Tk Source Code

Check-in [fa1a2028]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Implemented metadata output of gif comment - crashes test image-15.1 - megadata write with Tk_PhotoGetMetadata does not work, as the photo handle is not available within the write function.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-529-image-metadata
Files: files | file ages | folders
SHA3-256: fa1a20281b544bb04b007e650b96d0954453b04c77be031343660715c4c31d0a
User & Date: oehhar 2018-12-14 14:09:43
Context
2018-12-19
11:18
TIP529: option -metadata is now dict. Test crash apparently fixed by trunk merge check-in: 9f5d05d9 user: oehhar tags: tip-529-image-metadata
2018-12-14
14:09
Implemented metadata output of gif comment - crashes test image-15.1 - megadata write with Tk_PhotoGetMetadata does not work, as the photo handle is not available within the write function. check-in: fa1a2028 user: oehhar tags: tip-529-image-metadata
2018-12-11
10:35
Corrected indents and formatting check-in: af5db475 user: oehhar tags: tip-529-image-metadata
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tk.decls.

1064
1065
1066
1067
1068
1069
1070








1071
1072
1073
1074
1075
1076
1077
# build against legacy sources.
declare 272 {
    void Tk_CreateOldImageType(const Tk_ImageType *typePtr)
}
declare 273 {
    void Tk_CreateOldPhotoImageFormat(const Tk_PhotoImageFormat *formatPtr)
}









# Define the platform specific public Tk interface.  These functions are
# only available on the designated platform.

interface tkPlat

################################






>
>
>
>
>
>
>
>







1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
# build against legacy sources.
declare 272 {
    void Tk_CreateOldImageType(const Tk_ImageType *typePtr)
}
declare 273 {
    void Tk_CreateOldPhotoImageFormat(const Tk_PhotoImageFormat *formatPtr)
}
# New in Tk8.7
declare 274 {
    Tcl_Obj *Tk_PhotoGetMetadata(Tk_PhotoHandle handle);
}
declare 275 {
    void Tk_PhotoSetMetadata(Tk_PhotoHandle handle,Tcl_Obj *metadata);
}


# Define the platform specific public Tk interface.  These functions are
# only available on the designated platform.

interface tkPlat

################################

Changes to generic/tkDecls.h.

874
875
876
877
878
879
880




881
882
883
884
885
886
887
888
....
1160
1161
1162
1163
1164
1165
1166


1167
1168
1169
1170
1171
1172
1173
....
1720
1721
1722
1723
1724
1725
1726




1727
1728
1729
1730
1731
1732
1733
/* 271 */
EXTERN Tcl_Interp *	Tk_Interp(Tk_Window tkwin);
/* 272 */
EXTERN void		Tk_CreateOldImageType(const Tk_ImageType *typePtr);
/* 273 */
EXTERN void		Tk_CreateOldPhotoImageFormat(
				const Tk_PhotoImageFormat *formatPtr);





typedef struct {
    const struct TkPlatStubs *tkPlatStubs;
    const struct TkIntStubs *tkIntStubs;
    const struct TkIntPlatStubs *tkIntPlatStubs;
    const struct TkIntXlibStubs *tkIntXlibStubs;
} TkStubHooks;

................................................................................
    int (*tk_PhotoPutZoomedBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 267 */
    int (*tk_PhotoSetSize) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 268 */
    long (*tk_GetUserInactiveTime) (Display *dpy); /* 269 */
    void (*tk_ResetUserInactiveTime) (Display *dpy); /* 270 */
    Tcl_Interp * (*tk_Interp) (Tk_Window tkwin); /* 271 */
    void (*tk_CreateOldImageType) (const Tk_ImageType *typePtr); /* 272 */
    void (*tk_CreateOldPhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 273 */


} TkStubs;

extern const TkStubs *tkStubsPtr;

#ifdef __cplusplus
}
#endif
................................................................................
	(tkStubsPtr->tk_ResetUserInactiveTime) /* 270 */
#define Tk_Interp \
	(tkStubsPtr->tk_Interp) /* 271 */
#define Tk_CreateOldImageType \
	(tkStubsPtr->tk_CreateOldImageType) /* 272 */
#define Tk_CreateOldPhotoImageFormat \
	(tkStubsPtr->tk_CreateOldPhotoImageFormat) /* 273 */





#endif /* defined(USE_TK_STUBS) */

/* !END!: Do not edit above this line. */

/* Functions that don't belong in the stub table */
#undef Tk_MainEx






>
>
>
>
|







 







>
>







 







>
>
>
>







874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
....
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
....
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
/* 271 */
EXTERN Tcl_Interp *	Tk_Interp(Tk_Window tkwin);
/* 272 */
EXTERN void		Tk_CreateOldImageType(const Tk_ImageType *typePtr);
/* 273 */
EXTERN void		Tk_CreateOldPhotoImageFormat(
				const Tk_PhotoImageFormat *formatPtr);
/* 274 */
EXTERN Tcl_Obj *Tk_PhotoGetMetadata(Tk_PhotoHandle handle);
/* 275 */
EXTERN void Tk_PhotoSetMetadata(Tk_PhotoHandle handle,Tcl_Obj *metadata);
				
typedef struct {
    const struct TkPlatStubs *tkPlatStubs;
    const struct TkIntStubs *tkIntStubs;
    const struct TkIntPlatStubs *tkIntPlatStubs;
    const struct TkIntXlibStubs *tkIntXlibStubs;
} TkStubHooks;

................................................................................
    int (*tk_PhotoPutZoomedBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 267 */
    int (*tk_PhotoSetSize) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 268 */
    long (*tk_GetUserInactiveTime) (Display *dpy); /* 269 */
    void (*tk_ResetUserInactiveTime) (Display *dpy); /* 270 */
    Tcl_Interp * (*tk_Interp) (Tk_Window tkwin); /* 271 */
    void (*tk_CreateOldImageType) (const Tk_ImageType *typePtr); /* 272 */
    void (*tk_CreateOldPhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 273 */
    Tcl_Obj *(*tk_PhotoGetMetadata) (Tk_PhotoHandle handle); /* 274 */
    void (*tk_PhotoSetMetadata) (Tk_PhotoHandle handle,Tcl_Obj *metadata); /* 275 */
} TkStubs;

extern const TkStubs *tkStubsPtr;

#ifdef __cplusplus
}
#endif
................................................................................
	(tkStubsPtr->tk_ResetUserInactiveTime) /* 270 */
#define Tk_Interp \
	(tkStubsPtr->tk_Interp) /* 271 */
#define Tk_CreateOldImageType \
	(tkStubsPtr->tk_CreateOldImageType) /* 272 */
#define Tk_CreateOldPhotoImageFormat \
	(tkStubsPtr->tk_CreateOldPhotoImageFormat) /* 273 */
#define Tk_PhotoGetMetadata \
	(tkStubsPtr->tk_PhotoGetMetadata) /* 274 */
#define Tk_PhotoSetMetadata \
	(tkStubsPtr->tk_PhotoSetMetadata) /* 275 */

#endif /* defined(USE_TK_STUBS) */

/* !END!: Do not edit above this line. */

/* Functions that don't belong in the stub table */
#undef Tk_MainEx

Changes to generic/tkImgGIF.c.

161
162
163
164
165
166
167


168
169
170
171
172
173
174
175
176
177
...
395
396
397
398
399
400
401


402
403
404
405
406
407
408
...
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
547
548
...
711
712
713
714
715
716
717
718

























































719
720
721






722
723
724
725
726
727
728
729






730
731
732







































733
734
735
736
737
738
739
...
743
744
745
746
747
748
749

750
751
752
753
754
755
756
...
933
934
935
936
937
938
939
940

941
942



943
944
945
946
947
948
949
950
951
952

953
954














955
956
957
958
959

960
961
962
963
964
965
966
967
968
969

970
971
972
973
974
975
976
#define MAX_LWZ_BITS		12
#define LM_to_uint(a,b)		(((b)<<8)|(a))

/*
 * Prototypes for local functions defined in this file:
 */



static int		DoExtension(GIFImageConfig *gifConfPtr,
			    Tcl_Channel chan, int label, unsigned char *buffer,
			    int *transparent);
static int		GetCode(Tcl_Channel chan, int code_size, int flag,
			    GIFImageConfig *gifConfPtr);
static int		GetDataBlock(GIFImageConfig *gifConfPtr,
			    Tcl_Channel chan, unsigned char *buf);
static int		ReadColorMap(GIFImageConfig *gifConfPtr,
			    Tcl_Channel chan, int number,
			    unsigned char buffer[MAXCOLORMAPSIZE][4]);
................................................................................
    int fileWidth, fileHeight, imageWidth, imageHeight;
    unsigned int nBytes;
    int index = 0, argc = 0, i, result = TCL_ERROR;
    Tcl_Obj **objv;
    unsigned char buf[100];
    unsigned char *trashBuffer = NULL;
    int bitPixel;


    unsigned char colorMap[MAXCOLORMAPSIZE][4];
    int transparent = -1;
    static const char *const optionStrings[] = {
	"-index", NULL
    };
    GIFImageConfig gifConf, *gifConfPtr = &gifConf;

