Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reduce the size of an image in C# and .NET 3.5?

I have a screen shot I take in my mobile app. The screen shot takes about 32 KB when saved as a png on a disk.

I am sending these to a central SQL Server and 32 KB is too big for that amount of times I will need to store that screen shot (approx 2500 times a day).

Is there any kind of trickery that I can do to get it to save smaller?

Here is the code I am using now to take it from Bitmap to bytes (to send to the server for storage):

MemoryStream stream = new MemoryStream();
 _signatureImage.Save(stream, ImageFormat.Png);
 return stream.ToArray();

_signatureImage is a Bitmap and is the screenshot in question.

Here is an example of the screen shot I am saving:

Screen Shot Image

Things that pop to mind (but I don't know how to do them):

  1. Reduce the actual Height and Width of the image (but hopefully in a way that will not distort it).
  2. Change it to a black and white image (not sure if I will see any real space savings from this)
  3. Compress it more (I don't like this as much because then it is not readable from the database).

Note, this all has to be done programatically, and cannot take very long, so complex image manipulations are out.

Thanks for any help.

like image 809
Vaccano Avatar asked Oct 07 '10 19:10

Vaccano


People also ask

How do I resize an image in coding?

One of the simplest ways to resize an image in the HTML is using the height and width attributes on the img tag. These values specify the height and width of the image element. The values are set in px i.e. CSS pixels.

How do I reduce the KB size of a photo?

How to reduce the image size in KB/MB? To reduce the image size in KB or MB online, first upload it to ResizePixel's website. Enter a desired file size and select the corresponding unit of measurement (KB or MB). Then proceed to Download page to get the image file.


4 Answers

    private static Image ResizeImage(int newSize, Image originalImage)
    {
        if (originalImage.Width <= newSize)
            newSize = originalImage.Width;

        var newHeight = originalImage.Height * newSize / originalImage.Width;

        if (newHeight > newSize)
        {
            // Resize with height instead
            newSize = originalImage.Width * newSize / originalImage.Height;
            newHeight = newSize;
        }

        return originalImage.GetThumbnailImage(newSize, newHeight, null, IntPtr.Zero);
    }

This should work with your Bitmap object Type and resize the Height or Width, depending on which is appropriate for your image dimensions. It will also maintain scale.

EDIT:

You could create a new Bitmap object and resize your original image into that Bitmap object.

Bitmap b = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;

g.DrawImage(imgToResize, 0, 0, newWidth, newHeight);
g.Dispose();

return (Image)b;

I don't have the Compact Framework installed, but it seems that this should work for you.

like image 169
pattertj Avatar answered Oct 27 '22 07:10

pattertj


If color depth is not an issue, you might change it to black and white, or 16 color mode. There should be a significant savings over png's 24-bpp (or 32-bpp with alpha) storage requirements. The other thing to think about is saving it as a .gif file in 256 color mode.

As you're saving signature data, I'd think changing the dimensions of the image would be a bad idea. You might also consider applying a lossless compression like zip, but that is likely more computationally intensive than you require.

like image 43
Matt Mills Avatar answered Oct 27 '22 07:10

Matt Mills


Change the color palette to a lower color depth. Take a look at this question (well look at the answert really) which shows converting to 1bpp. You could go to 8bpp instead of 1bpp and have significant size savings. The mechanism for conversion will be the same as what is shown.

EDIT

Thinking out of the box, you might also consider just sending the data points from the upper part of the screen and the signature vector, and have the server recreate the screen for you. If size really is a big issue, I'd probably investigate that.

EDIT 2

If simply resizing the image is a reasonable solution (you'll obviously lose data in doing so) then you can use the Imaging namespace in the SDF to create a thumbnail as Alex explains here.

like image 27
ctacke Avatar answered Oct 27 '22 06:10

ctacke


If monochrome image is acceptable, you can try TIFF G4 (lossless compression). TIFF G4 is known for being very effective in file size to store black and white image. Unfortunately I dont have any info available on how it compares to PNG, but worth investigating into it.

Here is the info and example on how to do it in C#

like image 26
Fadrian Sudaman Avatar answered Oct 27 '22 05:10

Fadrian Sudaman