Image quality

  • Thread starter Thread starter JJ
  • Start date Start date
J

JJ

Whilst I am resizing images I am losing quality. This is only happening in
small amounts, but if you repeatedly put the same image through the
following code, the image quality slowly degrades. Can anyone spot why this
may be happening? Should it only deteriate once upon intitially going
through this procedure? The deterioration is subtle, but after a few
iterations is quite noticeable..:

private static System.Drawing.Image CopyImage(System.Drawing.Image
imageFile, int width, int height)

{

System.Drawing.Bitmap bmpOut;

ImageFormat Format = imageFile.RawFormat;

bmpOut = new Bitmap(width, height, PixelFormat.Format64bppPArgb);

bmpOut.SetResolution(imageFile.HorizontalResolution,
imageFile.VerticalResolution);

bmpOut.Palette = imageFile.Palette;

Graphics g = Graphics.FromImage(bmpOut);

g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

g.CompositingQuality =
System.Drawing.Drawing2D.CompositingQuality.HighQuality;


g.FillRectangle(Brushes.White, 0, 0, width, height);

g.DrawImage(imageFile, 0, 0, width, height);

imageFile.Dispose();

g.Dispose();

return bmpOut;



}



The image is then saved to disk using the following:

....

EncoderParameters encoderParameters;

encoderParameters = new EncoderParameters(1);

encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);

ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

NewImage.Save(HttpContext.Current.Server.MapPath(newImgPath), jgpEncoder,
encoderParameters);

NewImage.Dispose();

encoderParameters.Dispose();

....
 
Whilst I am resizing images I am losing quality. This is only happening in
small amounts, but if you repeatedly put the same image through the
following code, the image quality slowly degrades. Can anyone spot why this
may be happening?  Should it only deteriate once upon intitially going
through this procedure? The deterioration is subtle, but after a few
iterations is quite noticeable..:

private static System.Drawing.Image CopyImage(System.Drawing.Image
imageFile, int width, int height)

{

System.Drawing.Bitmap bmpOut;

ImageFormat Format = imageFile.RawFormat;

bmpOut = new Bitmap(width, height, PixelFormat.Format64bppPArgb);

bmpOut.SetResolution(imageFile.HorizontalResolution,
imageFile.VerticalResolution);

bmpOut.Palette = imageFile.Palette;

Graphics g = Graphics.FromImage(bmpOut);

g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

g.CompositingQuality =
System.Drawing.Drawing2D.CompositingQuality.HighQuality;

g.FillRectangle(Brushes.White, 0, 0, width, height);

g.DrawImage(imageFile, 0, 0, width, height);

imageFile.Dispose();

g.Dispose();

return bmpOut;

}

The image is then saved to disk using the following:

...

EncoderParameters encoderParameters;

encoderParameters = new EncoderParameters(1);

encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);

ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

NewImage.Save(HttpContext.Current.Server.MapPath(newImgPath), jgpEncoder,
encoderParameters);

NewImage.Dispose();

encoderParameters.Dispose();

...

Well, I think it depends on the original image. You should try to play
with the values to find better result. For example, I am always adding
an additional value to the EncoderParameter for LZW Compression, which
is basically a technique for lossless compression:

encoderParameters.Param[1] = new EncoderParameter(Encoder.Compression,
(long)EncoderValue.CompressionLZW);
 
Thanks Alexey.

I did just try that and it came up with an exception, but I'll looking a
little deeper into the 'encoder' area.
Thanks for the pointer,
JJ
Whilst I am resizing images I am losing quality. This is only happening in
small amounts, but if you repeatedly put the same image through the
following code, the image quality slowly degrades. Can anyone spot why
this
may be happening? Should it only deteriate once upon intitially going
through this procedure? The deterioration is subtle, but after a few
iterations is quite noticeable..:

private static System.Drawing.Image CopyImage(System.Drawing.Image
imageFile, int width, int height)

{

System.Drawing.Bitmap bmpOut;

ImageFormat Format = imageFile.RawFormat;

bmpOut = new Bitmap(width, height, PixelFormat.Format64bppPArgb);

bmpOut.SetResolution(imageFile.HorizontalResolution,
imageFile.VerticalResolution);

bmpOut.Palette = imageFile.Palette;

Graphics g = Graphics.FromImage(bmpOut);

g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

g.CompositingQuality =
System.Drawing.Drawing2D.CompositingQuality.HighQuality;

g.FillRectangle(Brushes.White, 0, 0, width, height);

g.DrawImage(imageFile, 0, 0, width, height);

imageFile.Dispose();

g.Dispose();

return bmpOut;

}

The image is then saved to disk using the following:

...

EncoderParameters encoderParameters;

encoderParameters = new EncoderParameters(1);

encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);

ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

NewImage.Save(HttpContext.Current.Server.MapPath(newImgPath), jgpEncoder,
encoderParameters);

NewImage.Dispose();

encoderParameters.Dispose();

...

Well, I think it depends on the original image. You should try to play
with the values to find better result. For example, I am always adding
an additional value to the EncoderParameter for LZW Compression, which
is basically a technique for lossless compression:

encoderParameters.Param[1] = new EncoderParameter(Encoder.Compression,
(long)EncoderValue.CompressionLZW);
 
Thanks Alexey.

I did just try that and it came up with an exception, but I'll looking a
little deeper into the 'encoder' area.
Thanks for the pointer,

