【问题标题】:Convert BMP to TIFF using System.Drawing.Common on Mac OS X在 Mac OS X 上使用 System.Drawing.Common 将 BMP 转换为 TIFF
【发布时间】:2020-08-27 15:12:39
【问题描述】:

我正在尝试使用System.Drawing.Common 在 Mac 操作系统上使用以下 C# 代码 (.NET CORE 3.1) 将 BMP 图像转换为 tiff 图像:

        public void SaveBitmapAsTiff(string location, Bitmap image)
        {

            var imageCodecInfo = GetEncoderInfo("image/tiff");
            var encoder = Encoder.Compression;
            var encoderParameters = new EncoderParameters(1);
            
            var encoderParameter = new EncoderParameter(
                encoder,
                (long)EncoderValue.CompressionLZW);
            encoderParameters.Param[0] = encoderParameter;
            location = location.Replace(".bmp", "");
            image.Save(location + ".tiff", imageCodecInfo, encoderParameters);
            // image.Save(location + ".tiff", ImageFormat.Tiff); Also tried this method overload
        }
        
        private static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            int j;
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
            for(j = 0; j < encoders.Length; ++j)
            {
                if(encoders[j].MimeType == mimeType)
                    return encoders[j];
            }
            return null;
        }

location 参数包含我们要写入的文件路径,image 参数包含我们从磁盘加载的位图。

当我尝试运行此代码时,出现以下异常:

Unhandled exception. System.NotImplementedException: Not implemented.
   at System.Drawing.SafeNativeMethods.Gdip.CheckStatus(Int32 status)
   at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
   at System.Drawing.Image.Save(String filename, ImageFormat format)
   at BmpTiffConverter.Services.FileService.SaveBitmapAsTiff(String location, Bitmap image) in /Users/tomcoldenhoff/Documents/ReSoftware/Repositories/BmpTiffConverter/BmpTiffConverter/Services/FileService.cs:line 54
   at BmpTiffConverter.Services.ConverterService.ConvertBmpToTiff(String inputPath, String outputPath) in /Users/tomcoldenhoff/Documents/ReSoftware/Repositories/BmpTiffConverter/BmpTiffConverter/Services/ConverterService.cs:line 20

我的谷歌搜索表明我必须安装 libgdiplus,我已经用 brew install mono-libgdiplusbrew upgrade mono-libgdiplus 安装了。

我还通过安装runtime.osx.10.10-x64.CoreCompat.System.Drawing 软件包尝试了@Andy 的建议答案,不幸的是这不起作用。

有人有其他建议吗?

【问题讨论】:

  • 您使用的是哪个 dotnet 核心版本?
  • @TreviAwater 我正在使用 3.1,我也编辑了帖子
  • 我可以成功调用 Save 但不能为多个帧调用 SaveAdd ......我似乎无法弄清楚。
  • 这个问题帮我解决了错误the type initializer for 'gdip' threw an exception

标签: c# macos .net-core tiff bmp


【解决方案1】:

问题是mono-libgdiplus 没有实现EncoderValue.CompressionLZW 编码器参数。我建议不要使用那个库,而是安装这个 nuget 包:

runtime.osx.10.10-x64.CoreCompat.System.Drawing

一旦我添加了那个包,你的代码就完美运行了。

【讨论】:

  • 嗨@Andy,感谢您的回复。我试过安装你建议的 NuGet 包,不幸的是异常仍然存在。
  • @TomColdenhoff -- 我会开始一个新项目并尝试一下。我在我的 Mac 上对其进行了测试,没有任何问题。
  • 创建一个新项目并没有解决问题,可能是我的 Mac 设备的问题,因为你说它在你的机器上工作。我将在今天晚些时候在另一台 Mac 设备上试用它,并及时更新。
  • 在另一台 Mac 机器上运行它并且它工作正常。感谢您的回复。
【解决方案2】:

很遗憾,我没有要测试的 Mac。我使用 DotNet Core 3.1 在 Windows 和 Ubuntu 20 上测试了您的代码,您的代码似乎可以正常工作。我只能猜测这与您如何创建或修改您的 Bitmap 可能有关。

以下是我在 Linux 下创建项目的方式。 dotnet add package 是我添加 System.Drawing.Common NuGet 包的方式。我不确定它在 Mono 上是如何工作的,或者您是否正在使用 Mono。

> dotnet new console
> dotnet add package System.Drawing.Common
> dotnet restore

我编辑了program.cs

> dotnet build
> dotnet run

它运行得非常好。我现在可以在任何图像查看器中打开 tiff 图像。

从代码风格的角度来看,我建议进行很多更改。我知道您遵循了 MSDN 的代码示例,但就目前而言,他们的示例在这种情况下并不是很清楚。我刚刚复制并粘贴了整个 .cs 文件,并将 cmets 添加到各种修改中。编写清晰的代码与编写工作代码一样重要。

using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;

class Program
{
    // made the function more generic Bitmap inherits from Image and Image contains
    // the save feature so it might as well be made more general
    public static void SaveImageAsTiff(string location, Image image)
    {
        // fetch tiffCodec
        var tiffCodec = ImageCodecInfo
            .GetImageEncoders()
            .Where(info => info.MimeType == "image/tiff")
            .First();

        // create encoderParameters
        // this structure is much clearer IMO
        // (Can you see that there is now a color depth parameter?)
        var encoderParameters = new EncoderParameters(2) 
        {
            Param = new EncoderParameter[]{
                new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW),
                new EncoderParameter(Encoder.ColorDepth, 24L)
            }
        };

        // save image using codec and encoder parameters
        // it is common behavior to just save the file with the given location parameter 
        // and not to try do some extension conversion
        image.Save(location, tiffCodec, encoderParameters);
    }

    static void Main(string[] args)
    {
        // original bitmap location
        // (Yes forward slashes work on Windows so relative file paths are simple to handle)
        string bmpLocation = @"C:/Images/test.bmp";
        //string bmpLocation = @"~/Images/test.bmp"; // test on Linux

        // tidy way to convert file extensions of a path in C#
        string tiffLocation = System.IO.Path.ChangeExtension(bmpLocation, "tiff");

        // open image and force it to be a bitmap for examples sakes
        Bitmap bmpImage = new Bitmap(Image.FromFile(bmpLocation));

        // save image as tiff
        SaveImageAsTiff(tiffLocation, bmpImage);
    }
}

【讨论】:

  • 嗨@Kwiksilver,感谢您的回复。不幸的是,您的回答对我不起作用。
猜你喜欢
  • 2016-10-13
  • 2010-12-11
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-24
  • 1970-01-01
  • 2012-02-29
相关资源
最近更新 更多