-
Notifications
You must be signed in to change notification settings - Fork 634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggested Palette #627
Comments
sBIT, not sPLT, is intended for this. If, instead of just using a bit depth reduction where every component value is one of the exact values [0..2^B-1]/(2^B-1) you choose different component values then you can't use sBIT and can only convey the information with sPLT. E.g. when you reduce a particular component to 5 bits you have component values c/31; 0/31,1/31,...,30/31,31/31. The 5-bit values "c" are converted into 8 bits values by multiplying by either 8 (multiple; bit-shift left by 3) or 255/31 (scaling.) Then you just set the sBIT for that component to 5. However if you determine that you really need 40 levels for that component you could, in theory, record those values in sPLT but sPLT records a full colour, not a single component, so if the other channels need 40 levels too the sPLT would end up with 404040 entries. At 6 bytes per entry that's likely to destroy any compression gain in the IDAT! So in that case you use a higher sBIT value, say 6, convert all the component values to the corresponding 8-bit values (64 of them) but just use the 40 required for the image. Because of the way LZ77 compression works this will still work just fine; the compression improvement comes from reducing the number of byte values in the uncompressed data stream, not what those values are! There is likely to be a significant improvement in using the same sBIT for all three or four channels when scaling because that means the byte values are the same for each component. Scaling is recommended in PNG v2 (specification 1.2) but shift left is allowed and avoids this problem when component bit depths differ. Note that the current W3C proposal for PNG v3 mandates scaling in most cases when a cICP chunk is present; multply/shift left is only mandated for the new "narrow range" images. sPLT is really intended for cases where a 8 or 16-bit per component image may need to be displayed on a palette mapped display. Normally it's better to just add a PLTE chunk to give the optimized palette but sPLT is more general; for example it accommodates output with 10-bit palettes. Palettisation of RGB data is extremely well researched. Google "python palette reduction code". It's built in to the PIL. Simply reducing the number of colours, for example to about 250,000 (equivalent to sBIT 6 for each component) is likely to give improved compression and, so long dithering is used, is unlikely to degrade the quality of most continuous tone images. Knowing the colours which exist in the scene is even better. For business graphics it is normally possible to come up with under 256 colours (which can be stored in a PLTE). This is because the program which generates the graphics knows which are the solid colours (so must be preserved) and can generate a small set of ditherable colours for shading. Likewise in 3D rendering it may be possible to identify the primary colours of the foreground objects and favour these over different colours in an out-of-focus background. Always dither the image when doing this kind of reduction. |
I'm trying to apply custom color depths to channels, e.g. 5, 6 or 7 bit. This may lead to file size reduction may up to 50% while preserving enough quality. Currently it's implemented as additional encoding\decoding steps.
Do I understand it correctly that suggested palettes were designed for this purpose? 5, 6 or 7 bit numbers can be represented by 8 bit as required by the spec.
If yes, could you give pointers how to specify suggested palettes using python?
Thanks
The text was updated successfully, but these errors were encountered: