How is the size of a PNG file determined? - png

The image properties for this image say that the width and height are respectively 340 pixels and 471 pixels. The bit depth is 24 bits. My understanding was that this means that the value associated with each pixel is encoded using 24 bits. So I expected the file size to be around 471 * 340 * 24 = 3843360 bits = 480420 bytes =480 KB. But then one of the image properties says the size of the file is 9.98 KB. Why the big difference?
I am reading the images into a convolutional neural network where I need to supply the input shape.
Below is a screenshot of image properties
Below is a screenshot of actual image:

The PNG image format is designed to support lossless data compression. The file size you calculated is completely uncompressed, just raw image data. To save disk space, the file is compressed, and given your example of the image, this can be done very effectively because most of the image is exactly the same color.

Related

How to shrink or manage an image's size in bytes

Python 3.6.6, Pillow 5.2.0
The Google Vision API has a size limit of 10485760 bytes.
When I'm working with a PIL Image, and save it to Bytes, it is hard to predict what the size will be. Sometimes when I try to resize it to have smaller height and width, the image size as bytes gets bigger.
I've tried experimenting with modes and formats, to understand their impact on size, but I'm not having much luck getting consistent results.
So I start out with a rawImage that is Bytes obtained from some user uploading an image (meaning I don't know much about what I'm working with yet).
rawImageSize = sys.getsizeof(rawImage)
if rawImageSize >= 10485760:
imageToShrink = Image.open(io.BytesIO(rawImage))
## do something to the image here to shrink it
# ... mystery code ...
## ideally, the minimum amount of shrinkage necessary to get it under 10485760
rawBuffer = io.BytesIO()
# possibly convert to RGB first
shrunkImage.save(rawBuffer, format='JPEG') # PNG files end up bigger after this resizing (!?)
rawImage = rawBuffer.getvalue()
print(sys.getsizeof(rawImage))
To shrink it I've tried getting a shrink ratio and then simply resizing it:
shrinkRatio = 10485760.0 / float(rawImageSize)
imageWidth, imageHeight = pilImage.size
shrunkImage = imageToShrink.resize((int(imageWidth * shrinkRatio),
int(imageHeight * shrinkRatio)), Image.LANCZOS)
Of course I could use a sufficiently small and somewhat arbitrary thumbnail size instead. I've thought about iterating thumbnail sizes until a combination takes me below the maximum bytes size threshold. I'm guessing the bytes size varies based on the color depth and mode and (?) I got from the end user that uploaded the original image. And that brings me to my questions:
Can I predict the size in bytes a PIL Image will be before I convert it for consumption by Google Vision? What is the best way to manage that size in bytes before I convert it?
First all, you probably don't need to maximize to the 10M limit posed by Google Vision API. In most case, a much smaller file will be just fine, and faster.
In addition to that, you may want to keep in mind that the aspect ratio might lead to different result. See this, https://www.mlreader.com/prepare-image-for-google-vision-api

how to change DPI of an image in MATLAB

Here is the problem to change an image resolution from 300 dpi to 200 dpi or 600 dpi.
i am using matlab but how can i be. so for i have use the imresize function which down sample the image and up sample it.
imresize(image, scale ,interpolation).
how can down sample the image to reduce its quality too. so that i may check the difference between the original image and the down sampled image.
j= imresize(I,0.2,'nearest');
where I is the original image and j is the down sampled image. is this changing the dpi of an image.
Dots per inch (DPI) has nothing to do with the type of resizing done by imresize. In fact, changing the DPI does not even require changing the actual image data, just the metadata -- a property or label. DPI gives you the information needed to go from pixels -> inches (print size).

UIImage allocates more memory

In my viewcontroller i created a UIImageView and assigned a image in the Interface Builder. While checking on instruments i have allocation of malloc of 600kb and the responsible library is ImageIO_Malloc. But the size of my image is 37kb. I dont know why it allocates 600kb.
I have also tried with the code by assigning UIImage imageNamed. Still no good.
Do you people have any idea on that.
600 kB is really not much to allocate for a image. Your 37 kB is probably just the size of the compressed image file. However when that image needs to be displayed the image view needs to allocate back buffering of it so it can be represented in an uncompressed format internally.
An image with dimensions of 640x480 pixels will result in 300.000 pixels, each of which needs and R, G, B, and possible alpha value - meaning 3-4 bytes per pixel. So you can easily see allocations in the order og 600 kB for even fairly small images.

Understanding 24 bit PNG generated with Photoshop

A 24 bit .png file with transparency, as those that can be generated with Photoshop, has really 24 bits distributed across each color plus the alpha ? or the 24 bit refer only to the colors and ignores the alpha (RGBA 8888).
Is there any tool to examine a PNG file and verify this kind of information? Does Photoshop have any options to verify or configure this?
24 bit + alpha is actually 32 bits per pixel. Meaning you have the Red, Green, Blue and Alpha channels, each being 8 bit, allowing for 256 shades per channel translating to 256 x 256 x 256 x 256 possible colour combinations. That's what the "millions of colours" and "billions of colours" mean in certain graphics and video software.
As I understand it, there are three kinds of "24 bit" pngs:
24 bits with no transparency. No alpha information, truly 24 bits per pixel.
24 bits per pixel with alpha transparency. This would be 24 bits of color information with 8 bits of alpha (allows for various levels of transparency) - 32 bits per pixel total.
24 bits per pixel with binary transparency. This would be 24 bits of color information with 1 bit of alpha (transparent or not transparent) - 25 bits per pixel total.
24 bit PNG doesn't say much. An image has a pixel format. The pixel format describes the Colorspace used (such as CMYK, RGB) and bits per channel information (i.e. how many bits are allocated to represent each channel of the colorspace in use).
Go to File > File Info > Advanced. That should tell you what you are looking for.
After dissecting the exported file myself (from Photoshop CS6), I found that the "24 bit" file generated by Photoshop is actually still 8 bit. The RGBA is still one byte per channel. The IHDR PNG chunk still says that it's 8 bits per channel.
It's an 8 bit PNG.
The exported PNG also contains about 825 bytes of useless marketing text data (per PNG image).
See the image (with the byte for "bits per channel" selected):
See the specification for more details:
http://www.libpng.org/pub/png/spec/1.2/png-1.2.pdf

How many bits per component do I have to specify for pngcrunch-optimized 24bit PNG files with alphatransparency?

CGBitmapContextCreate takes an parameter that's not very obvious to me:
For example, for a 32-bit pixel format
and an RGB color space, you would
specify a value of 8 bits per
component.
I have created 24-bit PNG files with alphatransparency, and added them to Xcode. At compile time, Xcode optimizes those PNG tiles with pngcrunch.
So, when trying to make an graphics context out of such an image file on iPhone-OS, I need to specify the bits per component.
In this case, I would say they're 4 bits per component, although I dont know if alpha counts as an component.
It's 8 bits per component:
Red:8;
Green:8;
Blue:8;
Alpha:8;
That adds up to 32 bits per pixel. Your 24-bit png with transparency is 24-bits for RGB, plus 8 bits for transparency (the 'alpha channel').