................................................................................
     * the GIF.
     */

    if (Tk_PhotoExpand(interp, imageHandle,
	    destX + width, destY + height) != TCL_OK) {
	return TCL_ERROR;
    }












    /*
     * Search for the frame from the GIF to display.
     */

    while (1) {
	if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {
	    /*
	     * Premature end of image.
	     */

	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "premature end of image data for this index", -1));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "PREMATURE_END",
		    NULL);
	    goto error;
	}

	switch (buf[0]) {
	case GIF_TERMINATOR:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "no image data for this index", -1));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "NO_DATA", NULL);
	    goto error;

	case GIF_EXTENSION:
	    /*
	     * This is a GIF extension.
	     */

	    if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"error reading extension function code in GIF image",
			-1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
			NULL);
		goto error;
	    }
	    if (DoExtension(gifConfPtr, chan, buf[0],
		    gifConfPtr->workingBuffer, &transparent) < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"error reading extension in GIF image", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
			NULL);
		goto error;
	    }
	    continue;
................................................................................
	ckfree(block.pixelPtr);
    }

    /*
     * We've successfully read the GIF frame (or there was nothing to read,
     * which suits as well). We're done.
     */


























































    Tcl_SetObjResult(interp, Tcl_NewStringObj(tkImgFmtGIF.name, -1));
    result = TCL_OK;







  error:
    /*
     * If a trash buffer has been allocated, free it now.
     */

    if (trashBuffer != NULL) {
	ckfree(trashBuffer);
    }






    return result;
}
 







































/*
 *----------------------------------------------------------------------
 *
 * StringMatchGIF --
 *
 *	This function is invoked by the photo image type to see if an object
 *	contains image data in GIF format.
................................................................................
 *	data, and 0 otherwise.
 *
 * Side effects:
 *	The size of the image is placed in widthPtr and heightPtr.
 *
 *----------------------------------------------------------------------
 */


static int
StringMatchGIF(
    Tcl_Obj *dataObj,		/* the object containing the image data */
    Tcl_Obj *format,		/* the image format object, or NULL */
    int *widthPtr,		/* where to put the string width */
    int *heightPtr,		/* where to put the string height */
................................................................................
 
static int
DoExtension(
    GIFImageConfig *gifConfPtr,
    Tcl_Channel chan,
    int label,
    unsigned char *buf,
    int *transparent)

{
    int count;




    switch (label) {
    case 0x01:			/* Plain Text Extension */
	break;

    case 0xff:			/* Application Extension */
	break;

    case 0xfe:			/* Comment Extension */
	do {

	    count = GetDataBlock(gifConfPtr, chan, buf);
	} while (count > 0);














	return count;

    case 0xf9:			/* Graphic Control Extension */
	count = GetDataBlock(gifConfPtr, chan, buf);
	if (count < 0) {

	    return 1;
	}
	if ((buf[0] & 0x1) != 0) {
	    *transparent = buf[3];
	}

	do {
	    count = GetDataBlock(gifConfPtr, chan, buf);
	} while (count > 0);
	return count;

    }

    do {
	count = GetDataBlock(gifConfPtr, chan, buf);
    } while (count > 0);
    return count;
}






>
>


|







 







>
>







 







|
>
>
>
>
>
>
>
>
>
>
>





|
<
<
<
<
<
<
<
<



|











|
<
<
<
<
<


|
|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>








>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







|
>


>
>
>









|
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>





<
<
<
<
<
>







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
...
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
547
548
549
550
...
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
...
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
....
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094





1095
1096
1097
1098
1099
1100
1101
1102
#define MAX_LWZ_BITS		12
#define LM_to_uint(a,b)		(((b)<<8)|(a))

/*
 * Prototypes for local functions defined in this file:
 */

static int		ReadOneByte(Tcl_Interp *interp,
			    GIFImageConfig *gifConfPtr, Tcl_Channel chan);
static int		DoExtension(GIFImageConfig *gifConfPtr,
			    Tcl_Channel chan, int label, unsigned char *buffer,
			    int *transparent, Tcl_Obj *metadata);
static int		GetCode(Tcl_Channel chan, int code_size, int flag,
			    GIFImageConfig *gifConfPtr);
static int		GetDataBlock(GIFImageConfig *gifConfPtr,
			    Tcl_Channel chan, unsigned char *buf);
static int		ReadColorMap(GIFImageConfig *gifConfPtr,
			    Tcl_Channel chan, int number,
			    unsigned char buffer[MAXCOLORMAPSIZE][4]);
................................................................................
    int fileWidth, fileHeight, imageWidth, imageHeight;
    unsigned int nBytes;
    int index = 0, argc = 0, i, result = TCL_ERROR;
    Tcl_Obj **objv;
    unsigned char buf[100];
    unsigned char *trashBuffer = NULL;
    int bitPixel;
    Tcl_Obj *metadata;
    int gifLabel;
    unsigned char colorMap[MAXCOLORMAPSIZE][4];
    int transparent = -1;
    static const char *const optionStrings[] = {
	"-index", NULL
    };
    GIFImageConfig gifConf, *gifConfPtr = &gifConf;

................................................................................
     * the GIF.
     */

    if (Tk_PhotoExpand(interp, imageHandle,
	    destX + width, destY + height) != TCL_OK) {
	return TCL_ERROR;
    }
    
    /*
     * -------------------------------------------------------------------------
     * From here on, go to error to not leave memory leaks
     * -------------------------------------------------------------------------
     */

    /*
     * Initialize the metadata dict
     */
    metadata = Tcl_NewDictObj();
    
    /*
     * Search for the frame from the GIF to display.
     */

    while (1) {
	if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {








	    goto error;
	}

	switch (gifLabel) {
	case GIF_TERMINATOR:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "no image data for this index", -1));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "NO_DATA", NULL);
	    goto error;

	case GIF_EXTENSION:
	    /*
	     * This is a GIF extension.
	     */

	    if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {





		goto error;
	    }
	    if (DoExtension(gifConfPtr, chan, gifLabel,
		    gifConfPtr->workingBuffer, &transparent, metadata) < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"error reading extension in GIF image", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
			NULL);
		goto error;
	    }
	    continue;
