0

Я пытаюсь разделить и слить многостраничное изображение tiff. Причина, по которой я разделяю, - рисовать аннотации на каждом уровне изображения. Код работает нормально, однако объединенный tiff довольно большой по сравнению с исходным tiff. Например, я тестировал с 17 цветными страницами tiff image (размер 5 МБ), после расщепления и слияния, он создает 85MB tiff изображение. Я использую BitMiracle.LibTiff.I фактически прокомментировал временной код аннотации, чтобы решить проблему с этим размером, я не уверен, что я делаю неправильно. Вот код для разделения.Размер байт изображения увеличивается после сплита и слияния файла Tiff

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); 
} 
+1

Пожалуйста, разместите ссылки на образец до и после изображений, и я смогу рассказать вам, почему размеры настолько разные. Вероятно, это связано с субоптимальным методом/параметрами кодирования. – BitBank

+0

Как отправить изображения вам? Можете ли вы отправить тестовое письмо на [email protected], чтобы я мог отправлять изображения? –

ответ

1

Скорее всего, проблема вызвана тем фактом, вы превращающие все изображения до 32 бит на пиксель растровые изображения.

Предположим, у вас есть черно-белое факсимильное изображение. Он может быть закодирован как файл TIFF на 100 Кбайт. Такое же изображение может занять 10 мегабайт, если вы сохраните его как 32-битное растровое изображение. Сжатие этих мегабайт поможет, но вы никогда не достигнете того же коэффициента сжатия, что и в исходном изображении, потому что вы увеличили количество данных изображения с 1 бит на пиксель до 32 бит на пиксель.

Таким образом, вы не должны преобразовывать изображения в растровые изображения 32bpp, если это возможно. По возможности старайтесь сохранить свои свойства и сжатие. Посмотрите исходный код утилиты TiffCP для подсказок, как это сделать.

Если вам абсолютно необходимо преобразовать изображения в растровые изображения 32bpp (возможно, вам придется добавить к ним красочные аннотации), то для уменьшения результирующего размера не так много можно сделать. Вы можете уменьшить выходной размер на 10-20% процентов, если вы выберете лучшую схему сжатия и настройте схему правильно. Боюсь, это все.

+0

Спасибо. Мне не нужно сохранять как 32bpp bitmap ... как изменить код выше, чтобы использовать наименьшие бит на пиксель? –

+0

@HariNarisetty Использовать исходный код утилиты TiffCp как начало. – Bobrovsky