【问题标题】:Cannot save TIF file using GDI+无法使用 GDI+ 保存 TIF 文件
【发布时间】:2019-11-09 21:24:06
【问题描述】:

我有一个选择和加载 JPG 文件的 vb.net 应用程序

 LoadedImage = Image.FromFile(InputImageName)

然后尝试使用 GDI+ 将文件另存为 TIF

 LoadedImage.Save(TIF_ImageName, ImageFormat.Tiff)

没有语法错误,但保存失败

System.InvalidCastException was unhandled
Message=Conversion from string "System.Runtime.InteropServices.E" to type 'Integer' is not valid.

我尝试过使用位图而不是图像,没有乐趣 图像很大(9000x11000 像素) 这是encoderparams 的问题吗?也许没有默认值?可用的样本是用于双色调图像的。

最后,我将使用位置数据生成新的 TIF 标签,因此这是开发中的一个临时步骤。

【问题讨论】:

    标签: vb.net gdi tiff


    【解决方案1】:

    尝试使用ImageCodecInfo 类,它提供了控制用于对图像格式进行编码的编解码器参数的方法。

    在 GDI+ 中,您可以指定数量非常有限的参数。在实践中,只有Compression 方法和Quality 级别决定了压缩级别(0-100,其中0 是最大压缩)。

    这些参数组装EncoderParameters 对象的EncoderParameter 数组中 - 用于指定Encoder 主题 - 在将它们传递给接受 Image.Save() 重载之前>ImageCodecInfoEncoderParameters 作为参数。

    示例方法调用
    将源图像保存为 TIFF 格式,使用相同的 DPI 设置,压缩级别设置为 50%。图片保存为24bpp RGB格式。根据需要进行修改。
    压缩类型为LZW

    Dim jpgImage As Image = Image.FromFile("ImageFile.jpg"), True)
    SaveTiffImage(jpgImage, jpgImage.VerticalResolution, 50L, "DestinationFile.tif")
    jpgImage.Dispose()
    

    编解码器初始化方法

    Imports System.Drawing
    Imports System.Drawing.Imaging
    Imports ImageCodec = System.Drawing.Imaging.Encoder
    
    Private Sub SaveTiffImage(image As Image, resolution As Single, compressionLevel As Long, fileName As String)
        resolution = Math.Max(72, Math.Min(2400, resolution))
        compressionLevel = Math.Max(0, Math.Min(100, compressionLevel))
    
        Using bitmap = New Bitmap(image.Width, image.Height, PixelFormat.Format24bppRgb)
            bitmap.SetResolution(resolution, resolution)
            Using g = Graphics.FromImage(bitmap)
                g.DrawImage(image, New Rectangle(Point.Empty, image.Size),
                                   New Rectangle(Point.Empty, image.Size), GraphicsUnit.Pixel)
                Dim codec = ImageCodecInfo.GetImageEncoders().
                            FirstOrDefault(Function(enc) enc.FormatID = ImageFormat.Tiff.Guid)
                Dim qualityParam =
                    New EncoderParameter(ImageCodec.Quality, compressionLevel)
                Dim compressionParam =
                    New EncoderParameter(ImageCodec.Compression, EncoderValue.CompressionLZW)
                Using codecParms = New EncoderParameters(2)
                    codecParms.Param(0) = qualityParam
                    codecParms.Param(1) = compressionParam
                    bitmap.Save(fileName, codec, codecParms)
                End Using
            End Using
        End Using
    End Sub
    

    C# 版本

    using System.Drawing;
    using System.Drawing.Imaging;
    using ImageCodec = System.Drawing.Imaging.Encoder;
    
    private void SaveTiffImage(Image image, float resolution, long compressionLevel, string fileName)
    {
        resolution = Math.Max(72, Math.Min(2400, resolution));
        compressionLevel = Math.Max(0, Math.Min(100, compressionLevel));
    
        using (var bitmap = new Bitmap(image.Width, image.Height, PixelFormat.Format24bppRgb))
        {
            bitmap.SetResolution(resolution, resolution);
            using (var g = Graphics.FromImage(bitmap))
            {
                g.DrawImage(image, new Rectangle(Point.Empty, image.Size), 
                                   new Rectangle(Point.Empty, image.Size), GraphicsUnit.Pixel);
                var imageCodec = ImageCodecInfo.GetImageEncoders()
                                    .FirstOrDefault(enc => enc.FormatID == ImageFormat.Tiff.Guid);
                if (imageCodec == null)
                    throw new NotSupportedException("TIFF Conversion not suppoted", 
                          new NullReferenceException("TIFF Codec reference missing"));
                var qualityParam = 
                    new EncoderParameter(ImageCodec.Quality, compressionLevel);
                var compressionParam = 
                    new EncoderParameter(ImageCodec.Compression, (long)EncoderValue.CompressionLZW);
                using (var codecParms = new EncoderParameters(2))
                {
                    codecParms.Param[0] = qualityParam;
                    codecParms.Param[1] = compressionParam;
                    bitmap.Save(fileName, imageCodec, codecParms);
                }
            }
        }
    }
    

    【讨论】:

    • 您好,谢谢!需要进行一些更改才能消除错误 - 修改了 2 行 Dim qualityParam = New EncoderParameter(Encoder.Quality, compressionLevel) Dim compressionParam = New EncoderParameter(Encoder.Compression, EncoderValue.CompressionLZW)
    • 为什么这个:Imports ImageCodec = System.Drawing.Imaging.Encoder 会产生错误?这是一个标准的Imports 修改,以避免与使用相同名称的其他命名空间/类发生冲突。在这种情况下,Text.Encoder 命名空间。您使用的是什么版本的 Visual Studio?
    • 嗨 Jimi - 这可能是问题吗?这里有 3 个变化。 . . Imports ImageCodec = System.Drawing.Imaging.Encoder - VS 说不需要,但是引用 ImageCodec 的 2 行被修改为使用 encoder.Quality 和 Encoder.Compression (Dim qualityParam = New EncoderParameter(encoder.Quality, compressionLevel) Dim compressionParam = New EncoderParameter(encoder.Compression, EncoderValue.CompressionLZW))
    • Visual Studio 说什么并不重要。该 Import 是必需的,您可以保持原样。 ImageCodecSystem.Drawing.Imaging.Encoder,最好保留原样,因为您可能还需要对 System.Text 的引用(它也有一个 Encoder 类),并且此设置避免了在导入两个命名空间时出现的冲突。我仍然不知道您是否能够转换图像。
    • 嗨,谢谢 - 问题是 VS2015 - 我切换到 VS2019(有点小悲伤)并将代码改回你的建议,瞧 - 得到了我的第一个 TIF!下一个任务是将位置数据添加为标签,以便 ArcMap 可以加载文件并使用 WGS84 正确显示它
    猜你喜欢
    • 1970-01-01
    • 2020-02-17
    • 2021-09-07
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 2021-03-19
    • 2013-08-30
    • 2014-11-11
    相关资源
    最近更新 更多