Tk Img Extensions
Check-in [c8336949ad]
Not logged in
Tcl 2014 Conference, Portland/OR, US, Nov 10-14
Send your abstracts to tclconference@googlegroups.com by Sep 8.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Replaced workaround for adding alpha channel with png_set_add_alpha for lower memory consumption.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:c8336949ad3db9268c385c5523524a4cf496a795
User & Date: obermeier 2013-10-02 18:12:59
Context
2013-10-03
09:38
Use xerrorhandler on all platforms, not only UNIX. check-in: 88f406c8e9 user: nijtmans tags: trunk
2013-10-02
18:12
Replaced workaround for adding alpha channel with png_set_add_alpha for lower memory consumption. check-in: c8336949ad user: obermeier tags: trunk
2013-10-01
14:47
Eliminate a few compiler warnings, discovered by gcc 4.8.1 check-in: 31ff0acad8 user: nijtmans tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to png/png.c.

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
...
451
452
453
454
455
456
457

458
459
460
461








462
463
464
465
466
467
468
...
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
    unsigned int I;
    png_uint_32 info_width, info_height;
    int bit_depth, color_type, interlace_type;
    int intent;
    int result = TCL_OK;
    int matte;
    double alpha;
    unsigned char *addAlphaImg = NULL;
    int useAlpha = 0;
    int addAlpha = 0;

    if (ParseFormatOpts(interp, format, &matte, &alpha) != TCL_OK) {
        return TCL_ERROR;
    }

................................................................................
        block.offset[2] = 4;
    }

    if (png_set_expand != NULL) {
        png_set_expand(png_ptr);
    }

    png_read_update_info(png_ptr,info_ptr);
    block.pixelSize = png_get_channels(png_ptr, info_ptr);
    block.pitch = png_get_rowbytes(png_ptr, info_ptr);

    if ((color_type & PNG_COLOR_MASK_COLOR) == 0) {
        /* grayscale image */
        block.offset[1] = 0;
        block.offset[2] = 0;
    }
    block.width = width;
    block.height = height;
................................................................................
        }
    } else {
        /* Image has no alpha channel.
           If a valid alpha multiply has been specified, add an alpha channel to the image.
           The matte flag is ignored. */
        if ( alpha >= 0.0) {
            addAlpha = 1;

        } else {
            block.offset[3] = 0;
        }
    }









    if (png_get_sRGB && png_get_sRGB(png_ptr, info_ptr, &intent)) {
        png_set_sRGB(png_ptr, info_ptr, intent);
    } else if (png_get_gAMA) {
        double gamma;
        if (!png_get_gAMA(png_ptr, info_ptr, &gamma)) {
            gamma = 0.45455;
................................................................................
    for(I=0;I<info_height;I++) {
        png_data[I]= ((char *) png_data) + (sizeof(char *) * info_height +
                I * block.pitch);
    }

    png_read_image(png_ptr,(png_bytepp) png_data);

    /* TODO:
       It seems the libpng way of adding an alpha channel would be to use
       the png_set_add_alpha function and then get the updated image
       information via png_read_update_info.
       As the png_set_add_alpha function is not (yet) available in the Stubs table,
       we allocate memory for an image with alpha channel and copy over the data 
       before putting the image into a Tk photo.

           png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
           png_read_update_info (png_ptr, info_ptr);
    */

    if (addAlpha) {
        unsigned char *srcPtr, *destPtr;
        block.pixelSize++;
        block.pitch = block.pixelSize * width;
        block.offset[3] = block.pixelSize - 1;
        addAlphaImg= (unsigned char *) ckalloc(info_height * block.pitch);
        destPtr = addAlphaImg + srcX*block.pixelSize;
        srcPtr  = (unsigned char *) (png_data[srcY]+srcX*block.pixelSize);
        if (block.pixelSize == 2) {
            for(I=0;I<height*width;I++) {
                *destPtr++ = *srcPtr++;
                *destPtr++ = alpha * 255;
            }
        } else {
            for(I=0;I<height*width;I++) {
                *destPtr++ = *srcPtr++;
                *destPtr++ = *srcPtr++;
                *destPtr++ = *srcPtr++;
                *destPtr++ = alpha * 255;
            }
        }
        block.pixelPtr=addAlphaImg + srcX*block.pixelSize;
    } else {
        block.pixelPtr=(unsigned char *) (png_data[srcY]+srcX*block.pixelSize);
    }

    if (useAlpha) {
        unsigned char * alphaPtr = block.pixelPtr + block.offset[3];
        for(I=0;I<height*width;I++) {
            *alphaPtr = alpha * *alphaPtr;
            alphaPtr += block.offset[3] + 1 ;
        }
................................................................................
    }

    if (tkimg_PhotoPutBlock(interp, imageHandle, &block, destX, destY, width, height,
            block.offset[3]? TK_PHOTO_COMPOSITE_OVERLAY: TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) {
        result = TCL_ERROR;
    }

    if (addAlphaImg) {
        ckfree((char *) addAlphaImg);
    }
    ckfree((char *) png_data);
    png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);

    return result;
}

static int
ChnWrite (interp, filename, format, blockPtr)
    Tcl_Interp *interp;
    const char *filename;







<







 







<
<
<
<







 







>




>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<







 







<
<
<


<







353
354
355
356
357
358
359

360
361
362
363
364
365
366
...
416
417
418
419
420
421
422




423
424
425
426
427
428
429
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
...
480
481
482
483
484
485
486



































487

488
489
490
491
492
493
494
...
495
496
497
498
499
500
501



502
503

504
505
506
507
508
509
510
    unsigned int I;
    png_uint_32 info_width, info_height;
    int bit_depth, color_type, interlace_type;
    int intent;
    int result = TCL_OK;
    int matte;
    double alpha;

    int useAlpha = 0;
    int addAlpha = 0;

    if (ParseFormatOpts(interp, format, &matte, &alpha) != TCL_OK) {
        return TCL_ERROR;
    }

................................................................................
        block.offset[2] = 4;
    }

    if (png_set_expand != NULL) {
        png_set_expand(png_ptr);
    }





    if ((color_type & PNG_COLOR_MASK_COLOR) == 0) {
        /* grayscale image */
        block.offset[1] = 0;
        block.offset[2] = 0;
    }
    block.width = width;
    block.height = height;
