Я пытаюсь разделить и объединить многостраничное изображение в формате TIFF. Причина, по которой я разделяю, заключается в том, чтобы рисовать аннотации на каждом уровне изображения. Код работает нормально, однако объединенный TIFF довольно большой по сравнению с исходным TIFF. Например, я протестировал TIFF-изображение с 17 цветными страницами (размер 5 МБ), после разделения и слияния он создает TIFF-изображение размером 85 МБ. Я использую 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);
}