................................................................................
	ckfree(block.pixelPtr);
    }

    /*
     * We've successfully read the GIF frame (or there was nothing to read,
     * which suits as well). We're done.
     */

    /*
     * Read final zero
     */
    if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {
        goto error;
    }
    if (gifLabel != '\0') {
	/*
	 * Premature end of image.
	 */

	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"no image data termination", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "PREMATURE_END",
		NULL);
	goto error;
    }
    while (1) {
	if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {
	    goto error;
	}
	switch (gifLabel) {
	case GIF_TERMINATOR:
	    break;

	case GIF_EXTENSION:
	    /*
	     * This is a GIF extension.
	     */

	    if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {
		goto error;
	    }
	    if (DoExtension(gifConfPtr, chan, gifLabel,
		    gifConfPtr->workingBuffer, &transparent, metadata) < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"error reading extension in GIF image", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
			NULL);
		goto error;
	    }
	    continue;
	case GIF_START:
	    /*
	     * There should not be a second image block - bail out without error
	     */
	    break;
	default:
	    /*
	     * Not a valid start character; ignore it.
	     */

	    continue;
	}
	break;
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(tkImgFmtGIF.name, -1));
    result = TCL_OK;

    /*
     * Set the metadata object.
     * This increments the ref count
     */
    Tk_PhotoSetMetadata(imageHandle, metadata);

  error:
    /*
     * If a trash buffer has been allocated, free it now.
     */

    if (trashBuffer != NULL) {
	ckfree(trashBuffer);
    }
    
    /*
     * free the metadata object in case of error.
     * Otherwise, it is not freed as the ref count was incremented above.
     */
    Tcl_IncrRefCount(metadata);
    return result;
}
 

/*
 *----------------------------------------------------------------------
 *
 * Read one Byte --
 *
 *	Read one byte (label byte) from the image stream.
 *
 * Results:
 *	The return value is 1 if the first characters in the data are like GIF
 *	data, and 0 otherwise.
 *
 * Side effects:
 *	The size of the image is placed in widthPtr and heightPtr.
 *
 *----------------------------------------------------------------------
 */

static int
ReadOneByte(
    Tcl_Interp *interp,		/* Interpreter to use for reporting errors. */
    GIFImageConfig *gifConfPtr,
    Tcl_Channel chan		/* The image file, open for reading. */
    )
{
    unsigned char buf[2];
    if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {
        /*
         * Premature end of image.
         */

        Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"premature end of image data", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "PREMATURE_END", NULL);
	return -1;
    }
    return buf[0];
}
 
/*
 *----------------------------------------------------------------------
 *
 * StringMatchGIF --
 *
 *	This function is invoked by the photo image type to see if an object
 *	contains image data in GIF format.
................................................................................
 *	data, and 0 otherwise.
 *
 * Side effects:
 *	The size of the image is placed in widthPtr and heightPtr.
 *
 *----------------------------------------------------------------------
 */


