views:

77

answers:

2

I'm trying to rescale uploaded jpeg in asp.net

So I go:

Image original = Image.FromStream(myPostedFile.InputStream);
int w=original.Width, h=original.Height;

using(Graphics g = Graphics.FromImage(original))
{
 g.ScaleTransform(0.5f, 0.5f); ... // e.g.
 using (Bitmap done = new Bitmap(w, h, g))
 {
  done.Save( Server.MapPath(saveas), ImageFormat.Jpeg );
  //saves blank black, though with correct width and height
 }
}

this saves a virgin black jpeg whatever file i give it. Though if i take input image stream immediately into done bitmap, it does recompress and save it fine, like:

Image original = Image.FromStream(myPostedFile.InputStream);
using (Bitmap done = new Bitmap(original))
{
 done.Save( Server.MapPath(saveas), ImageFormat.Jpeg );
}

Do i have to make some magic with g?

upd: i tried:

Image original = Image.FromStream(fstream);
int w=original.Width, h=original.Height;
using(Bitmap b = new Bitmap(original)) //also tried new Bitmap(w,h)
 using (Graphics g = Graphics.FromImage(b))
 {
  g.DrawImage(original, 0, 0, w, h); //also tried g.DrawImage(b, 0, 0, w, h)
  using (Bitmap done = new Bitmap(w, h, g))
  {
   done.Save( Server.MapPath(saveas), ImageFormat.Jpeg );
  }
 }

same story - pure black of correct dimensions

A: 

Try this: - get the Image from your stream - create a new Bitmap of the correct size - get the Graphics object from the new bitmap, not the original one - call g.DrawImage(original, 0, 0, done.Width, done.Height)

Edit: The problem is this section:

using (Bitmap done = new Bitmap(w, h, g)) 
  { 
   done.Save( Server.MapPath(saveas), ImageFormat.Jpeg ); 
  }

You're creating a black bitmap, with the resolution specified by g. You're not actually creating a bitmap with any image data coming from g. In fact, I don't think the Graphics object actually stores image data that you can really pass around, it just allows you to manipulate some object that stores the image data.

Try replacing that with b.Save(...)

joelt
`b.Save(...)` does save image data, but transforms do not apply.It can be easily rescaled by using `b=new Bitmap(original,newWidth,newHeight)` BUT i actually need to make a series of transforms to original image, including rescale, crop and rotate, so trying to do it by means of `Graphics`, and render the final result into a bitmap. Am i misunderstanding the `Graphics` object?
joox
What is the right pattern to 1) take jpeg file 2) sequentially apply a number of transforms to it 3) save it ? Sounds simple...
joox
I think it's closer to say you're misunderstanding transforms. I really haven't dealt with transforms since college, about 7 years ago, so I'm kinda rusty. But I did a simple test with a rotation, and it worked. The trick is that you're not rotating the image data, you're rotating the graphics context, and then using that rotated context to draw your image. So in my case, the call to g.RotateTransform() needed to happen before the call to g.DrawImage(). How that's going to end up affecting you...hard to say. But cumulative effects of transforms can be funny, and order of operations may matter.
joelt
Order matters b/c transforms are fundamentally matrix operations, and matrix multiplication is not commutative, like scalar multiplication is. My use of transforms was in the context of OpenGL, and I often found myself surprised by the correct order of operations, and values used--sometimes it was the negative or inverse of what I expected it to be.
joelt
A: 

Since you didn't fill the area with background of image you're reading from inputStream,you can only get a blank image that way.

Instead of using scaling the image,you can use Fill background into a resized area.

Check this out:

Image img = Image.FromFile(Server.MapPath("a.png"));
int w = img.Width;
int h = img.Height;

//Create an empty bitmap with scaled size,here half
Bitmap bmp = new Bitmap(w / 2, h / 2);
//Create graphics object to draw
Graphics g = Graphics.FromImage(bmp);
//You can also use SmoothingMode,CompositingMode and CompositingQuality
//of Graphics object to preserve saving options for new image.        

//Create drawing area with a rectangle
Rectangle drect = new Rectangle(0, 0, bmp.Width, bmp.Height);
//Draw image into your rectangle area
g.DrawImage(img, drect);
//Save your new image
bmp.Save(Server.MapPath("a2.jpg"), ImageFormat.Jpeg);

Hope this helps
Myra

Myra
thanks, this made sense. i did a bit differently, but your code was good illustration
joox