0

我正在尝试拆分和合并多页 tiff 图像。我拆分的原因是在每个图像级别绘制注释。代码运行良好,但是与源 tiff 相比,合并的 tiff 相当大。例如,我用 17 个彩色页面的 tiff 图像(大小为 5MB)进行了测试,经过拆分和合并,它产生了 85MB 的 tiff 图像。我正在使用 BitMiracle.LibTiff。我实际上也临时注释了注释代码来解决这个大小问题,我不确定我做错了什么。这是要拆分的代码。

private List<Bitmap> SplitTiff(byte[] imageData)
{
    var bitmapList = new List<Bitmap>();
    var tiffStream = new TiffStreamForBytes(imageData);

    //open tif file
    var tif = Tiff.ClientOpen("", "r", null, tiffStream);

    //get number of pages
    var num = tif.NumberOfDirectories();
    if (num == 1) 
        return new List<Bitmap> 
        { 
            new Bitmap(GetImage(imageData)) 
        };

    for (short i = 0; i < num; i++)
    {
         //set current page
         tif.SetDirectory(i);
         FieldValue[] photoMetric = tif.GetField(TiffTag.PHOTOMETRIC);
         Photometric photo = Photometric.MINISBLACK;
         if (photoMetric != null && photoMetric.Length > 0)
             photo = (Photometric)photoMetric[0].ToInt();

         if (photo != Photometric.MINISBLACK && photo != Photometric.MINISWHITE)
             bitmapList.Add(GetBitmapFromTiff(tif));
         // else
             // bitmapList.Add(GetBitmapFromTiffBlack(tif, photo));// commented temporrarly to fix size issue
     }
     return bitmapList;
}

private static Bitmap GetBitmapFromTiff(Tiff tif)
{
    var value = tif.GetField(TiffTag.IMAGEWIDTH);
    var width = value[0].ToInt();

    value = tif.GetField(TiffTag.IMAGELENGTH);
    var height = value[0].ToInt();

    //Read the image into the memory buffer
    var raster = new int[height * width];
    if (!tif.ReadRGBAImage(width, height, raster))
    {
        return null;
    }

    var bmp = new Bitmap(width, height, PixelFormat.Format32bppRgb);

    var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

    var bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
    var bits = new byte[bmpdata.Stride * bmpdata.Height];

    for (var y = 0; y < bmp.Height; y++)
    {
        int rasterOffset = y * bmp.Width;
        int bitsOffset = (bmp.Height - y - 1) * bmpdata.Stride;

        for (int x = 0; x < bmp.Width; x++)
        {
            int rgba = raster[rasterOffset++];
            bits[bitsOffset++] = (byte)((rgba >> 16) & 0xff);
            bits[bitsOffset++] = (byte)((rgba >> 8) & 0xff);
            bits[bitsOffset++] = (byte)(rgba & 0xff);
            bits[bitsOffset++] = (byte)((rgba >> 24) & 0xff);
         }
    }

    System.Runtime.InteropServices.Marshal.Copy(bits, 0, bmpdata.Scan0, bits.Length);
    bmp.UnlockBits(bmpdata);

    return bmp;
}

并且将单个位图合并到 tiff 的代码在这里...

public static PrizmImage PrizmImageFromBitmaps(List<Bitmap> imageItems, string ext)
{
     if (imageItems.Count == 1 && !(ext.ToLower().Equals(".tif") || ext.ToLower().Equals(".tiff")))
         return new PrizmImage(new MemoryStream(ImageUtility.BitmapToByteArray(imageItems[0])), ext);

     var codecInfo = GetCodecInfo();
     var memoryStream = new MemoryStream();

     var encoderParams = new EncoderParameters(1);
     encoderParams.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);

     var initialImage = imageItems[0];
     var masterBitmap = imageItems[0];// new Bitmap(initialImage);
     masterBitmap.Save(memoryStream, codecInfo, encoderParams);
     encoderParams.Param[0] = new EncoderParameter(Encoder.SaveFlag,  (long)EncoderValue.FrameDimensionPage);

     for (var i = 1; i < imageItems.Count; i++)
     {
          var img = imageItems[i];
          masterBitmap.SaveAdd(img, encoderParams);
          img.Dispose();
     }

     encoderParams.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.Flush);
     masterBitmap.SaveAdd(encoderParams);

     memoryStream.Seek(0, SeekOrigin.Begin);
     encoderParams.Dispose();
     masterBitmap.Dispose();
     return new PrizmImage(memoryStream, ext);
}
4

1 回答 1

1

很可能,问题是由于您将所有图像转换为每像素 32 位的位图这一事实引起的。

假设您有一张黑白传真编码的图像。它可能被编码为 100 Kb TIFF 文件。当您将其保存为 32bpp 位图时,相同的图像可能需要 10 多兆字节。压缩这些兆字节会有所帮助,但您永远无法获得与源图像相同的压缩率,因为您将图像数据量从每像素 1 位增加到每像素 32 位

因此,如果可能,您不应将图像转换为 32bpp 位图。尽量保留它们的属性和压缩。查看 TiffCP 实用程序的源代码以获取如何执行此操作的提示。

如果您绝对必须将图像转换为 32bpp 位图(如果向它们添加彩色注释,则可能必须这样做),那么就没有什么可以做的来减小结果大小。如果您选择更好的压缩方案并正确调整方案,您可能会将输出大小减少 10-20%。但这就是全部,我害怕。

于 2014-01-07T18:07:44.413 回答