................................................................................
        }
    } else {
        /* Image has no alpha channel.
           If a valid alpha multiply has been specified, add an alpha channel to the image.
           The matte flag is ignored. */
        if ( alpha >= 0.0) {
            addAlpha = 1;
            png_set_add_alpha(png_ptr, (unsigned int)(alpha*255), PNG_FILLER_AFTER);
        } else {
            block.offset[3] = 0;
        }
    }

    /* Note: png_read_update_info may only be called once per info_ptr !! */
    png_read_update_info(png_ptr,info_ptr);
    block.pixelSize = png_get_channels(png_ptr, info_ptr);
    block.pitch = png_get_rowbytes(png_ptr, info_ptr);
    if (addAlpha) {
        block.offset[3] = block.pixelSize - 1;
    }

    if (png_get_sRGB && png_get_sRGB(png_ptr, info_ptr, &intent)) {
        png_set_sRGB(png_ptr, info_ptr, intent);
    } else if (png_get_gAMA) {
        double gamma;
        if (!png_get_gAMA(png_ptr, info_ptr, &gamma)) {
            gamma = 0.45455;
................................................................................
    for(I=0;I<info_height;I++) {
        png_data[I]= ((char *) png_data) + (sizeof(char *) * info_height +
                I * block.pitch);
    }

    png_read_image(png_ptr,(png_bytepp) png_data);




































    block.pixelPtr=(unsigned char *) (png_data[srcY]+srcX*block.pixelSize);


    if (useAlpha) {
        unsigned char * alphaPtr = block.pixelPtr + block.offset[3];
        for(I=0;I<height*width;I++) {
            *alphaPtr = alpha * *alphaPtr;
            alphaPtr += block.offset[3] + 1 ;
        }
................................................................................
    }

    if (tkimg_PhotoPutBlock(interp, imageHandle, &block, destX, destY, width, height,
            block.offset[3]? TK_PHOTO_COMPOSITE_OVERLAY: TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) {
        result = TCL_ERROR;
    }




    ckfree((char *) png_data);
    png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);

    return result;
}

static int
ChnWrite (interp, filename, format, blockPtr)
    Tcl_Interp *interp;
    const char *filename;