converting images to thumbnails

A

Andrus

I have big jpeg images represented as Byte[] arrays.

I need to resize them to Height='200' MaxWidth='150' small thumbnails for
fast display in web page.

Where to find sample code for DrawImage or other solution in server side
which reduces size of jpeg byte[] array for this format and to minimal size
before sending ?

Andrus.
 
J

Jeff Johnson

I have big jpeg images represented as Byte[] arrays.

I need to resize them to Height='200' MaxWidth='150' small thumbnails for
fast display in web page.

Where to find sample code for DrawImage or other solution in server side
which reduces size of jpeg byte[] array for this format and to minimal
size before sending ?

Here's the pseudo-code:

Load your byte array into a MemoryStream
Create a Bitmap object from it with the FromStream() method
Create a new Bitmap object with the thumbnail dimensions
Create a Graphics object over the new bitmap
Draw the big bitmap onto the new one with DrawImage(Image, Rectangle)
Use the new bitmap as you see fit

If you've done ANY work with the System.Drawing namespace this shouldn't be
hard to code, so I leave it as an exercise....
 
J

Jeff Johnson

That said, the Bitmap class has a constructor that takes an existing image
and a new size

HAHAHAHA!! I posted the long way in my reply when in fact not much more than
a month ago I was using the exact same method you just suggested. Cobwebs in
the brain, I guess....
 
A

Andrus

Cor, Peter and Jeff,
The getting an thumbnail from an image is an already long existing method
from image

http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx

Thank you for help.
I have almost zero experience using System.Drawing
I tried to create conversion function using sample from

http://blog.rileytech.net/post/2008/09/30/Image-resizing-ninjitsu.aspx

but got 3 strange compile errors shown in comments.
How to fix them ?

Andrus.

// converts jpeg image to jpeg thumbnail
Byte[] MakeMeAGoodThumbnail(Byte[] source)
{
// Argument '1': cannot convert from 'byte[]' to 'string'
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(source);
int width, height;
if (bmp.Height > 320 || bmp.Width > 240)
{
float percent = DeterminePercentageForResize(bmp.Height,
bmp.Width);
float floatWidth = (float)bmp.Width * percent;
float floatHeight = (float)bmp.Height * percent;

width = Convert.ToInt32(floatWidth);
height = Convert.ToInt32(floatHeight);
}
else
{
width = bmp.Width;
height = bmp.Height;
}

//Argument '3': cannot convert from 'bool' to
'System.Drawing.Image.GetThumbnailImageAbort' I:\raamat\Eeva\Eeva
Business\EntityBase\EntityBase.cs 890 79 Business
System.Drawing.Image thumb = bmp.GetThumbnailImage(width,
height, ThumbnailCallback(), IntPtr.Zero);
// Cannot implicitly convert type 'System.Drawing.Bitmap' to
'byte[]'
return new Bitmap(thumb);
}

