Depth24Image.st
changeset 8325 4b86cb61f568
parent 8197 ac41cb09e3f6
child 8440 44692625c8ab
equal deleted inserted replaced
8324:51826d506c5a 8325:4b86cb61f568
    42     It mainly consists of methods already implemented in Image,
    42     It mainly consists of methods already implemented in Image,
    43     reimplemented here for more performance.
    43     reimplemented here for more performance.
    44 
    44 
    45     Only the #rgb format is supported here.
    45     Only the #rgb format is supported here.
    46 
    46 
       
    47     with #rgb, pixels are internally stored byte-wise in rgb order
       
    48     (i.e. r at low byte, b at high byte).
       
    49 
       
    50     When reading pixel values, these are returned as rrggbb,
       
    51     both on LSB and on MSB machines.
       
    52     (red in high bits of the returned 24bit integer)
       
    53     Thus, pixelValues and rgbValues are identical, simulating MSB on all
       
    54     architectures (this should be transparent, if you use the rgbValueAt
       
    55     accessors; however, some old code uses pixelValueAt:, assuming that the
       
    56     returned pixel value is rrggbb (which it would not be without this hack).
       
    57 
    47     [author:]
    58     [author:]
    48 	Claus Gittinger
    59         Claus Gittinger
    49 
    60 
    50     [see also:]
    61     [see also:]
    51 	Depth1Image Depth2Image Depth4Image Depth8Image Depth16Image
    62         Depth1Image Depth2Image Depth4Image Depth8Image Depth16Image
    52 	ImageReader
    63         ImageReader
    53 "
    64 "
    54 ! !
    65 ! !
    55 
    66 
    56 !Depth24Image class methodsFor:'queries'!
    67 !Depth24Image class methodsFor:'queries'!
    57 
    68 
    79      Pixels start at x=0 , y=0 for upper left pixel,
    90      Pixels start at x=0 , y=0 for upper left pixel,
    80      end at x = width-1, y=height-1 for lower right pixel"
    91      end at x = width-1, y=height-1 for lower right pixel"
    81 
    92 
    82     |rgbVal|
    93     |rgbVal|
    83 
    94 
    84     photometric == #rgb ifTrue:[
    95     rgbVal := self rgbValueAtX:x y:y.
    85         rgbVal := self pixelAtX:x y:y.
    96     ^ Color rgbValue:rgbVal.
    86         ^ Color rgbValue:rgbVal.
       
    87     ].
       
    88     "/ the inherited method should handle all cases.
       
    89     ^ super colorAtX:x y:y.
       
    90 !
    97 !
    91 
    98 
    92 colorAtX:x y:y put:aColor
    99 colorAtX:x y:y put:aColor
    93     "set the pixel at x/y to aColor.
   100     "set the pixel at x/y to aColor.
    94      Pixels start at x=0 , y=0 for upper left pixel, end at
   101      Pixels start at x=0 , y=0 for upper left pixel, end at
    95      x = width-1, y=height-1 for lower right pixel."
   102      x = width-1, y=height-1 for lower right pixel."
    96 
   103 
    97     photometric == #rgb ifTrue:[
   104     self rgbValueAtX:x y:y put:(aColor rgbValue).
    98         self pixelAtX:x y:y put:(aColor rgbValue).
       
    99         ^ self
       
   100     ].
       
   101     super colorAtX:x y:y put:aColor.
       
   102 
   105 
   103     "Created: / 24-04-1997 / 17:32:59 / cg"
   106     "Created: / 24-04-1997 / 17:32:59 / cg"
   104     "Modified (format): / 31-08-2017 / 12:01:01 / cg"
   107     "Modified (format): / 31-08-2017 / 12:01:01 / cg"
   105 !
   108 !
   106 
   109 
   107 pixelAtX:x y:y
   110 pixelAtX:x y:y
   108     "retrieve a pixel at x/y; return a pixel value.
   111     "retrieve a pixel at x/y; 
       
   112      return a pixel value (0..16rFFFFFF) which is 24 bits RGB.
       
   113      In theory, the interpretation of the pixel value depends on the photometric,
       
   114      however as the only one supported here is #rgb, the returned value
       
   115      is always rrggbb (with r in high bits, b in low 8 bits).
   109      Pixels start at x=0 , y=0 for upper left pixel, end at
   116      Pixels start at x=0 , y=0 for upper left pixel, end at
   110      x = width-1, y=height-1 for lower right pixel.
   117      x = width-1, y=height-1 for lower right pixel."
   111      The pixel value contains r/g/b in msb order (i.e. r at high, b at low bits)"
       
   112 
   118 
   113     |index "{ Class: SmallInteger }"
   119     |index "{ Class: SmallInteger }"
   114      rVal  "{ Class: SmallInteger }"
   120      rVal  "{ Class: SmallInteger }"
   115      gVal  "{ Class: SmallInteger }"
   121      gVal  "{ Class: SmallInteger }"
   116      bVal  "{ Class: SmallInteger }"|
   122      bVal  "{ Class: SmallInteger }"|
   121 
   127 
   122     if (__isByteArrayLike(b)
   128     if (__isByteArrayLike(b)
   123      && __bothSmallInteger(x, y)
   129      && __bothSmallInteger(x, y)
   124      && __isSmallInteger(w)
   130      && __isSmallInteger(w)
   125      && (__INST(pixelFunction)==nil) ) {
   131      && (__INST(pixelFunction)==nil) ) {
   126 	int _idx;
   132         int _idx;
   127 
   133 
   128 	_idx = ((__intVal(w) * __intVal(y)) + __intVal(x))*3;
   134         _idx = ((__intVal(w) * __intVal(y)) + __intVal(x))*3;
   129 	if (((unsigned)(_idx+2)) < __byteArraySize(b)) {
   135         if (((unsigned)(_idx+2)) < __byteArraySize(b)) {
   130 	    unsigned char *pPix = &(__ByteArrayInstPtr(b)->ba_element[_idx]);
   136             unsigned char *pPix = &(__ByteArrayInstPtr(b)->ba_element[_idx]);
   131 	    unsigned int _pix;
   137             unsigned int _pix;
   132 	    _pix = (((pPix[0]<<8)+pPix[1])<<8)+pPix[2];
   138             _pix = (pPix[0]<<16) + (pPix[1] << 8) + pPix[2];
   133 	    RETURN( __MKSMALLINT(_pix) );
   139             RETURN( __MKSMALLINT(_pix) );
   134 	}
   140         }
   135     }
   141     }
   136 %}.
   142 %}.
   137     pixelFunction notNil ifTrue:[^ pixelFunction value:x value:y].
   143     pixelFunction notNil ifTrue:[^ pixelFunction value:x value:y].
   138 
   144 
   139     index := 1 + (((width * y) + x) * 3).
   145     index := 1 + (((width * y) + x) * 3).
   144 
   150 
   145     "Created: 24.4.1997 / 16:06:34 / cg"
   151     "Created: 24.4.1997 / 16:06:34 / cg"
   146 !
   152 !
   147 
   153 
   148 pixelAtX:x y:y put:aPixelValue
   154 pixelAtX:x y:y put:aPixelValue
   149     "set a pixel at x/y to aPixelValue, which is 24 bits RGB.
   155     "set a pixel at x/y to aPixelValue, (0..16rFFFFFF) which is 24 bits RGB.
   150      The interpretation of the pixelValue depends on the photometric
   156      In theory, the interpretation of the pixel value depends on the photometric,
   151      and the colormap. (see also: Image>>atX:y:put:)
   157      however as the only one supported here is #rgb, the expected value
       
   158      is always rrggbb (with r in high bits, b in low 8 bits).
   152      Pixels start at x=0 , y=0 for upper left pixel, end at
   159      Pixels start at x=0 , y=0 for upper left pixel, end at
   153      x = width-1, y=height-1 for lower right pixel"
   160      x = width-1, y=height-1 for lower right pixel"
   154 
   161 
   155     |index "{ Class: SmallInteger }"
   162     |index "{ Class: SmallInteger }"
   156      val   "{ Class: SmallInteger }"|
   163      val   "{ Class: SmallInteger }"|
   167 
   174 
   168         _idx = ((__intVal(w) * __intVal(y)) + __intVal(x))*3;
   175         _idx = ((__intVal(w) * __intVal(y)) + __intVal(x))*3;
   169         if (((unsigned)(_idx+2)) < __byteArraySize(b)) {
   176         if (((unsigned)(_idx+2)) < __byteArraySize(b)) {
   170             unsigned char *pPix = &(__ByteArrayInstPtr(b)->ba_element[_idx]);
   177             unsigned char *pPix = &(__ByteArrayInstPtr(b)->ba_element[_idx]);
   171             unsigned int _pix = __intVal(aPixelValue);
   178             unsigned int _pix = __intVal(aPixelValue);
   172             pPix[0] = (_pix>>16) & 0xFF;
   179             pPix[0] = (_pix>>16) & 0xFF;    // r
   173             pPix[1] = (_pix>>8) & 0xFF;
   180             pPix[1] = (_pix>>8) & 0xFF;     // g 
   174             pPix[2] = (_pix) & 0xFF;
   181             pPix[2] = (_pix) & 0xFF;        // b 
   175             RETURN( self );
   182             RETURN( self );
   176         }
   183         }
   177     }
   184     }
   178 %}.
   185 %}.
   179     bytes isNil ifTrue:[ self createPixelStore ].
   186     bytes isNil ifTrue:[ self createPixelStore ].
   191     "retrieve a pixel's rgb value at x/y; 
   198     "retrieve a pixel's rgb value at x/y; 
   192      return a 24bit rgbValue (rrggbb, red is MSB).
   199      return a 24bit rgbValue (rrggbb, red is MSB).
   193      Pixels start at 0@0 for the upper left pixel, 
   200      Pixels start at 0@0 for the upper left pixel, 
   194      and end at (width-1)@(height-1) for the lower right pixel."
   201      and end at (width-1)@(height-1) for the lower right pixel."
   195 
   202 
   196     (photometric == #rgb) ifTrue:[
   203     photometric == #rgb ifTrue:[
   197         ^ self pixelAtX:x y:y.
   204         ^ self pixelAtX:x y:y
   198     ].
   205     ].
   199     ^ super rgbValueAtX:x y:y
   206     ^ super rgbValueAtX:x y:y
   200 
   207 
   201     "Modified: / 10-09-2017 / 16:21:25 / cg"
   208     "Modified: / 10-09-2017 / 16:21:25 / cg"
   202 !
   209 !
   203 
   210 
   204 rgbValueAtX:x y:y put:rgb
   211 rgbValueAtX:x y:y put:rgbValue
   205     "store a pixel's rgb value at x/y; 
   212     "store a pixel's rgb value at x/y; 
   206      return a 24bit rgbValue (rrggbb, red is MSB).
   213      return a 24bit rgbValue (rrggbb, red is MSB).
   207      Pixels start at 0@0 for the upper left pixel, 
   214      Pixels start at 0@0 for the upper left pixel, 
   208      and end at (width-1)@(height-1) for the lower right pixel."
   215      and end at (width-1)@(height-1) for the lower right pixel."
   209 
   216 
   210     (photometric == #rgb) ifTrue:[
   217     photometric == #rgb ifTrue:[
   211         ^ self pixelAtX:x y:y put:rgb.
   218         self pixelAtX:x y:y put:rgbValue
   212     ].
   219     ] ifFalse:[
   213     ^ super rgbValueAtX:x y:y put:rgb
   220         super rgbValueAtX:x y:y put:rgbValue
       
   221     ].
   214 
   222 
   215     "Created: / 10-09-2017 / 16:21:50 / cg"
   223     "Created: / 10-09-2017 / 16:21:50 / cg"
   216 !
   224 !
   217 
   225 
   218 rowAt:y putAll:pixelArray startingAt:startIndex
   226 rowAt:y putAll:pixelArray startingAt:startIndex
   219     "store a single row's bits from bits in the pixelArray argument;
   227     "store a single row's bits from bits in the pixelArray argument;
       
   228      The interpretation of the pixel values depends on the photometric.
   220      Return the pixelArray.
   229      Return the pixelArray.
   221      Notice: row coordinate starts at 0."
   230      Notice: row coordinate starts at 0."
   222 
   231 
   223     |bytes dstIdx pixel|
   232     |bytes dstIdx pixel|
   224 
   233 
   225     bytes := self bits.
   234     photometric == #rgb ifTrue:[
   226     dstIdx := (y * self bytesPerRow) + 1.
   235         bytes := self bits.
   227     0 to:width-1 do:[:col |
   236         dstIdx := (y * self bytesPerRow) + 1.
   228         pixel := pixelArray at:(startIndex + col).
   237         0 to:width-1 do:[:col |
   229         bytes at:dstIdx put:((pixel bitShift:-16) bitAnd:16rFF).
   238             pixel := pixelArray at:(startIndex + col).
   230         bytes at:dstIdx+1 put:((pixel bitShift:-8) bitAnd:16rFF).
   239             "/ msbFirst
   231         bytes at:dstIdx+2 put:(pixel bitAnd:16rFF).
   240             bytes at:dstIdx put:((pixel bitShift:-16) bitAnd:16rFF).
   232         dstIdx := dstIdx + 3.
   241             bytes at:dstIdx+1 put:((pixel bitShift:-8) bitAnd:16rFF).
   233     ].
   242             bytes at:dstIdx+2 put:(pixel bitAnd:16rFF).
   234     ^ pixelArray
   243             dstIdx := dstIdx + 3.
       
   244         ].
       
   245         ^ self
       
   246     ].
       
   247     super rowAt:y putAll:pixelArray startingAt:startIndex.
   235 
   248 
   236     "Created: / 24-04-1997 / 15:50:27 / cg"
   249     "Created: / 24-04-1997 / 15:50:27 / cg"
   237     "Modified (comment): / 10-09-2017 / 16:22:39 / cg"
   250     "Modified (comment): / 10-09-2017 / 16:22:39 / cg"
   238 ! !
   251 ! !
   239 
   252 
  3338 !
  3351 !
  3339 
  3352 
  3340 blueBitsOf:pixel
  3353 blueBitsOf:pixel
  3341     "given a pixel-value, return the blue component as byteValue (0..255)"
  3354     "given a pixel-value, return the blue component as byteValue (0..255)"
  3342 
  3355 
  3343     ^ pixel bitAnd:16rFF.
  3356     photometric == #rgb ifTrue:[
       
  3357         ^ pixel bitAnd:16rFF.
       
  3358     ].
       
  3359     ^ super blueBitsOf:pixel.
  3344 
  3360 
  3345     "Created: 8.6.1996 / 09:56:20 / cg"
  3361     "Created: 8.6.1996 / 09:56:20 / cg"
  3346 !
  3362 !
  3347 
  3363 
  3348 blueComponentOf:pixel
  3364 blueComponentOf:pixel
  3373 !
  3389 !
  3374 
  3390 
  3375 greenBitsOf:pixel
  3391 greenBitsOf:pixel
  3376     "given a pixel-value, return the green component as byteValue (0..255)"
  3392     "given a pixel-value, return the green component as byteValue (0..255)"
  3377 
  3393 
  3378     ^ (pixel bitShift:-8) bitAnd:16rFF.
  3394     photometric == #rgb ifTrue:[
       
  3395         ^ (pixel bitShift:-8) bitAnd:16rFF.
       
  3396     ].
       
  3397     ^ super greenBitsOf:pixel.
  3379 
  3398 
  3380     "Modified: 8.6.1996 / 08:56:28 / cg"
  3399     "Modified: 8.6.1996 / 08:56:28 / cg"
  3381     "Created: 8.6.1996 / 09:56:30 / cg"
  3400     "Created: 8.6.1996 / 09:56:30 / cg"
  3382 !
  3401 !
  3383 
  3402 
  3427 !
  3446 !
  3428 
  3447 
  3429 redBitsOf:pixel
  3448 redBitsOf:pixel
  3430     "given a pixel-value, return the red component as byteValue (0..255)"
  3449     "given a pixel-value, return the red component as byteValue (0..255)"
  3431 
  3450 
  3432     ^ (pixel bitShift:-16) bitAnd:16rFF.
  3451     photometric == #rgb ifTrue:[
       
  3452         ^ ((pixel>>16) bitAnd:16rFF).
       
  3453     ].
       
  3454     ^ super redBitsOf:pixel.
  3433 
  3455 
  3434     "Modified: 8.6.1996 / 08:56:31 / cg"
  3456     "Modified: 8.6.1996 / 08:56:31 / cg"
  3435     "Created: 8.6.1996 / 09:56:39 / cg"
  3457     "Created: 8.6.1996 / 09:56:39 / cg"
  3436 !
  3458 !
  3437 
  3459 
  3455 
  3477 
  3456     ^ -16
  3478     ^ -16
  3457 !
  3479 !
  3458 
  3480 
  3459 rgbFromValue:pixelValue
  3481 rgbFromValue:pixelValue
  3460     "given a pixel value, return the corresponding 24bit rgbValue (rrggbb, red is MSB)."
  3482     "given a pixel value, return the corresponding 24bit rgbValue 
       
  3483      (rrggbb, red is MSB)."
  3461 
  3484 
  3462     (photometric == #rgb) ifTrue:[
  3485     (photometric == #rgb) ifTrue:[
  3463         ^ pixelValue
  3486         ^ pixelValue
  3464     ].
  3487     ].
  3465     ^ super rgbFromValue:pixelValue.
  3488     ^ super rgbFromValue:pixelValue.
  3475 
  3498 
  3476     "Modified: 10.6.1996 / 18:03:09 / cg"
  3499     "Modified: 10.6.1996 / 18:03:09 / cg"
  3477 !
  3500 !
  3478 
  3501 
  3479 valueFromRedBits:redBits greenBits:greenBits blueBits:blueBits
  3502 valueFromRedBits:redBits greenBits:greenBits blueBits:blueBits
  3480     (photometric == #rgba) ifTrue:[
  3503     ^ (((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:redBits
  3481         ^ (((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:blueBits
       
  3482     ].
       
  3483     ^ super valueFromRedBits:redBits greenBits:greenBits blueBits:blueBits.
       
  3484 
  3504 
  3485     "Modified: / 22-08-2017 / 18:34:07 / cg"
  3505     "Modified: / 22-08-2017 / 18:34:07 / cg"
  3486 ! !
  3506 ! !
  3487 
  3507 
  3488 !Depth24Image class methodsFor:'documentation'!
  3508 !Depth24Image class methodsFor:'documentation'!