简体   繁体   English

如何使用C#正确创建缩略图?

[英]How to correctly create a thumbnail using C#?

I have a console application written using C# on the top of Core .NET 2.2 framework. 我在Core .NET 2.2框架的顶部有一个使用C#编写的控制台应用程序。

I want to create asynchronous Task that would write a full-size image to storage. 我想创建异步任务,该任务会将完整大小的图像写入存储。 Additionally, the process will need to create a thumbnail and write it to the default storage. 此外,该过程将需要创建缩略图并将其写入默认存储。

Follow is the method that processes the logic. 遵循的是处理逻辑的方法。 I documented each line to explain that I believe is happening 我记录了每一行以解释我相信正在发生

// This method accepts FileObject and returns a task
// The generated task will write the file as is to the default storage
// Then it'll create a thumbnail of that images and store it to the default storage
public async Task ProcessImage(FileObject file, int thumbnailWidth = 250)
{
    // The name of the full-size image
    string filename = string.Format("{0}{1}", file.ObjectId, file.Extension);

    // The name along with the exact path to the full-size image
    string path = Path.Combine(file.ContentId, filename);

    // Write the full-size image to the storage
    await Storage.CreateAsync(file.Content, path)
                 .ContinueWith(task =>
    {
        // Reset the stream to the beginning since this will be the second time the stream is read
        file.Content.Seek(0, SeekOrigin.Begin);

        // Create original Image
        Image image = Image.FromStream(file.Content);

        // Calulate the height of the new thumbnail
        int height = (thumbnailWidth * image.Height) / image.Width;

        // Create the new thumbnail
        Image thumb = image.GetThumbnailImage(thumbnailWidth, height, null, IntPtr.Zero);

        using (MemoryStream thumbnailStream = new MemoryStream())
        {
            // Save the thumbnail to the memory stream
            thumb.Save(thumbnailStream, image.RawFormat);

            // The name of the new thumbnail
            string thumbnailFilename = string.Format("thumbnail_{0}", filename);

            // The name along with the exact path to the thumbnail
            string thumbnailPath = Path.Combine(file.ContentId, thumbnailFilename);

            // Write the thumbnail to storage
            Storage.CreateAsync(thumbnailStream, thumbnailPath);
        }

        // Dispose the file object to ensure the Stream is disposed
        file.Dispose();
        image.Dispose();
        thumb.Dispose();
    });
}

Here is my FileObject if needed 如果需要,这是我的FileObject

public class FileObject : IDisposable
{
    public string ContentId { get; set; }
    public string ObjectId { get; set; }
    public ContentType ContentType { get; set; }
    public string Extension { get; set; }
    public Stream Content { get; set; }
    private bool IsDisposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (IsDisposed)
            return;

        if (disposing && Content != null)
        {
            Content.Close();
            Content.Dispose();
        }

        IsDisposed = true;
    }
}

The above code writes the correct full-size image to the storage drive. 上面的代码将正确的全尺寸图像写入存储驱动器。 It also writes the thumbnail to storage. 它还会将缩略图写入存储。 However, the thumbnail is always corrupted. 但是,缩略图始终会损坏。 In other words, the generated thumbnail file is always written with 0 bytes. 换句话说,生成的缩略图文件始终以0字节写入。

How can I correctly create my thumbnail from file.Content stream after writing the same stream to the storage? 将相同的流写入存储后,如何从file.Content流正确创建缩略图?

I figured out the cause of the issue. 我找出问题的原因。 For some reason the line thumb.Save(thumbnailStream, image.RawFormat); 由于某种原因,行thumb.Save(thumbnailStream, image.RawFormat); position the thumbnailStream at the end and when writing to the storage nothing gets written thumbnailStream放置在末尾,并且在写入存储时不会写入任何内容

Fixing that issues was to reset the seek position after writing to the stream like this 解决该问题的方法是在像这样写入流后重置搜索位置

    using (MemoryStream thumbnailStream = new MemoryStream())
    {
        // Save the thumbnail to the memory stream
        thumb.Save(thumbnailStream, image.RawFormat);

        // Reset the seek position to the begining
        thumbnailStream.Seek(0, SeekOrigin.Begin);

        // The name of the new thumbnail
        string thumbnailFilename = string.Format("thumbnail_{0}", filename);

        // The name along with the exact path to the thumbnail
        string thumbnailPath = Path.Combine(file.ContentId, thumbnailFilename);

        // Write the thumbnail to storage
        Storage.CreateAsync(thumbnailStream, thumbnailPath);
    }

I am not sure what is the benefit that is gained when thumb.Save(...) does not reset the position to 0 after copying into a new stream! 我不确定在复制到新流中后thumb.Save(...)不会将位置重置为0会有什么好处! I just feel that it should be doing that since it will always write a new stream not appending to an existing one. 我只是觉得应该这样做,因为它将始终编写一个新的流,而不是将其追加到现有的流之后。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM