简体   繁体   中英

"Parameter is invalid" when saving Bitmap to MemoryStream

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM