Still playing with bitmap images

  • Thread starter Thread starter Earl
  • Start date Start date
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();
 
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
 
Thanks Kevin, I'd already read most of Bob's stuff and I didn't find
anything directly on point.
 
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);
 
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.
 
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.
 
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.
 
Back
Top