Whilst I am resizing images I am losing quality. This is only happeningin
small amounts, but if you repeatedly put the same image through the
following code, the image quality slowly degrades. Can anyone spot why
this
may be happening? Should it only deteriate once upon intitially going
through this procedure? The deterioration is subtle, but after a few
iterations is quite noticeable..:
private static System.Drawing.Image CopyImage(System.Drawing.Image
imageFile, int width, int height)

System.Drawing.Bitmap bmpOut;
ImageFormat Format = imageFile.RawFormat;
bmpOut = new Bitmap(width, height, PixelFormat.Format64bppPArgb);

bmpOut.Palette = imageFile.Palette;
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality =
System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.FillRectangle(Brushes.White, 0, 0, width, height);
g.DrawImage(imageFile, 0, 0, width, height);


return bmpOut;

The image is then saved to disk using the following:

EncoderParameters encoderParameters;
encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
NewImage.Save(HttpContext.Current.Server.MapPath(newImgPath), jgpEncoder,
encoderParameters);


...

Well, I think it depends on the original image. You should try to play
with the values to find better result. For example, I am always adding
an additional value to the EncoderParameter for LZW Compression, which
is basically a technique for lossless compression:

encoderParameters.Param[1] = new EncoderParameter(Encoder.Compression,
(long)EncoderValue.CompressionLZW);- Hide quoted text -

- Show quoted text -

hmm... what kind of exception, General GDI+ Error?
Note, that you would need to resize an array, because now you would
have two values.

encoderParameters = new EncoderParameters(2);
 
Whilst I am resizing images I am losing quality. This is only happening in
small amounts, but if you repeatedly put the same image through the
following code, the image quality slowly degrades. Can anyone spot why this
may be happening?  Should it only deteriate once upon intitially going
through this procedure? The deterioration is subtle, but after a few
iterations is quite noticeable..:

private static System.Drawing.Image CopyImage(System.Drawing.Image
imageFile, int width, int height)

{

System.Drawing.Bitmap bmpOut;

ImageFormat Format = imageFile.RawFormat;

bmpOut = new Bitmap(width, height, PixelFormat.Format64bppPArgb);

bmpOut.SetResolution(imageFile.HorizontalResolution,
imageFile.VerticalResolution);

bmpOut.Palette = imageFile.Palette;

Graphics g = Graphics.FromImage(bmpOut);

g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

g.CompositingQuality =
System.Drawing.Drawing2D.CompositingQuality.HighQuality;

In addition, you can try to use SmoothingMode.HighQuality and
InterpolationMode.Bilinear (I use often this one). Hope this helps.
 
JJ said:
Whilst I am resizing images I am losing quality. This is only happening in
small amounts, but if you repeatedly put the same image through the
following code, the image quality slowly degrades. Can anyone spot why this
may be happening? Should it only deteriate once upon intitially going
through this procedure? The deterioration is subtle, but after a few
iterations is quite noticeable..:

If you resize an image an compress it with JPEG, you will get a quality
loss every time.

If you don't resize the image, and recompress it with JPEG, you will not
loose much data, as most of the data that the compression throws away
is data that was recreated when the image was decompressed. If you
resize the image, you will use both the original data and recreated data
to create a new image. When you compress this new image, the data that
the compression throws away doesn't correspond with the data that came
from the recreated data, so you are throwing away more and more of the
original data every time.

For example, the compression throws away 75% of the color information,
because color is less important than intensity. It calculates the
avarage color for each four pixels in a 2x2 grid, and uses the average
color for all four of the pixels. When you recompress the image, the
four pixels already have the same color, so no actual color information
is lost. If you resize the image, the 2x2 grid no longer matches the
loaded data, so the compression again throws away some of the color
information.
 
Thanks Göran.

By saving it as jpeg at 100L quality setting, is this compressing it
further? I am not, in effect, resizing after the first pass, as the
dimensions do not change (though I am resaving it - which I've now worked
around).
The loss is small and only obviouse when the image has fine detail (like
white text on dark backgrounds).

In this case, I would be interested in how you can make an exact copy of an
image and save to the same file. The clone() method is one option I suppose,
but there are issues there if you are saving back to the same file (GDI+
errors). The popular solution seems to be creating a new graphics object
from the original then disposing, as I try to do - but then I can't work
around this gradual loss.

Thanks,
JJ
 
JJ said:
Thanks Göran.

By saving it as jpeg at 100L quality setting, is this compressing it
further?

Even at the quality setting 100, there is still some compression and
some quality loss. For one, it still throws away 75% of the color
information, as I described.
I am not, in effect, resizing after the first pass, as the
dimensions do not change (though I am resaving it - which I've now worked
around).
The loss is small and only obviouse when the image has fine detail (like
white text on dark backgrounds).

Yes, if you don't resize the image, the degradation should be minimal.
In this case, I would be interested in how you can make an exact copy of an
image and save to the same file. The clone() method is one option I suppose,
but there are issues there if you are saving back to the same file (GDI+
errors). The popular solution seems to be creating a new graphics object
from the original then disposing, as I try to do - but then I can't work
around this gradual loss.

If you load the image from a file, you have to dispose that image before
you can save anything to that file. One way to get around that is to
open a FileStream for reading the file, and load the image from that
stream. That way you can dispose the stream so that the image is not
keeping the file open.

The Bitmap class has a constructor that takes an Image, that would be
the most straight forward way of making a copy of an image.
 
Back
Top