Resizing Image control in DataList ItemTemplate

D

David W. Simmonds

I have a DataList control that has an Image control in the ItemTemplate. I
would like to resize the image that goes into that control. I have a series
of jpg files that are full size, full resolution (ie. large). I have a
database that contains references to the pictures. Currently I have to
resize the jpgs manually, and then point the ImageUrl property at that jpg
using databinding. This works fine. I would like to avoid the resizing step
and have the server code do it. I could then have the full image load into
another browser window if the user requests it, but the initial image would
be a realistic size (640x480 or 720x480). Is there a way to replace the
Image control in the datalist with a new resized one?

If I had a Button object in the datalist ItemTemplate, how do I receive the
event that it has been pressed? With just a button on the form, I can just
dblclick the control in the IDE and the event is added to the code.
 
S

Shiv Kumar

David,

For now I will assume you know the basic mechanics of the http protocol and
how browsers work with regards to <img>, <link>, <script> tags etc.

So in theory, your image control's ImageUrl should point to (to keep it
simple) an aspx page whose sole purpose is:
Given the url to the full sized image (as a parameter), to return the
thumbnail of that image. Better still, an additional parameter in the url
will tell it if you need a thumbnail or full size.

So lets say that the ImageUrl property of the image control would look like
this:

/ImageProcessor.aspx?filename=someimage.jpg&size=small

No in the ImageProcessor.aspx you simply load up the actual file and (if the
size parameter = small) get a thumbnail.

The way you return the "image" (binary) to the browser is by writing to the
Response.OutputStream

A simple method like this should help

"stream" in this case Response.OutputStream. In my case width, height and
img are private members of my class that were initialized at the time of
creating and instance.
public void GetThumbnail(ref System.IO.Stream stream)

{

System.Drawing.Image thumbnail;

System.IntPtr ptr = new IntPtr();

/* If the width parameter is "0", assume normal image size */

if (width != 0)

{

thumbnail = img.GetThumbnailImage(width, height, null, ptr);

thumbnail.Save(stream, img.RawFormat);

thumbnail.Dispose();

}

else

{

img.Save(stream, img.RawFormat);

}

img.Dispose();

}
 
M

MSFT

Hi David,

Thank you for using MSDN Newsgroup. I am Luke and I am review this issue
currently. As I understand, you have two questions about the DataList
control:

1. How to resize a image
2. How to receive events from a button in ItemTemplate

For question 1, you may refer to the Shiv's message, I think his suggestion
is a valid solution. For question 2, we should associate the button's Click
event with a function with AddHandler method. For example, in the
datalist's ItemDataBound :


Private Sub DataList1_ItemDataBound(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.DataListItemEventArgs) Handles
DataList1.ItemDataBound

Dim b As Button

b = e.Item.FindControl("MyButton")

AddHandler Button1.Click, AddressOf DataListButtonClick

End Sub

