diff options
-rw-r--r-- | generic/tkImgPPM.c | 58 | ||||
-rw-r--r-- | tests/imgPPM.test | 11 |
2 files changed, 48 insertions, 21 deletions
diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c index edd1b71..d9c06ab 100644 --- a/generic/tkImgPPM.c +++ b/generic/tkImgPPM.c @@ -141,7 +141,7 @@ FileReadPPM( * image being read. */ { int fileWidth, fileHeight, maxIntensity; - int nLines, nBytes, h, type, count; + int nLines, nBytes, h, type, count, bytesPerChannel = 1; unsigned char *pixelPtr; Tk_PhotoImageBlock block; @@ -158,12 +158,14 @@ FileReadPPM( Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "DIMENSIONS", NULL); return TCL_ERROR; } - if ((maxIntensity <= 0) || (maxIntensity >= 256)) { + if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "PPM image file \"%s\" has bad maximum intensity value %d", fileName, maxIntensity)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "INTENSITY", NULL); return TCL_ERROR; + } else if (maxIntensity > 0x00ff) { + bytesPerChannel = 2; } if ((srcX + width) > fileWidth) { @@ -173,20 +175,20 @@ FileReadPPM( height = fileHeight - srcY; } if ((width <= 0) || (height <= 0) - || (srcX >= fileWidth) || (srcY >= fileHeight)) { + || (srcX >= fileWidth) || (srcY >= fileHeight)) { return TCL_OK; } if (type == PGM) { - block.pixelSize = 1; + block.pixelSize = 1 * bytesPerChannel; block.offset[0] = 0; block.offset[1] = 0; block.offset[2] = 0; } else { - block.pixelSize = 3; + block.pixelSize = 3 * bytesPerChannel; block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; + block.offset[1] = 1 * bytesPerChannel; + block.offset[2] = 2 * bytesPerChannel; } block.offset[3] = 0; block.width = width; @@ -228,12 +230,21 @@ FileReadPPM( ckfree(pixelPtr); return TCL_ERROR; } - if (maxIntensity != 255) { + if (maxIntensity < 0x00ff) { unsigned char *p; for (p = pixelPtr; count > 0; count--, p++) { *p = (((int) *p) * 255)/maxIntensity; } + } else if (maxIntensity > 0x00ff) { + unsigned char *p; + unsigned int value; + + for (p = pixelPtr; count > 0; count--, p += 2) { + value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]); + value = value * 255 / maxIntensity; + p[0] = p[1] = (unsigned char) value; + } } block.height = nLines; if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY, @@ -478,7 +489,7 @@ StringReadPPM( * image being read. */ { int fileWidth, fileHeight, maxIntensity; - int nLines, nBytes, h, type, count, dataSize; + int nLines, nBytes, h, type, count, dataSize, bytesPerChannel = 2; unsigned char *pixelPtr, *dataBuffer; Tk_PhotoImageBlock block; @@ -496,12 +507,14 @@ StringReadPPM( Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "DIMENSIONS", NULL); return TCL_ERROR; } - if ((maxIntensity <= 0) || (maxIntensity >= 256)) { + if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "PPM image data has bad maximum intensity value %d", maxIntensity)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "INTENSITY", NULL); return TCL_ERROR; + } else if (maxIntensity > 0x00ff) { + bytesPerChannel = 2; } if ((srcX + width) > fileWidth) { @@ -516,15 +529,15 @@ StringReadPPM( } if (type == PGM) { - block.pixelSize = 1; + block.pixelSize = 1 * bytesPerChannel; block.offset[0] = 0; block.offset[1] = 0; block.offset[2] = 0; } else { - block.pixelSize = 3; + block.pixelSize = 3 * bytesPerChannel; block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; + block.offset[1] = 1 * bytesPerChannel; + block.offset[2] = 2 * bytesPerChannel; } block.offset[3] = 0; block.width = width; @@ -535,7 +548,7 @@ StringReadPPM( dataSize -= srcY * block.pitch; } - if (maxIntensity == 255) { + if (maxIntensity == 0x00ff) { /* * We have all the data in memory, so write everything in one go. */ @@ -582,8 +595,19 @@ StringReadPPM( Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "TRUNCATED", NULL); return TCL_ERROR; } - for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) { - *p = (((int) *dataBuffer) * 255)/maxIntensity; + if (maxIntensity < 0x00ff) { + for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) { + *p = (((int) *dataBuffer) * 255)/maxIntensity; + } + } else { + unsigned char *p; + unsigned int value; + + for (p = pixelPtr; count > 0; count--, p += 2) { + value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]); + value = value * 255 / maxIntensity; + p[0] = p[1] = (unsigned char) value; + } } dataSize -= nBytes; block.height = nLines; diff --git a/tests/imgPPM.test b/tests/imgPPM.test index 456427f..b5955df 100644 --- a/tests/imgPPM.test +++ b/tests/imgPPM.test @@ -21,7 +21,7 @@ proc put {file data} { puts -nonewline $f $data close $f } - + test imgPPM-1.1 {FileReadPPM procedure} -body { put test.ppm "P6\n0 256\n255\nabcdef" image create photo p1 -file test.ppm @@ -39,9 +39,9 @@ test imgPPM-1.4 {FileReadPPM procedure} -body { image create photo p1 -file test.ppm } -returnCodes error -result {PPM image file "test.ppm" has dimension(s) <= 0} test imgPPM-1.5 {FileReadPPM procedure} -body { - put test.ppm "P6\n10 20\n256\nabcdef" + put test.ppm "P6\n10 20\n100000\nabcdef" image create photo p1 -file test.ppm -} -returnCodes error -result {PPM image file "test.ppm" has bad maximum intensity value 256} +} -returnCodes error -result {PPM image file "test.ppm" has bad maximum intensity value 100000} test imgPPM-1.6 {FileReadPPM procedure} -body { put test.ppm "P6\n10 20\n0\nabcdef" image create photo p1 -file test.ppm @@ -161,7 +161,7 @@ test imgPPM-4.1 {StringReadPPM procedure, data too short [Bug 1822391]} -body { } -cleanup { image delete I } -returnCodes error -result {truncated PPM data} - + imageFinish # cleanup @@ -169,3 +169,6 @@ catch {file delete test.ppm} cleanupTests return +# Local Variables: +# mode: tcl +# End: |