I have an array of bitmaps which need compiling into a single, multi-page tiff image, however when saving the bitmap to a MemoryStream object I get the "Parameter is invalid" error message with no other detail.
The problem code:
private static MemoryStream convertToStream(Bitmap b)
{
using (MemoryStream ms = new MemoryStream())
{
b.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
return ms;
}
}
The bitmaps are in 600x600 DPI with an average of 35 pages (equating to 35 bitmaps)
What I have tried: I have confirmed the bitmap array contains the expected contents by saving them to disk
Any help is appreciated.
Stack trace: at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) at System.Drawing.Image.Save(Stream stream, ImageFormat format) at ConfigureTiffDPI.Program.convertToStream(Bitmap b) in C:\Users<user>\source\repos\ConfigureTiffDPI\ConfigureTiffDPI\Program.cs:line 37 at ConfigureTiffDPI.Program.CompileBitmaps(Bitmap[] bitmaps) in C:\Users<user>\source\repos\ConfigureTiffDPI\ConfigureTiffDPI\Program.cs:line 44 at ConfigureTiffDPI.Program.Main(String[] args) in C:\Users<user>\source\repos\ConfigureTiffDPI\ConfigureTiffDPI\Program.cs:line 29
[EDIT] Given the comments I have edited the code as such:
MemoryStream ms = new MemoryStream();
b.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
return ms;
However the error still persists
It's not possible to know why calling Save(stream) fails without knowing what the bitmap object contains exactly. But in general, to save multi-page TIFF, you need to call System.Drawing.Image.Save()
once, followed by repeated calls to SaveAdd
. The approach is the same whether you're saving to disk file or to memory stream.
There's a code sample from Microsoft on this page that saves 3 pages to a TIFF file on disk. I changed the first parameter of multi.Save()
from "Multiframe.tiff" to ms
, which is the MemoryStream, and the code produced a valid multi-page TIFF in the stream. Here's the modified code:
Bitmap multi;
Bitmap page2;
Bitmap page3;
ImageCodecInfo myImageCodecInfo = null;
Encoder myEncoder;
EncoderParameter myEncoderParameter;
EncoderParameters myEncoderParameters;
// Create three Bitmap objects. imageFiles is a list of strings holding file names
multi = new Bitmap(imageFiles[0]);
page2 = new Bitmap(imageFiles[1]);
page3 = new Bitmap(imageFiles[2]);
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (j = 0; j < encoders.Length; ++j)
if (encoders[j].MimeType == "image/tiff"/*mimeType*/)
{
myImageCodecInfo = encoders[j];
break;
}
myEncoder = Encoder.SaveFlag;
myEncoderParameters = new EncoderParameters(1);
myEncoderParameter = new EncoderParameter(myEncoder, (long)EncoderValue.MultiFrame);
myEncoderParameters.Param[0] = myEncoderParameter;
multi.Save(ms, myImageCodecInfo, myEncoderParameters);
// Save the second page (frame).
myEncoderParameter = new EncoderParameter(myEncoder, (long)EncoderValue.FrameDimensionPage);
myEncoderParameters.Param[0] = myEncoderParameter;
multi.SaveAdd(page2, myEncoderParameters);
// Save the third page (frame).
myEncoderParameter = new EncoderParameter(myEncoder, (long)EncoderValue.FrameDimensionPage);
myEncoderParameters.Param[0] = myEncoderParameter;
multi.SaveAdd(page3, myEncoderParameters);
// Close the multiple-frame file.
myEncoderParameter = new EncoderParameter(myEncoder, (long)EncoderValue.Flush);
myEncoderParameters.Param[0] = myEncoderParameter;
multi.SaveAdd(myEncoderParameters);
Another option to save multi-page TIFF to a stream is to use a professional imaging SDK like LEADTOOLS. (Disclosure: I work for its vendor). The code to load a list of images and save them into a TIFF stream is simply this:
using (RasterCodecs codecs = new RasterCodecs())
foreach (string imageFile in imageFiles) // list of strings holding file names
{
RasterImage imagePage = codecs.Load(imageFile);
ms.Position = 0; //rewind the memory stream to the start
codecs.Save(imagePage, ms, RasterImageFormat.TifLzw, 24, 1, 1, -1, CodecsSavePageMode.Append);
}
Another advantage of using this SDK is the flexibility and added features. For example, to change the compression used for any page in the TIFF, replace RasterImageFormat.TifLzw
with a different other value such as RasterImageFormat.TifJpeg411
or RasterImageFormat.CcittGroup4
to save using JPEG or FaxG4 compression, respectively. If you would like to try LEADTOOLS, There's a free evaluation here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.