static int
StringMatchGIF(
    Tcl_Obj *dataObj,		/* the object containing the image data */
    Tcl_Obj *format,		/* the image format object, or NULL */
    int *widthPtr,		/* where to put the string width */
    int *heightPtr,		/* where to put the string height */
................................................................................
 
static int
DoExtension(
    GIFImageConfig *gifConfPtr,
    Tcl_Channel chan,
    int label,
    unsigned char *buf,
    int *transparent,
    Tcl_Obj *metadata)
{
    int count;
    Tcl_Obj *metadataData;
    int length;
    unsigned char *bytePtr;

    switch (label) {
    case 0x01:			/* Plain Text Extension */
	break;

    case 0xff:			/* Application Extension */
	break;

    case 0xfe:			/* Comment Extension */
	length = 0;
	while ( 0 <
		(count = GetDataBlock(gifConfPtr, chan, buf)) ) {

	    if (length == 0) {
		metadataData = Tcl_NewByteArrayObj(buf, count);
	    } else {
		bytePtr = Tcl_SetByteArrayLength(metadataData, length+count);
		memcpy(bytePtr+length,buf,count);
	    }
	    length += count;
	}
	if (length > 0) {
	    if ( TCL_OK != Tcl_DictObjPut(NULL, metadata,
		    Tcl_NewStringObj("comment",-1), metadataData)) {
		return -1;
	    }
	}
	return count;

    case 0xf9:			/* Graphic Control Extension */
	count = GetDataBlock(gifConfPtr, chan, buf);
	if (count < 0) {
	    /* HaO: return 1 on file read error will not show error - why ? */
	    return 1;
	}
	if ((buf[0] & 0x1) != 0) {
	    *transparent = buf[3];
	}





	break;
    }

    do {
	count = GetDataBlock(gifConfPtr, chan, buf);
    } while (count > 0);
    return count;
}

Changes to generic/tkImgPhoto.c.

3796
3797
3798
3799
3800
3801
3802


































































3803
3804
3805
3806
3807
3808
3809
	}
	return TCL_ERROR;
    }
    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
	    masterPtr->width, masterPtr->height);
    return TCL_OK;
}


































































 
/*
 *----------------------------------------------------------------------
 *
 * TkGetPhotoValidRegion --
 *
 *	This function is called to get the part of the photo where there is






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
	}
	return TCL_ERROR;
    }
    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
	    masterPtr->width, masterPtr->height);
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tk_PhotoGetMetadata --
 *
 *	This function is called to obtain the metadata object of a photo
 *	image.
 *
 * Results:
 *	The image's metadata object pointer.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
Tk_PhotoGetMetadata(
    Tk_PhotoHandle handle)	/* Handle for the image whose dimensions are
				 * requested. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;

    return masterPtr->metadata;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tk_PhotoSetMetadata --
 *
 *	This function is called to obtain to set the metadata object of a
 *	photo image.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tk_PhotoSetMetadata(
    Tk_PhotoHandle handle,	/* Handle for the image whose dimensions are
				 * requested. */
    Tcl_Obj *metadata)
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;
    /*
     * Free current object if present
     */
    if(masterPtr->metadata != NULL) {
	Tcl_DecrRefCount(masterPtr->metadata);
    }
    /*
     * Increment ref count of new object to get it
     */
    if (metadata != NULL) {
	Tcl_IncrRefCount(metadata);
    }
    masterPtr->metadata = metadata;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkGetPhotoValidRegion --
 *
 *	This function is called to get the part of the photo where there is

Changes to generic/tkStubInit.c.

1176
1177
1178
1179
1180
1181
1182


1183
1184
1185
    Tk_PhotoPutZoomedBlock, /* 267 */
    Tk_PhotoSetSize, /* 268 */
    Tk_GetUserInactiveTime, /* 269 */
    Tk_ResetUserInactiveTime, /* 270 */
    Tk_Interp, /* 271 */
    Tk_CreateOldImageType, /* 272 */
    Tk_CreateOldPhotoImageFormat, /* 273 */


};

/* !END!: Do not edit above this line. */






>
>



1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
    Tk_PhotoPutZoomedBlock, /* 267 */
    Tk_PhotoSetSize, /* 268 */
    Tk_GetUserInactiveTime, /* 269 */
    Tk_ResetUserInactiveTime, /* 270 */
    Tk_Interp, /* 271 */
    Tk_CreateOldImageType, /* 272 */
    Tk_CreateOldPhotoImageFormat, /* 273 */
    Tk_PhotoGetMetadata, /* 274 */
    Tk_PhotoSetMetadata, /* 275 */
};

/* !END!: Do not edit above this line. */