diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2013-11-03 11:29:18 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2013-11-03 11:29:18 (GMT) |
commit | 3205d71a865a9a055c5fc810f39104aad5f91673 (patch) | |
tree | 5bc9f53c958fb33d023951ce1fc6188a62990f8e | |
parent | f46c814d2d9a8f709c8adeb6fdf1da896d80dbee (diff) | |
download | tk-3205d71a865a9a055c5fc810f39104aad5f91673.zip tk-3205d71a865a9a055c5fc810f39104aad5f91673.tar.gz tk-3205d71a865a9a055c5fc810f39104aad5f91673.tar.bz2 |
[1632447]: Allow the PPM maxval to go up to 65535, to conform with a format
definition change from around 2000 (even if that's a rare format).
-rw-r--r-- | generic/tkImgPPM.c | 58 | ||||
-rw-r--r-- | tests/imgPPM.test | 12 |
2 files changed, 49 insertions, 21 deletions
diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c index 8a46fde..b476ac6 100644 --- a/generic/tkImgPPM.c +++ b/generic/tkImgPPM.c @@ -140,7 +140,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; @@ -155,13 +155,15 @@ FileReadPPM( "\" has dimension(s) <= 0", NULL); return TCL_ERROR; } - if ((maxIntensity <= 0) || (maxIntensity >= 256)) { + if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) { char buffer[TCL_INTEGER_SPACE]; sprintf(buffer, "%d", maxIntensity); Tcl_AppendResult(interp, "PPM image file \"", fileName, "\" has bad maximum intensity value ", buffer, NULL); return TCL_ERROR; + } else if (maxIntensity > 0x00ff) { + bytesPerChannel = 2; } if ((srcX + width) > fileWidth) { @@ -171,20 +173,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; @@ -224,12 +226,21 @@ FileReadPPM( ckfree((char *) 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, @@ -474,7 +485,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; @@ -490,7 +501,7 @@ StringReadPPM( NULL); return TCL_ERROR; } - if ((maxIntensity <= 0) || (maxIntensity >= 256)) { + if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) { char buffer[TCL_INTEGER_SPACE]; sprintf(buffer, "%d", maxIntensity); @@ -498,6 +509,8 @@ StringReadPPM( "PPM image data has bad maximum intensity value ", buffer, NULL); return TCL_ERROR; + } else if (maxIntensity > 0x00ff) { + bytesPerChannel = 2; } if ((srcX + width) > fileWidth) { @@ -512,15 +525,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; @@ -531,7 +544,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. */ @@ -574,8 +587,19 @@ StringReadPPM( Tcl_AppendResult(interp, "truncated PPM data", 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 a9e9dc0..926dbec 100644 --- a/tests/imgPPM.test +++ b/tests/imgPPM.test @@ -20,7 +20,7 @@ proc put {file data} { puts -nonewline $f $data close $f } - + test imgPPM-1.1 {FileReadPPM procedure} { put test.ppm "P6\n0 256\n255\nabcdef" list [catch {image create photo p1 -file test.ppm} msg] $msg @@ -38,9 +38,9 @@ test imgPPM-1.4 {FileReadPPM procedure} { list [catch {image create photo p1 -file test.ppm} msg] $msg } {1 {PPM image file "test.ppm" has dimension(s) <= 0}} test imgPPM-1.5 {FileReadPPM procedure} { - put test.ppm "P6\n10 20\n256\nabcdef" + put test.ppm "P6\n10 20\n100000\nabcdef" list [catch {image create photo p1 -file test.ppm} msg] $msg -} {1 {PPM image file "test.ppm" has bad maximum intensity value 256}} +} {1 {PPM image file "test.ppm" has bad maximum intensity value 100000}} test imgPPM-1.6 {FileReadPPM procedure} { put test.ppm "P6\n10 20\n0\nabcdef" list [catch {image create photo p1 -file test.ppm} msg] $msg @@ -156,10 +156,14 @@ test imgPPM-4.1 {StringReadPPM procedure, data too short [Bug 1822391]} \ } \ -returnCodes error \ -result {truncated PPM data} - + eval image delete [image names] # cleanup catch {file delete test.ppm} cleanupTests return + +# Local Variables: +# mode: tcl +# End: |