Still playing with bitmap images

E

Earl

I have an image issue that I do not understand. When I try to save a bitmap
created from a picturebox image, I can save without exception so long as the
bitmap was retrieved from a file and loaded into the picturebox. But if I
load the image from the database into the picturebox and try to save
(without change), I then get a null exception telling me that the encoder
parameter is null. I'm speculating that the file provides the encoder param
but the database image does not. What do I need to know to resolve this?

int intWidth = pb.Width;
int intHeight = pb.Height;
Bitmap bmp = new Bitmap(pb.Image, intWidth, intHeight);
MemoryStream ms = new MemoryStream();
bmp.Save(ms, pb.Image.RawFormat);
arrayImage = ms.GetBuffer();
ms.Close();
 
M

Marc Gravell

At what point (in that sample) does the error occur? I don't know if it
is related, but you might wish to use either ms.ToArray(), or read
ms.Length before closing the stream, as ms.GetBuffer() will return
random data (probably all 0s) from the end of the oversized buffer that
MemoryStream allocates.

If this arrayImage is what you are saving to the database and then
reloading, then this could explain the errors, as the "image" contains
garbage at the end.

Marc
 
E

Earl

Thanks Kevin, I'd already read most of Bob's stuff and I didn't find
anything directly on point.
 
E

Earl

Have to use an ImageFormat instead of RawFormat. Apparently the file holds
the encoder params but those must be provided by the ImageFormat if saving
from the database or newly created bitmap.

bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
 
K

Kevin Spencer

Hi Earl,

Sorry about that. The answer is there, but not directly. It's in an article
about saving JPEGs with a specific compression
(http://www.bobpowell.net/jpeg_compression.htm). The EncoderParameters
array is included in 2 overloads of the base Image class Save method, in
your case, the overload that takes a stream as an argument:

System.Drawing.Image.Save(System.IO.Stream,
System.Drawing.Imaging.ImageCodecInfo,
System.Drawing.Imaging.EncoderParameters)
(http://msdn2.microsoft.com/en-gb/library/ms142148(VS.80).aspx)

The System.Drawing.Imaging.ImageCodecInfo class
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.imagecodecinfo(VS.80).aspx)
is easy to create, using the static ImageCodecInfo.GetEncoders method, and
using a MIME string. Here's a method that creates one:

public static ImageCodecInfo GetEncoderInfo(string mimeType)
{
int intCt;

ImageCodecInfo[] aryEncoders = ImageCodecInfo.GetImageEncoders();
for (intCt = 0; intCt < aryEncoders.Length; intCt++)
{
if (aryEncoders[intCt].MimeType == mimeType)
return aryEncoders[intCt];
}
throw new Exception("MimeType '" + mimeType + "' not found");
}

In the case of a BitMap, you would use "image/bmp" as the MIME string:

ImageCodeInfo codecInfo = GetEncoderInfo("image/bmp");

As to the EncoderParameters, the Encoder class
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoderparameter(VS.80).aspx)
provides a parameter for the image encoder used by the Save method, and you
can create and use any number of them. The constructor for EncoderParameter
usually takes an Encoder
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoder.encoder(VS.80).aspx)
and a value. There are a number of constructor overloads
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoder.encoder(VS.80).aspx)
to handle the different types of Encoders
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoder_members(VS.80).aspx)
available. The most commonly-used values for Encoders can be found in the
System.Drawing.Imaging.EncoderValue enumeration
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encodervalue(VS.80).aspx).

--
HTH,

Kevin Spencer
Microsoft MVP
Logostician
http://unclechutney.blogspot.com

Parabola is a mate of plane.
 
K

Kevin Spencer

I'm glad that worked for you, Earl. Keep the other information I gave you
(in my last reply) about ImageCodecInfo and EncoderParameters for future
reference!

--
HTH,

Kevin Spencer
Microsoft MVP
Logostician
http://unclechutney.blogspot.com

Parabola is a mate of plane.
 
E

Earl

Thanks for the links. I'm sure they will come in handy.

Kevin Spencer said:
Hi Earl,

Sorry about that. The answer is there, but not directly. It's in an
article about saving JPEGs with a specific compression
(http://www.bobpowell.net/jpeg_compression.htm). The EncoderParameters
array is included in 2 overloads of the base Image class Save method, in
your case, the overload that takes a stream as an argument:

System.Drawing.Image.Save(System.IO.Stream,
System.Drawing.Imaging.ImageCodecInfo,
System.Drawing.Imaging.EncoderParameters)
(http://msdn2.microsoft.com/en-gb/library/ms142148(VS.80).aspx)

The System.Drawing.Imaging.ImageCodecInfo class
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.imagecodecinfo(VS.80).aspx)
is easy to create, using the static ImageCodecInfo.GetEncoders method, and
using a MIME string. Here's a method that creates one:

public static ImageCodecInfo GetEncoderInfo(string mimeType)
{
int intCt;

ImageCodecInfo[] aryEncoders = ImageCodecInfo.GetImageEncoders();
for (intCt = 0; intCt < aryEncoders.Length; intCt++)
{
if (aryEncoders[intCt].MimeType == mimeType)
return aryEncoders[intCt];
}
throw new Exception("MimeType '" + mimeType + "' not found");
}

In the case of a BitMap, you would use "image/bmp" as the MIME string:

ImageCodeInfo codecInfo = GetEncoderInfo("image/bmp");

As to the EncoderParameters, the Encoder class
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoderparameter(VS.80).aspx)
provides a parameter for the image encoder used by the Save method, and
you can create and use any number of them. The constructor for
EncoderParameter usually takes an Encoder
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoder.encoder(VS.80).aspx)
and a value. There are a number of constructor overloads
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoder.encoder(VS.80).aspx)
to handle the different types of Encoders
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encoder_members(VS.80).aspx)
available. The most commonly-used values for Encoders can be found in the
System.Drawing.Imaging.EncoderValue enumeration
(http://msdn2.microsoft.com/en-gb/library/system.drawing.imaging.encodervalue(VS.80).aspx).

--
HTH,

Kevin Spencer
Microsoft MVP
Logostician
http://unclechutney.blogspot.com

Parabola is a mate of plane.



Earl said:
Thanks Kevin, I'd already read most of Bob's stuff and I didn't find
anything directly on point.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top