So I have been able to take a multi-page TIFF file and convert it to a single jpeg image but it flattens the TIFF. By flatten it, I mean it only returns the first page. The goal is to retrieve the TIFF (via memory stream), open each page of the TIFF and append it to a new jpeg (or any web image). Thus creating one long image to view on the web without the aid of a plugin. I do have the MODI.dll installed but I am not sure how to use it in this instance but it is an option.
Source Code (using a FileHandler):
#region multi-page tiff to single page jpeg
var byteFiles = dfSelectedDocument.File.FileBytes; // <-- FileBytes is a byte[] or byte array source.
byte[] jpegBytes;
using( var inStream = new MemoryStream( byteFiles ) )
using( var outStream = new MemoryStream() ) {
System.Drawing.Image.FromStream( inStream ).Save( outStream, ImageFormat.Jpeg );
jpegBytes = outStream.ToArray();
}
context.Response.ContentType = "image/JPEG";
context.Response.AddHeader( "content-disposition",
string.Format( "attachment;filename=\"{0}\"",
dfSelectedDocument.File.FileName.Replace( ".tiff", ".jpg" ) )
);
context.Response.Buffer = true;
context.Response.BinaryWrite( jpegBytes );
#endregion
have you compressed the jpeg?
https://msdn.microsoft.com/en-us/library/bb882583(v=vs.110).aspx
I'm guessing that you'll have to loop over each frame in the TIFF.
Here's an excerpt from Split multi page tiff file:
private void Split(string pstrInputFilePath, string pstrOutputPath)
{
//Get the frame dimension list from the image of the file and
Image tiffImage = Image.FromFile(pstrInputFilePath);
//get the globally unique identifier (GUID)
Guid objGuid = tiffImage.FrameDimensionsList[0];
//create the frame dimension
FrameDimension dimension = new FrameDimension(objGuid);
//Gets the total number of frames in the .tiff file
int noOfPages = tiffImage.GetFrameCount(dimension);
ImageCodecInfo encodeInfo = null;
ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < imageEncoders.Length; j++)
{
if (imageEncoders[j].MimeType == "image/tiff")
{
encodeInfo = imageEncoders[j];
break;
}
}
// Save the tiff file in the output directory.
if (!Directory.Exists(pstrOutputPath))
Directory.CreateDirectory(pstrOutputPath);
foreach (Guid guid in tiffImage.FrameDimensionsList)
{
for (int index = 0; index < noOfPages; index++)
{
FrameDimension currentFrame = new FrameDimension(guid);
tiffImage.SelectActiveFrame(currentFrame, index);
tiffImage.Save(string.Concat(pstrOutputPath, @"\", index, ".TIF"), encodeInfo, null);
}
}
}
You should be able to adapt the logic above to append onto your JPG rather than create separate files.
In case you get the dreadful "A generic error occurred in GDI+" error (which is arguably the Rickroll of all errors) when using the SelectActiveFrame
method suggested in the other answers, I strongly suggest to use the System.Windows.Media.Imaging.TiffBitmapDecoder
class instead (you will need to add a Reference to the PresentationCore.dll
framework library).
Here's an example code that does just that (it puts all the TIFF frames into a list of standard Bitmaps):
List<System.Drawing.Bitmap> bmpLst = new List<System.Drawing.Bitmap>();
using (var msTemp = new MemoryStream(data))
{
TiffBitmapDecoder decoder = new TiffBitmapDecoder(msTemp, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
int totFrames = decoder.Frames.Count;
for (int i = 0; i < totFrames; ++i)
{
// Create bitmap to hold the single frame
System.Drawing.Bitmap bmpSingleFrame = BitmapFromSource(decoder.Frames[i]);
// add the frame (as a bitmap) to the bitmap list
bmpLst.Add(bmpSingleFrame);
}
}
And here's the BitmapFromSource
helper method:
public static Bitmap BitmapFromSource(BitmapSource bitmapsource)
{
Bitmap bitmap;
using (var outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
bitmap = new Bitmap(outStream);
}
return bitmap;
}
For further info regarding this workaround, I also suggest to read this blog post I wrote.