Saving mostly images with white space - high file size,

I save some A4 images and thumbnails to a file.

I want to know which format is better. They come back from scanning only in shades of gray. However, some of the images are quite large in size (compared to what we expect).

We tried to save them in JPEG format with different qualities, but still cannot get them as small as we would like, JPEG is not the most efficient format for this.

A4 Quality saved 8 saved as 196 KB smaller image saved as 8 saves as 28 KB

Since most of this image is a space, we expected much smaller file sizes. File size here is more important than image quality. Are we doing something wrong?

Here is an example image of A4 enter image description here

Here is an example of a smaller image enter image description here

Our code is written in C #

// Get a bitmap. Bitmap bmp1 = new Bitmap(@"c:\TestImageFromScanner.jpg"); ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg); // Create an Encoder object based on the GUID // for the Quality parameter category. System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; // Create an EncoderParameters object. // An EncoderParameters object has an array of EncoderParameter // objects. In this case, there is only one // EncoderParameter object in the array. EncoderParameters myEncoderParameters = new EncoderParameters(1); EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder,8L); myEncoderParameters.Param[0] = myEncoderParameter; bmp1.Save(@"c:\TestJpegQuality8.jpg", jgpEncoder, myEncoderParameters); 
+6
source share
4 answers

I used the function to convert the image only to black or white using a threshold. This significantly reduced the size of the image, the quality of which decreased significantly.

  var downsizeImage = ImageTools.ConvertToBitonal(scaledBmp, 500); downsizeImage.Save(string.Format(@"C:\Temp\{0}Downsized.png", betSlipImage.BetSlipID), ImageFormat.Png); var ms = new MemoryStream(); downsizeImage.Save(ms, ImageFormat.Png); public static Bitmap ConvertToBitonal(Bitmap original, int threshold) { Bitmap source; // If original bitmap is not already in 32 BPP, ARGB format, then convert if (original.PixelFormat != PixelFormat.Format32bppArgb) { source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb); source.SetResolution(original.HorizontalResolution, original.VerticalResolution); using (var g = Graphics.FromImage(source)) { g.DrawImageUnscaled(original, 0, 0); } } else { source = original; } // Lock source bitmap in memory var sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // Copy image data to binary array var imageSize = sourceData.Stride * sourceData.Height; var sourceBuffer = new byte[imageSize]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize); // Unlock source bitmap source.UnlockBits(sourceData); // Create destination bitmap var destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed); destination.SetResolution(original.HorizontalResolution, original.VerticalResolution); // Lock destination bitmap in memory var destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); // Create destination buffer imageSize = destinationData.Stride * destinationData.Height; var destinationBuffer = new byte[imageSize]; var sourceIndex = 0; var destinationIndex = 0; var pixelTotal = 0; byte destinationValue = 0; var pixelValue = 128; var height = source.Height; var width = source.Width; // Iterate lines for (var y = 0; y < height; y++) { sourceIndex = y * sourceData.Stride; destinationIndex = y * destinationData.Stride; destinationValue = 0; pixelValue = 128; // Iterate pixels for (var x = 0; x < width; x++) { // Compute pixel brightness (ie total of Red, Green, and Blue values) - Thanks murx // BGR pixelTotal = sourceBuffer[sourceIndex] + sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2]; if (pixelTotal > threshold) { destinationValue += (byte)pixelValue; } if (pixelValue == 1) { destinationBuffer[destinationIndex] = destinationValue; destinationIndex++; destinationValue = 0; pixelValue = 128; } else { pixelValue >>= 1; } sourceIndex += 4; } if (pixelValue != 128) { destinationBuffer[destinationIndex] = destinationValue; } } // Copy binary image data to destination bitmap Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize); // Unlock destination bitmap destination.UnlockBits(destinationData); // Dispose of source if not originally supplied bitmap if (source != original) { source.Dispose(); } // Return return destination; } 
+1
source

But is there a better image format for images that have shades of gray and mostly spaces?

Looking at your image, it is monochrome, and not in shades of gray. And if monochrome is acceptable, you can use JBIG2 to compress your documents.

It has special improvements for text (among other things):

Ideally, a JBIG2 encoder will segment the input page into text areas, grayscale areas, and other data areas. Regions that are neither text nor semitone are typically compressed using a context-specific arithmetic coding algorithm called a QM encoder. Text areas are compressed as follows: foreground pixels in regions are grouped into characters. A symbol dictionary is then created and encoded, usually also using context-sensitive arithmetic coding, and regions are encoded by describing the characters that are displayed there.

Emphasis is mine.

+6
source

For images with large blocks of flat color, consider using PNG-8.

However, the suggestion ta.speot.ls in this case seems to be better suited to your needs.

+1
source

Lossless compression groups pixels of the same color. If there are 100 white pixels, it stores โ€œone hundred white pixelsโ€ instead of โ€œwhite pixel, white pixel .....โ€ 100 times.

Your images have large areas of white. If you want it to compress well, it should be the same white. So quantify your images. Just reduce the number of colors.

I think you just need it to be readable as proof of something, so you don't need shades of gray.

The best results will have 1 bit of depth (2 colors black and white), PNG and tiff give good results.

If you can afford to spend more time on this, you could do some processing, such as removing single pixels (noise).

Avoid jpeg that was made for photos.

0
source

Source: https://habr.com/ru/post/956555/


All Articles