TIP 166: Reading and Writing the Photo Image Alpha Channel

Login
FlightAware bounty program for improvements to Tcl and certain Tcl packages.
Author:         Donal K. Fellows <donal.k.fellows@man.ac.uk>
Author:         Simon Bachmann <simonbachmann@bluewin.ch>
State:          Final
Type:           Project
Vote:           Done
Created:        19-Nov-2003
Post-History:   
Keywords:       Tk,image get,image put
Tcl-Version:    8.7

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.