float DeterminePercentageForResize(int height, int width)
{
int highestValue;
if (height > width)
highestValue = height;
else
highestValue = width;

float percent = 100 / (float)highestValue;

if (percent > 1 && percent != 0)
throw new Exception("Percent cannot be greater than 1 or
equal to zero");
else
return percent;
}

public bool ThumbnailCallback()
{
return false;
}
 
C

Cor Ligthert[MVP]

Pete,

Note that there are advantages and disadvantages to using the
GetThumbnailImage() method. The advantage is that if you request a
thumbnail the exact size for which one is available for the file already,
it's quite fast. The disadvantage is that if it needs to create a new
thumbnail image, it will scale the original thumbnail, not the original
image, which can produce especially poor results. You also have no
control over the scaling algorithm used, as you would if you scaled the
original image yourself using the Graphics class and DrawImage() method.
True, but for Internet when you need every day many new thumbnails which is
scaled down often 100 times, it is mostly better then trying to find a
solution which often fits perfect for only one image.

Just an add to your message.

Cor
 
C

Cor Ligthert[MVP]

Pete,

Note that there are advantages and disadvantages to using the
GetThumbnailImage() method. The advantage is that if you request a
thumbnail the exact size for which one is available for the file already,
it's quite fast. The disadvantage is that if it needs to create a new
thumbnail image, it will scale the original thumbnail, not the original
image, which can produce especially poor results. You also have no
control over the scaling algorithm used, as you would if you scaled the
original image yourself using the Graphics class and DrawImage() method.
True, but for Internet when you need every day many new thumbnails which is
scaled down often 100 times, it is mostly better then trying to find a
solution which often fits perfect for only one image.

Just an add to your message.

Cor
 
A

Andrus

Pete,
Note that there are advantages and disadvantages to using the
GetThumbnailImage() method. The advantage is that if you request a
thumbnail the exact size for which one is available for the file already,
it's quite fast. The disadvantage is that if it needs to create a new
thumbnail image, it will scale the original thumbnail, not the original
image, which can produce especially poor results. You also have no
control over the scaling algorithm used, as you would if you scaled the
original image yourself using the Graphics class and DrawImage() method.

Thank you very much.
My thumbnails height is 200 and maxwidth is 150 pixels.
Images are typically jpeg files taken by digital camera, not processed, size
is 3-7 MB .

Currently I send whole image to Silverlight application and Silverlight
itself resizes images to this size. Resulting thumbnails are sharp and good
quality.

I added code code which pre-processes byte[] images in server to reduce
image size transferred over internet.
Resulting thumbnails are much lower quality in screen.
I tried also thumb.Save(ms, ImageFormat.Png ); but problem persists.

How to improve thumbnail quality ?

Andrus.

Byte[] MakeMeAGoodThumbnail(Byte[] source)
{
Bitmap bmp = new Bitmap(new MemoryStream(source));
int width, height;
if (bmp.Height > 200 || bmp.Width > 150)
{
float percent = DeterminePercentageForResize(bmp.Height,
bmp.Width);
float floatWidth = (float)bmp.Width * percent;
float floatHeight = (float)bmp.Height * percent;

width = Convert.ToInt32(floatWidth);
height = Convert.ToInt32(floatHeight);
}
else
{
width = bmp.Width;
height = bmp.Height;
}
Image thumb = bmp.GetThumbnailImage(width, height,
() => false, IntPtr.Zero);
var ms = new MemoryStream();
thumb.Save(ms, ImageFormat.Jpeg);
return ms.ToArray();
}

float DeterminePercentageForResize(int height, int width)
{
int highestValue;
if (height > width)
highestValue = height;
else
highestValue = width;

float percent = 100 / (float)highestValue;

if (percent > 1 && percent != 0)
throw new Exception("Percent cannot be greater than 1 or
equal to zero");
else
return percent;
}
 
A

Andrus

Pete,
Note that there are advantages and disadvantages to using the
GetThumbnailImage() method. The advantage is that if you request a
thumbnail the exact size for which one is available for the file already,
it's quite fast. The disadvantage is that if it needs to create a new
thumbnail image, it will scale the original thumbnail, not the original
image, which can produce especially poor results. You also have no
control over the scaling algorithm used, as you would if you scaled the
original image yourself using the Graphics class and DrawImage() method.

Thank you very much.
My thumbnails height is 200 and maxwidth is 150 pixels.
Images are typically jpeg files taken by digital camera, not processed, size
is 3-7 MB .

Currently I send whole image to Silverlight application and Silverlight
itself resizes images to this size. Resulting thumbnails are sharp and good
quality.

I added code code which pre-processes byte[] images in server to reduce
image size transferred over internet.
Resulting thumbnails are much lower quality in screen.
I tried also thumb.Save(ms, ImageFormat.Png ); but problem persists.

How to improve thumbnail quality ?

Andrus.

Byte[] MakeMeAGoodThumbnail(Byte[] source)
{
Bitmap bmp = new Bitmap(new MemoryStream(source));
int width, height;
if (bmp.Height > 200 || bmp.Width > 150)
{
float percent = DeterminePercentageForResize(bmp.Height,
bmp.Width);
float floatWidth = (float)bmp.Width * percent;
float floatHeight = (float)bmp.Height * percent;

width = Convert.ToInt32(floatWidth);
height = Convert.ToInt32(floatHeight);
}
else
{
width = bmp.Width;
height = bmp.Height;
}
Image thumb = bmp.GetThumbnailImage(width, height,
() => false, IntPtr.Zero);
var ms = new MemoryStream();
thumb.Save(ms, ImageFormat.Jpeg);
return ms.ToArray();
}

float DeterminePercentageForResize(int height, int width)
{
int highestValue;
if (height > width)
highestValue = height;
else
highestValue = width;

float percent = 100 / (float)highestValue;

if (percent > 1 && percent != 0)
throw new Exception("Percent cannot be greater than 1 or
equal to zero");
else
return percent;
}
 
A

Andrus

Pete,
There are a number of threads in this newsgroup that cover that topic.
Please feel free to use Google Groups or another archive to search for
them. If you do the search correctly, you will probably even find the
article that Jeff Johnson posted in this very message thread in which he
included a brief summary of the technique. Once you've seen the general
technique to apply, if you still have specific questions, please do feel
free to ask for help.

I performed searches in google and tried code samples shown in comments.
All those methods produce non-sharp thumbnails compared to thumbnail created
in silverlight client.

How to create high-quality small-size thumbails in server?

Andrus.

Byte[] MakeMeAGoodThumbnail(Byte[] source, int imageHeight, int imageWidth)
{
Bitmap bmp = new Bitmap(new MemoryStream(source));
int width, height;
if (bmp.Height > imageHeight || bmp.Width > imageWidth)
{
float percent = DeterminePercentageForResize(bmp.Height,
bmp.Width);
float floatWidth = (float)bmp.Width * percent;
float floatHeight = (float)bmp.Height * percent;

width = Convert.ToInt32(floatWidth);
height = Convert.ToInt32(floatHeight);
}
else
{
width = bmp.Width;
height = bmp.Height;
}
var ms = new MemoryStream();

//http://www.west-wind.com/Weblog/posts/283.aspx comment
var resized = BetterThumbnail(bmp, width, height);

#if false
//http://www.west-wind.com/Weblog/posts/283.aspx
var resized = new Bitmap(width, height);
Graphics g = Graphics.FromImage(resized);
g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, width, height);
g.DrawImage(bmp, 0, 0, width, height);
bmp.Dispose();
g.Dispose();
#endif

#if false
//http://www.bobpowell.net/changing_resolution.htm
Bitmap resized = new Bitmap(width, height);
Graphics g = Graphics.FromImage(resized);
g.DrawImage(bmp, new Rectangle(0, 0, resized.Width,
resized.Height), 0, 0,
bmp.Width,
bmp.Height, GraphicsUnit.Pixel);
g.Dispose();
#endif

#if false
// digital photos contain built-in thumbnails. This function
resizes them and produces low
// quality thumbnail:
Image resized = bmp.GetThumbnailImage(width, height,
() => false, IntPtr.Zero);
#endif
resized.Save(ms, ImageFormat.Jpeg);
return ms.ToArray();
}

public static Bitmap BetterThumbnail(Bitmap inputImage, int width, int
height)
{
Bitmap outputImage = new Bitmap(width, height,
PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(outputImage);
g.CompositingMode = CompositingMode.SourceCopy;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
Rectangle destRect = new Rectangle(0, 0, width, height);
g.DrawImage(inputImage, destRect, 0, 0, inputImage.Width,
inputImage.Height, GraphicsUnit.Pixel);
g.Dispose();
return outputImage;
}

float DeterminePercentageForResize(int height, int width)
{
int highestValue;
if (height > width)
highestValue = height;
else
highestValue = width;

float percent = 100 / (float)highestValue;

if (percent > 1 && percent != 0)
throw new Exception("Percent cannot be greater than 1 or
equal to zero");
else
return percent;
}
 
A

Andrus

Pete,
There are a number of threads in this newsgroup that cover that topic.
Please feel free to use Google Groups or another archive to search for
them. If you do the search correctly, you will probably even find the
article that Jeff Johnson posted in this very message thread in which he
included a brief summary of the technique. Once you've seen the general
technique to apply, if you still have specific questions, please do feel
free to ask for help.

I performed searches in google and tried code samples shown in comments.
All those methods produce non-sharp thumbnails compared to thumbnail created
in silverlight client.

How to create high-quality small-size thumbails in server?

Andrus.

Byte[] MakeMeAGoodThumbnail(Byte[] source, int imageHeight, int imageWidth)
{
Bitmap bmp = new Bitmap(new MemoryStream(source));
int width, height;
if (bmp.Height > imageHeight || bmp.Width > imageWidth)
{
float percent = DeterminePercentageForResize(bmp.Height,
bmp.Width);
float floatWidth = (float)bmp.Width * percent;
float floatHeight = (float)bmp.Height * percent;

width = Convert.ToInt32(floatWidth);
height = Convert.ToInt32(floatHeight);
}
else
{
width = bmp.Width;
height = bmp.Height;
}
var ms = new MemoryStream();

//http://www.west-wind.com/Weblog/posts/283.aspx comment
var resized = BetterThumbnail(bmp, width, height);

#if false
//http://www.west-wind.com/Weblog/posts/283.aspx
var resized = new Bitmap(width, height);
Graphics g = Graphics.FromImage(resized);
g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, width, height);
g.DrawImage(bmp, 0, 0, width, height);
bmp.Dispose();
g.Dispose();
#endif

#if false
//http://www.bobpowell.net/changing_resolution.htm
Bitmap resized = new Bitmap(width, height);
Graphics g = Graphics.FromImage(resized);
g.DrawImage(bmp, new Rectangle(0, 0, resized.Width,
resized.Height), 0, 0,
bmp.Width,
bmp.Height, GraphicsUnit.Pixel);
g.Dispose();
#endif

#if false
// digital photos contain built-in thumbnails. This function
resizes them and produces low
// quality thumbnail:
Image resized = bmp.GetThumbnailImage(width, height,
() => false, IntPtr.Zero);
#endif
resized.Save(ms, ImageFormat.Jpeg);
return ms.ToArray();
}

public static Bitmap BetterThumbnail(Bitmap inputImage, int width, int
height)
{
Bitmap outputImage = new Bitmap(width, height,
PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(outputImage);
g.CompositingMode = CompositingMode.SourceCopy;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
Rectangle destRect = new Rectangle(0, 0, width, height);
g.DrawImage(inputImage, destRect, 0, 0, inputImage.Width,
inputImage.Height, GraphicsUnit.Pixel);
g.Dispose();
return outputImage;
}

float DeterminePercentageForResize(int height, int width)
{
int highestValue;
if (height > width)
highestValue = height;
else
highestValue = width;

float percent = 100 / (float)highestValue;

if (percent > 1 && percent != 0)
throw new Exception("Percent cannot be greater than 1 or
equal to zero");
else
return percent;
}
 
A

Andrus

Pete,
If you want to pursue the question here, you need a more specific
description than "non-sharp thumbnails". In particular, you really ought
to provide example files for people to look at: an original image, along
with two thumbnail examples, one from Silverlight that you like, and the
one from System.Drawing that you don't.

Silverlight renders to screen. Probably it is not possible to render image
to file in Silverlight.
Is it sufficient to use print screen to create images and attach them to the
message posted to this newsgroup using news server ?

Andrus.
 
A

Andrus

Pete,
If you want to pursue the question here, you need a more specific
description than "non-sharp thumbnails". In particular, you really ought
to provide example files for people to look at: an original image, along
with two thumbnail examples, one from Silverlight that you like, and the
one from System.Drawing that you don't.

Silverlight renders to screen. Probably it is not possible to render image
to file in Silverlight.
Is it sufficient to use print screen to create images and attach them to the
message posted to this newsgroup using news server ?

Andrus.
 

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