Version 2 of fast alpha blending (transparency)

Updated 2003-12-06 14:31:06

Here is a quick and dirty alpha blending code, for achieving a fade in/out transition between two images. It is coded is C, with critcl for speed, but the algorithm is very simple, a mixing of the pixels from two images returning in a third.

 package require Img
 package require critcl
 package provide alphablend 1.0 

 critcl::config outdir .
 critcl::cheaders -I/usr/local/include
 critcl::ccode {
    #include <tcl.h>
    #include <tk.h>
 }

 ::critcl::ccommand blend_img { dummy ip objc objv } {
    Tk_PhotoHandle ph[3];
    Tk_PhotoImageBlock ib[3];
    Tcl_Obj *obj;
    int i,j,k,blend,pxsiz,pitch;
    unsigned char *p[3];

    if (objc != 5) {
        Tcl_WrongNumArgs(ip,1,objv,"img1 img2 img3 blend");
        return TCL_ERROR;
    }
    ph[0] = Tk_FindPhoto(ip,Tcl_GetString(objv[1]));
    ph[1] = Tk_FindPhoto(ip,Tcl_GetString(objv[2]));
    ph[2] = Tk_FindPhoto(ip,Tcl_GetString(objv[3]));
    Tcl_GetIntFromObj(ip,objv[4],&blend);
    Tk_PhotoGetImage(ph[0],ib);
    Tk_PhotoGetImage(ph[1],ib+1);
    Tk_PhotoGetImage(ph[2],ib+2);
    p[0] = ib[0].pixelPtr;
    p[1] = ib[1].pixelPtr;
    p[2] = ib[2].pixelPtr;
    pxsiz = ib[0].pixelSize;
    pitch = ib[0].pitch;
    for (i=0;i<ib[0].height;i++) {
        for (j=0;j<ib[0].width;j++) {
            *(p[2]+i*pitch+j*pxsiz) =
                (*(p[0]+i*pitch+j*pxsiz) * blend +
                *(p[1]+i*pitch+j*pxsiz) * (100-blend)) / 100;
            *(p[2]+i*pitch+j*pxsiz+1) = 
                (*(p[0]+i*pitch+j*pxsiz+1) * blend +
                *(p[1]+i*pitch+j*pxsiz+1) * (100-blend)) / 100;
            *(p[2]+i*pitch+j*pxsiz+2) = 
                (*(p[0]+i*pitch+j*pxsiz+2) * blend +
                *(p[1]+i*pitch+j*pxsiz+2) * (100-blend)) / 100;
        }       
    }   
    Tk_PhotoPutBlock(ph[2],ib+2,0,0,ib[0].width,ib[0].height,1);
    return TCL_OK;
 }   

 set blend 100
 pack [canvas .c -width 800 -height 600]
 pack [scale .sc -variable blend -orient hor] \
    -fill x -expand 1
 pack [button .b -text exit -command exit] -padx 30 -pady 20
 update

 # create a list with your pictures (the first two will be loaded)
 set images {
 /root/quadros/harvesters.jpg
 /root/quadros/gogh29.jpg
 /root/quadros/beggars.jpg
 /root/quadros/brueg1-8.jpg
 /root/quadros/hunters.jpg
 }

 proc load_imgs {} {
    global images 
    foreach i {1 2} {
        global img$i
        set fn [lindex $images $i]
        set img$i \
            [image create photo -file $fn -width 640 -height 480]
    }       
 }   

 load_imgs
 set img3 [image create photo]
 $img3 copy $img1

 set updwait 0

 proc update_img {blend} {
    global img1 img2 img3 updwait
    # don't let it go too fast
    if {$updwait} {
        return
    }   
    incr updwait
    blend_img $img1 $img2 $img3 $blend
    after 50 {set updwait 0}
 }   
 .sc config -command update_img
 .c create image 50 50 -anchor nw -image $img3

RildoPragana