I have an image with grayscale background and 2 thin lines (1 pixel wide) drawn in color. I'm trying to use various JPEG compression table (luminance and chrominance) to get the best possible result while staying under a certain file size.
The grayscale background compresses well and looks decent. The thin vertical and horizontal color lines get mutilated / smeared. The current JPEG algorithm uses 2x2 sub-sampling on the Cb and Cr channels and the chrominance compression table is fairly aggressive (high compression).
Is there any way to embed a "BMP" type data into JPEG image. Basically specify a color for specific pixels to be applied after the JPEG is de-compressed?
Any other ways clean up how thin color lines get encoded / decoded in JPEG without increasing the overall file size by a lot.
P.S. I'm testing all this stuff in Matlab.
Related
So I just wanted to ask this question because there is a quality slider for png in Adobe Photoshop.
Now the reason why I find this very confusing is I know that PNG is a lossless format.
I'm not sure what is used to measure objective quality, by that I mean how much information is contained in images. I'm assuming it's either dpi or bit depth or file size for the same format?
Now, I know that the same lossless compression for the same image can have varying quality (bit depth and dpi).
This is because you can do an in between step and encode it into a lossy format like jpg, before converting back into a lossless format like png.
For example, we have a picture of some dice taken by a camera in a lossless png format it's the original quality let's say 360dpi horizontal and vertical resolution and 24 bit depth.
Then we can encode it into jpg (which is using lossy compression) and presumably the quality would go down slightly from averaging pixels, as it is lossy compression and it would lower the quality to something like 200dpi horizontal and vertical resolution and 12 bit depth.
Then we encode that back into png again (lossless compression) and the final quality would be 200dpi horizontal and vertical resolution and 12 bit depth.
So now we have two pngs for the same image which are in a lossless format, the original one and our one that was encoded from a jpg, that have different quality.
The point I'm trying to make is that I think this is why two images using lossless compression can have differing quality, even though lossless compression does not remove any information, because one of the lossless compression images could have just been encoded from a lossy format. Information can be removed from lossless formats by encoding to and from a lossy format.
So now back to the question, is this why Photoshop has a quality slider for PNG images?
For qualities below 100% say 80%, is Photoshop encoding into something lossy like jpg and then back into the lossless png so that the files can have different quality and thus, a different file size for the same image?
I've also read something on wikipedia about PNG being able to perform lossy compression as well, so is that what is happening instead?
https://en.wikipedia.org/wiki/Portable_Network_Graphics#Lossy_PNG_compression
I'm just confused about it.
Photoshop may be reducing color depth as described in the the wiki you included in your question:
reducing color depth, either:
use a palette (instead of RGB) if the image has 256 or fewer colors,
use a smaller palette, if the image has 2, 4, or 16 colors, or
(optionally) lossily discard some of the data in the original image
The original PNG image is 800x1200 and takes up about 34K. After the images is resized by GraphicsMagick to 320x480 size, the resulting images takes up approximately 37K. (For comparison, if the image is resized with Paint on Windows 7 then the resulting image is 40K.) What gives? The whole point of resizing an image was to save space. How should GraphicsMagick be used to shrink the image size?
PNG is a lossless format and compresses the image data by first performing a step called prediction and then applying the same algorithm used in zlib. The prediction step is a crucial one in order to effectively compress the file, and it is based on the values of earlier neighbors pixels.
So, suppose you have a large PNG in black & white (by that I really mean only black and white, some people confuse that by grayscale sometimes). Also suppose it is not a tiny checkerboard pattern. In many regions of this image, you will have a relatively large white region, and then a relatively large black region, and so on. When the predictor is inside one of these large regions, it has no trouble to correctly predict that the current pixel intensity is exactly equal to the last one. This makes it easier to better compress the data describing your image.
Now, let us downscale this black & white image using some resampling filter different than nearest neighbor (let's say Lanczos). This has a great chance to turn your black & white image into a grayscale one, which has a much greater intensity range. This potentially makes the job of the predictor much harder, and thus the final file size might be larger.
For instance here is a black & white 256x256 PNG image which takes 5440 bytes, a resizing of it (using 3-lobed Lanczos) to 120x120 which now takes 7658 bytes, and another resizing (using nearest neighbor) to 120x120 which occupies 2467 bytes.
PNG is a compressed format. Sometimes trying to compress a maximally compressed item actually results in a larger item. So if the 800x1200 is resized to a smaller size, but the result retains everything that was in the original, because the original is already as minimal as possible, you could see this happen. To demonstrate this, try using 7zip to compress some data with ultra compression. Then try compressing the compressed file. Often the second compressed file will be larger than the first.
I have a matlab code and it generates a .png image of 1024*768 resolution. The images are about 450KB in size and I need to know how to optimise and compress these images using matlab.
Can't I play with the quality as in JPEG ?
I read the imwrite manual and don`t seem to find a good way to do this.
Is there any way to achieve it in matlab ?
By design PNG files are lossless - there is no 'quality' to be adjusted (it's probably why a mod changed your question title).
You can reduce the number of colors in the image (the color depth) which will in turn reduce filesize (PNG-8 instead of PNG-24, for example), but the whole point of PNG is it produces lossless images, so there is simple no quality value a la JPEG.
Taken from the manual :
A parameter of input in case it is JPEG:
'Quality' - A number between 0 and 100; higher numbers mean higher quality (less image degradation due to compression), but the resulting file size is larger.
imwrite(x,'c:\1.jpg','Quality',10)
edit: Sorry, I answered this one while the title was JPEG and not PNG.
PNG doesn't support any quality settings - it is a lossless format. The compression it applies is generally as good as possible.
JPEGs are smaller in size than PNGs. So, I thought that if I can make a specific region in a JPEG-file transparent, with some code, maybe I can save some bytes.
So does anyone know how to achieve this with for example PHP or JavaScript?
No. You can't do this. JPGs do not support alpha channels and have no capacity to designate certain colors as transparent either (GIF-style).
There's several issues with this, all of them have to do with that JPEG is a lossy compression format. The JPEG format is optimized for natural images and sharp edges will get blurred. If you intend that a specific pixel should have the value #d67fff there's no guarantee that after color conversion, FDCT, quantization, IDCT and color conversion, the pixel still will have that value. There's also a strong possibility that that pixel value will occur in areas that you don't want.
No. JPEG does not support transparency and is not likely to do so any time
soon. http://www.faqs.org/faqs/jpeg-faq/part1/section-12.html
You cannot do that, the client renders the image and doesn't know that you want it to treat that color as transparent (plus various compression methods on jpeg wouldn't work well with transparencies anyway).
I believe you can go with an 8-bit custom-pallet png, should save you a lot of space. Otherwise 24-bit PNG is your only high color option.
You can convert your image to SVG containing a color information as JPEG and an alpha channel as grayscale mask. Here is a tool I wrote to do it https://github.com/igrmk/transpeg
In Fireworks, when you export a PNG8 file with alpha transparency, the resulting file will be something like this:
png8-fireworks.png: PNG image data, 500 x 500, 8-bit colormap, non-interlaced
If you convert a 32bit PNG using other tools (PNGOUT, Smush.it) the result looks like this:
png24-smushit.png: PNG image data, 500 x 500, 8-bit/color RGBA, non-interlaced
png8-pngout.png: PNG image data, 500 x 500, 8-bit/color RGBA, non-interlaced
What exactly is the difference? They both have alpha transparency, but the Fireworks file is 8KB while the others are 20KB. Now the Fireworks file in noticeably lower quality (namely with banding on gradients).
For some images the PNG8+alpha from Fireworks works great and has a super small file size comparatively. I just haven't been able to figure out what Fireworks is doing and how it is different than the other methods.
The PNG8 file is a very efficient format. It finds the unique colors in the image and only saves those in a small palette. The cool part is that it also saves alpha transparency in the palette with each color. (If you have three pure reds (#FF0000) in your image, but each has a different alpha value, let's say 255, 128, 65, it will save three entries in the palette.
You can also in Fireworks choose to limit the palette size to a power of 2, so you can reduce colors used for more savings. Often a 256 color image will look fine at 64 colors and save a lot of weight.
from sites of both tools:
PNGOUT:
It won't convert an image to a color type or bit depth that cannot losslessly store the image.
It won't reduce the number of colors being used in an image, or convert the colors to grayscale unless all the colors correspond to PNG grayscale values already.
Smush.it:
It is a "lossless" tool […]
Neither gives you a 256 paletted png: it's the diff between "colormap" (= palette) and "rgba" (truecolor = R of 2^8 x G of 2^8 x B of 2^8 x Alpha of 2^8, with 2^8 = 256).
Fireworks does.
PNG-8 means 8 bits per pixel, which means it can only display 256 different colours (from a pallet).
24 and 32 bits per pixel allow you to use far more colours (and hence get nice smooth gradients) but come at the cost of filesize.