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 に答える