首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >覆盖现有Jpeg文件/用已编辑的Jpeg文件替换现有jpeg文件

覆盖现有Jpeg文件/用已编辑的Jpeg文件替换现有jpeg文件
EN

Stack Overflow用户
提问于 2018-02-02 09:33:02
回答 1查看 1.6K关注 0票数 4

我已经构建了一个程序,允许我通过System.Image.Drawing插入注释和图片标题。所以现在,我很难用添加了注释和标题的Jpeg文件覆盖现有的Jpeg文件,但是我在删除文件时遇到了错误,所以我不知道该如何处理该文件,因为我已经尝试过处理该文件,但由于我处理得太早,所以无法保存它,但我无法保存它,因为现有的文件名没有被删除,所以我现在有点卡在中间。

这是我的密码:

代码语言:javascript
复制
public string EditComment(string OriginalFilepath, string newFilename)
{
       
    image = System.Drawing.Image.FromFile(OriginalFilepath);
    PropertyItem propItem = image.PropertyItems[0];
    using (var file = System.Drawing.Image.FromFile(OriginalFilepath))
    {
        propItem.Id = 0x9286;  // this is the id for 'UserComment'
        propItem.Type = 2;
        propItem.Value = System.Text.Encoding.UTF8.GetBytes("HelloWorld\0");
        propItem.Len = propItem.Value.Length;
        file.SetPropertyItem(propItem);
        PropertyItem propItem1 = file.PropertyItems[file.PropertyItems.Count() - 1];
        file.Dispose();
        image.Dispose();
        string filepath = Filepath;
        if (File.Exists(@"C:\Desktop\Metadata"))
        {
            System.IO.File.Delete(@"C:\Desktop\Metadata");
        }
        string newFilepath = filepath + newFilename;
        file.Save(newFilepath, ImageFormat.Jpeg);//error appears here
        return filepath;      
     }
}

显示的错误如下:

“System.ArgumentException”类型的异常发生在System.Drawing.dll中,但未在用户代码中处理 附加信息:参数无效。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-02 09:41:31

问题是从文件中打开图像会锁定文件。您可以通过将文件读入一个字节数组,创建一个内存流,然后从该流打开图像来解决这个问题:

代码语言:javascript
复制
public string EditComment(string originalFilepath, string newFilename)
{
    Byte[] bytes = File.ReadAllBytes(originalFilepath);
    using (MemoryStream stream = new MemoryStream(bytes))
    using (Bitmap image = new Bitmap(stream))
    {
        PropertyItem propItem = image.PropertyItems[0];
        // Processing code
        propItem.Id = 0x9286;  // this is the id for 'UserComment'
        propItem.Type = 2;
        propItem.Value = System.Text.Encoding.UTF8.GetBytes("HelloWorld\0");
        propItem.Len = propItem.Value.Length;
        image.SetPropertyItem(propItem);
        // Not sure where your FilePath comes from but I'm just
        // putting it in the same folder with the new name.
        String newFilepath;
        if (newFilename == null)
            newFilepath = originalFilePath;
        else
            newFilepath = Path.Combine(Path.GetDirectory(originalFilepath), newFilename);
        image.Save(newFilepath, ImageFormat.Jpeg);
        return newFilepath;
    }
}

确保您的不像在测试代码中那样在using块中释放图像对象。不仅using块确实存在,因此不需要手动处理,而且还很难将映像保存到内存中不再存在的磁盘中。类似地,您似乎两次从文件中打开图像。我只是假设所有这些都是为了解决问题而做的实验,但一定要把它们清理干净。

打开图像时要记住的基本规则如下:

与一些人所认为的相反,对图像对象的基本.Clone()调用不会改变这种行为。克隆的对象仍然保留对原始源的引用。

注意,如果您实际上想要一个不包含在usingPixelFormat中的可用图像对象,那么有效地对原始图像进行完整的数据克隆。(注意:我认为这不适用于动画GIF文件)这样做后,您可以安全地释放原始文件,只需使用新的干净克隆版本。

实际上,还有一些其他的解决办法可以将图像取出来,但我看到的大多数方法都不是最优的。以下是解决锁定问题的两个最常见的有效解决方案:

  • 使用Bitmap构造函数从从文件加载的图像中创建新的Bitmap(Image image)。这个新对象将没有指向该文件的链接,因此您可以自由地释放锁定该文件的对象。这是完美的,但它将图像的颜色深度更改为32位的ARGB,这可能是不想要的。但是,如果您只需要在UI上显示一个图像,这是一个很好的解决方案。
  • 如我的代码所示,创建一个MemoryStream,而不是在using块中创建,使流按需要打开。让溪流开放对我来说并不是个好主意。虽然有人说过,由于MemoryStream只是由一个简单的数组而不是外部资源支持,垃圾收集器显然可以很好地处理这种情况.

我还看到一些人使用System.Drawing.ImageConverter从字节进行转换,但是我调查了这个过程的内部,它所做的实际上与这里的最后一个方法相同,该方法保留了一个内存流。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48579643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档