TIP #166: READING AND WRITING THE PHOTO IMAGE ALPHA CHANNEL ============================================================= Version: $Revision: 1.12 $ Author: Donal K. Fellows Simon Bachmann State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: Wednesday, 19 November 2003 URL: https://tip.tcl-lang.org166.html Post-History: ------------------------------------------------------------------------- ABSTRACT ========== This TIP describes how to update the *image get* and *image put* subcommands so as to allow script-level access to the full alpha channel information that has been present in the photo image data model since Tk 8.3. RATIONALE =========== Alpha channels. We've had them in Tk's photo image data model (which is currently 8-bits-per-channel RGBA) for quite some time now. We can copy the alpha data around inside the image. We now display them correctly on deep-enough displays (many thanks to the people who have worked on that!) But can we write alpha data into an image? No. Not unless you have an image format handler that produces alpha data installed (e.g. the PNG from tkimg.) I think we should fix this so that people can read and write the full alpha data from scripts. PROPOSAL ========== I propose to update the /photoImageInstance/ *get* subcommand so that it takes an extra option *-withalpha* (to be placed after the coordinates). If that option is specified, the subcommand will return four values instead of three, with the fourth being the contents of the alpha channel for the pixel. Without this new option, the subcommand will return three values as before. I also propose to update the /photoImageInstance/ *put* subcommand so that alpha channel information may be specified in the following ways when using the list-of-lists-of-pixel-data format (the image-format format will be up to the particular image format code, as always.) * If a pixel is specified as being the empty string, that pixel will be set to be completely transparent. This parallels the interpretation of the empty string as transparency elsewhere within the core (notably in [canvas] items.) * Any standard Tk colour format (those accepted by *Tk_GetColor()* - e.g. /bisque2/ or /#abcdef/) may have the following suffix added - *@A* - where A is a fractional alpha value in the range 0.0 to 1.0 (which values correspond to fully transparent and fully opaque respectively.) * Any standard Tk colour format which does not have a *@A* suffix may have a *#XX* suffix, where XX is a pair of hex digits that specify an integer alpha value in the range 0 (fully transparent) to 255 (fully opaque). * Any standard Tk colour format which does not have a *@A* suffix nor a *#XX* suffix may have a *#X* suffix, where X is a single hex digit that specifies an integer alpha value in the range 0 (fully transparent) to 255 (fully opaque). This is expanded in range from 4 bits wide to 8 bits wide by multiplication by 0x11. * All pixel colours that have neither of the foregoing suffixes are to be interpreted as being fully opaque, which is the current situation anyway. * An additional pixel format is to be supported, consisting of a Tcl list of three or four integers in the range 0 to 255, being the value of the red channel, green channel, blue channel and alpha channel respectively in that order. An absent alpha channel is to be interpreted as full opacity. * Two additional pixel formats are to be supported, consisting of a *#* followed by exactly four or eight hexadecimal digits. When four digits are present, they will be interpreted as containing data for the /RGBA/ channels (in that order), and each digit will be expanded internally to 8-bits wide by multiplication by 0x11. When eight digits are present, they will be interpreted as containing data for the /RGBA/ channels (in that order) with two digits for each channel. It should also be possible to include alpha information in the data retrieved with the /photoImageInstance/ *data* subcommand. For this, I propose to make the list-of-lists-of-pixel-data format a regular photo image format (like PNG, GIF, PPM, etc.) with the name *default*. This format will have no file read/write capabilities. As before, the list-of-lists format will be the default choice for /photoImageInstance/ *data*, and the last one to be tried for /photoImageInstance/ *put*. The main benefit of this change is that it will be possible to request the *default* format explicitly with the *-format* option and - most important - to pass suboptions to the format handler. The *default* image data format shall accept the suboption *-colorformat* /type/ which specifies the format to be used to encode the color and alpha data for each pixel. Accepted values shall be *rgb* for the #RRGGBB format (the current format and default for the suboption), *rgba* for the #RRGGBBAA format, and *list* for the list format with four elements. This change will have two side effects: * The *-data* option to photo images will accept image data in the list-of-lists form as well. Currently only data in one of the registered file formats is accepted. * The underlying implementation will become simpler and cleaner. Finally, the /photoImageInstance/ *transparency* command's subcommands will be updated in the following way: * The *get* subcommand will be modified to take an extra option, *-alpha* (to be placed after the coordinates), that modifies the result to be the integral alpha value (in the range 0 to 255) for the specified pixel. Without the option, the result shall continue to be a boolean that is true exactly when the pixel is wholly transparent. * The *set* subcommand will be modified to take an extra option, *-alpha* (to be placed after the new value), that modifies the interpretation of the new value so that it is the integral alpha value to be set for the pixel. Without the option, the value will be interpreted as a boolean as before. EXAMPLES ========== Create a small image with a black border and a partially-transparent red area in the center. image create photo transExample transExample put black -to 0 0 10 10 transExample put red@.5 -to 2 2 8 8 Retrieve the alpha value of a pixel near the middle of the image created previously. set aVal [transExample transparency get 5 5 -alpha] Create a green box with a simple shadow effect image create photo foo # Make a simple graduated fill varying in alpha for the shadow for {set i 14} {$i>0} {incr i -1} { set i2 [expr {$i+30}] foo put [format black#%x [expr {15-$i}]] -to $i $i $i2 $i2 } # Put a solid green rectangle on top foo put #080 -to 0 0 30 30 Retrieve image data with alpha information in the list-of-lists form and create a new image with it. image create photo bar -file imageWithTransparency.png set imageData [bar data -format {default -colorformat rgba} # Inspect / modify / save data image create photo baz -data $imageData REFERENCE IMPLEMENTATION ========================== Branch tip-166 on fossil. COPYRIGHT =========== This document is placed in the public domain. ------------------------------------------------------------------------- TIP AutoGenerator - written by Donal K. Fellows