Private Sub DataListButtonClick(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click

End Sub

Hope this help,

Luke
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
D

David W. Simmonds

Do you have a fast method of resizing a System.Drawing.Image object?
Preferably one that results in a quality image. I have a method found on
codeproject.com, but as noted in the comment, it requires a lot of cpu time.

int y = (int)(((double)((double)m_nWidth/(double)m_Image.Size.Width)) *
(double)m_Image.Size.Height);
thumb = Resize(new Bitmap(m_Image), m_nWidth, y, (bool)(m_nWidth > 200));
public static Bitmap Resize(Bitmap b, int nWidth, int nHeight, bool
bBilinear)
{
//Bitmap bTemp = (Bitmap)b.Clone();
Bitmap bTemp = b;
b = new Bitmap(nWidth, nHeight, bTemp.PixelFormat);
double nXFactor = (double)bTemp.Width/(double)nWidth;
double nYFactor = (double)bTemp.Height/(double)nHeight;
if (bBilinear)
{
double fraction_x, fraction_y, one_minus_x, one_minus_y;
int ceil_x, ceil_y, floor_x, floor_y;
Color c1 = new Color();
Color c2 = new Color();
Color c3 = new Color();
Color c4 = new Color();
byte red, green, blue;
byte b1, b2;
for (int x = 0; x < b.Width; ++x)
{
for (int y = 0; y < b.Height; ++y)
{
// Setup
floor_x = (int)Math.Floor(x * nXFactor);
floor_y = (int)Math.Floor(y * nYFactor);
ceil_x = floor_x + 1;
if (ceil_x >= bTemp.Width) ceil_x = floor_x;
ceil_y = floor_y + 1;
if (ceil_y >= bTemp.Height) ceil_y = floor_y;
fraction_x = x * nXFactor - floor_x;
fraction_y = y * nYFactor - floor_y;
one_minus_x = 1.0 - fraction_x;
one_minus_y = 1.0 - fraction_y;
c1 = bTemp.GetPixel(floor_x, floor_y);
c2 = bTemp.GetPixel(ceil_x, floor_y);
c3 = bTemp.GetPixel(floor_x, ceil_y);
c4 = bTemp.GetPixel(ceil_x, ceil_y);
// Blue
b1 = (byte)(one_minus_x * c1.B + fraction_x * c2.B);
b2 = (byte)(one_minus_x * c3.B + fraction_x * c4.B);
blue = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));
// Green
b1 = (byte)(one_minus_x * c1.G + fraction_x * c2.G);
b2 = (byte)(one_minus_x * c3.G + fraction_x * c4.G);
green = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));
// Red
b1 = (byte)(one_minus_x * c1.R + fraction_x * c2.R);
b2 = (byte)(one_minus_x * c3.R + fraction_x * c4.R);
red = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));
b.SetPixel(x,y, System.Drawing.Color.FromArgb(255, red, green, blue));
}
}
}
else
{
for (int x = 0; x < b.Width; ++x)
for (int y = 0; y < b.Height; ++y)
b.SetPixel(x, y, bTemp.GetPixel((int)(Math.Floor(x * nXFactor)),
(int)(Math.Floor(y * nYFactor))));
}
return b;
}
 
S

Shiv Kumar

David,

Other than figuring out the new size and maintaining the aspect ratio the
code I provided will work (it needs to be given the size). But even getting
at the proper size (while maintaining the aspect ratio) is not as
complicated as the code you posted.
 
D

David W. Simmonds

The code you provided is excellent and it works, but the call to
GetThumbnailImage returns a bad image if the size if larger than about
120x120. GetThumbnailImage will read the thumbnail contained in the jpg and
resize it. The thumbnail in the jpg is generally small and low resolution.

I found some code and modified it to look like this:
public System.Drawing.Image Resize(System.Drawing.Image src, int nWidth, int
nHeight, bool bBilinear)
{
Bitmap bmPhoto = new Bitmap(nWidth, nHeight,
PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(src.HorizontalResolution, src.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(src,
new Rectangle(0,0,nWidth,nHeight),
new Rectangle(0,0,src.Width,src.Height),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
 
S

Shiv Kumar

Yes the code you posted is what I would do (and have been doing before
coming across the GetThumbnail method and in other development
tools/languages) as well.
 
D

David W. Simmonds

When the image arrives at the client side, it is a .bmp file, so it is a
huge file. What do I have to do to send it as a .jpg?
 
D

David W. Simmonds

I have tried using
thumb.Save(Response.OutputStream, ImageFormat.Jpeg)

but right clicking on the image and selecting Save Target As... only allows
me to choose a .bmp file.
 
M

MSFT

Hi David,

You may convert it to JPG format before return. For example:

from:
...
grPhoto.DrawImage(src,
new Rectangle(0,0,nWidth,nHeight),
new Rectangle(0,0,src.Width,src.Height),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;

to:

grPhoto.DrawImage(src,
new Rectangle(0,0,nWidth,nHeight),
new Rectangle(0,0,src.Width,src.Height),
GraphicsUnit.Pixel);
grPhoto.Dispose();


MemoryStream ms = new MemoryStream();
bmPhoto.Save(ms, ImageFormat.Jpeg);
Bitmap myPhoto = new Bitmap(ms);
return myPhoto

Luke
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
M

MSFT

Hi David,

What did you mean "did not work"? Is it still in BMP format or generate
some error? I test your code on my side and it have two options when I
select "save picture as": JPG and BMP". Or you may try:

thumb.Save(Response.OutputStream, ImageFormat.Jpeg);

Will this save it as JPG format?

Luke
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 

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

Members online

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top