#BUGFIX by cg
authorClaus Gittinger <cg@exept.de>
Tue, 22 Aug 2017 17:53:06 +0200
changeset 8085 ba867f680fde
parent 8084 95a21362ceba
child 8086 c2e7b74ac2d3
#BUGFIX by cg class: Depth32Image added: #numAlphaBits #numBlueBits #numGreenBits #numRedBits comment/format in: #alphaBitsOf: #alphaShiftForPixelValue #colorAtX:y:put: #negative changed: #blueBitsOf: #blueShiftForPixelValue #greenBitsOf: #greenShiftForPixelValue #redBitsOf: #redShiftForPixelValue #valueFromRedBits:greenBits:blueBits: class: Depth32Image class comment/format in: #documentation
Depth32Image.st
--- a/Depth32Image.st	Tue Aug 22 17:41:57 2017 +0200
+++ b/Depth32Image.st	Tue Aug 22 17:53:06 2017 +0200
@@ -43,11 +43,12 @@
     Only the minimum protocol is implemented here; much more is
     needed for higher performance operations on depth32 images.
 
-    (however, 32bit images are currntly relatively seldom used, 
-     so falling back into the slow general methods from Image does not hurt too much.
-     This situation will change, when more support for alpha channels is added and they
-     are more heavily used in ST/X...)
-
+    Sometimes, 32bit images with no alpha information (i.e. r,g,b,0) is encountered.
+    In this case, we treat the low byte as red, the next as green, the 2rd as blue byte,
+    and ignore the fourth byte.
+    When reading/writing pixel values, these are treated like argb (i.e. the blue bits are in low bit positions,
+    not shifted).
+    
     [author:]
         Claus Gittinger
 
@@ -127,25 +128,30 @@
 
     |index "{ Class: SmallInteger }"|
 
+    index := 1 + (((width * y) + x) * 4).
     (photometric == #rgb) ifTrue:[
-        index := 1 + (((width * y) + x) * 4).
         bytes at:(index) put:(aColor redByte).
         bytes at:(index + 1) put:(aColor greenByte).
         bytes at:(index + 2) put:(aColor blueByte).
         bytes at:(index + 3) put:0.              
         ^ self
     ].
-    (photometric == #rgba) ifTrue:[
-        index := 1 + (((width * y) + x) * 4).
+    (photometric == #rgbx) ifTrue:[
         bytes at:(index) put:(aColor redByte).
         bytes at:(index + 1) put:(aColor greenByte).
         bytes at:(index + 2) put:(aColor blueByte).
-        bytes at:(index + 3) put:(aColor alphaByte). "alpha channel"
+        bytes at:(index + 3) put:255.              
+        ^ self
+    ].
+    (photometric == #rgba) ifTrue:[
+        bytes at:(index) put:(aColor redByte).
+        bytes at:(index + 1) put:(aColor greenByte).
+        bytes at:(index + 2) put:(aColor blueByte).
+        bytes at:(index + 3) put:(aColor alphaByte). "alpha channel in last byte"
         ^ self
     ].
     (photometric == #argb) ifTrue:[
-        index := 1 + (((width * y) + x) * 4).
-        bytes at:(index) put:255.                    "alpha channel"
+        bytes at:(index) put:(aColor alphaByte).     "alpha channel in first byte"
         bytes at:(index + 1) put:(aColor redByte).
         bytes at:(index + 2) put:(aColor greenByte).
         bytes at:(index + 3) put:(aColor blueByte).             
@@ -154,7 +160,7 @@
 
     super colorAtX:x y:y put:aColor.
 
-    "Modified: / 21-02-2017 / 01:49:58 / cg"
+    "Modified: / 22-08-2017 / 17:12:28 / cg"
 !
 
 pixelAtX:x y:y
@@ -812,19 +818,22 @@
         r := bytes at:index.
         newBytes at:index put:(255-r).
         index := index + 1.
+        
         g := bytes at:index.
         newBytes at:index put:(255-g).
         index := index + 1.
+
         b := bytes at:index.
         newBytes at:index put:(255-b).
         index := index + 1.
+
         a := bytes at:index.
         newBytes at:index put:a.
         index := index + 1.
     ].
     ^ newImage
 
-    "Modified (comment): / 21-02-2017 / 17:09:03 / cg"
+    "Modified (format): / 22-08-2017 / 17:13:38 / cg"
 ! !
 
 !Depth32Image methodsFor:'initialization'!
@@ -890,20 +899,18 @@
 alphaBitsOf:pixel
     "given a pixel-value, return the alpha component as byteValue (0..255)"
 
+    photometric == #argb ifTrue:[
+        "a,r,g,b; MSB"
+        ^ (pixel bitShift:-24) bitAnd:16rFF.
+    ].
     photometric == #rgba ifTrue:[
         "r,g,b,a; MSB"
         ^ pixel bitAnd:16rFF.
     ].
-    photometric == #argb ifTrue:[
-        "a,r,g,b; MSB"
-        ^ (pixel bitShift:-24) bitAnd:16rFF.
-    ].
-    photometric == #rgb ifTrue:[
-        ^ 0
-    ].
-    self error:'unsupported photometric'
+    "r,g,b,0; MSB"
+    ^ 0
 
-    "Modified (format): / 11-04-2017 / 12:50:20 / cg"
+    "Modified: / 22-08-2017 / 17:18:44 / cg"
 !
 
 alphaComponentOf:pixel
@@ -925,24 +932,15 @@
     "return the shift amount used with translation from pixelValues to alphaBits.
      That is the number of bits to shift the alpha value into the pixel value."
 
-    photometric == #rgba ifTrue:[
-        "/ alpha in low byte
-        "r,g,b,a"
-        ^ 0
-    ].
     photometric == #argb ifTrue:[
-        "/ alpha in high byte
-        "a,r,g,b"
+        "/ a,r,g,b - alpha in high byte
         ^ 24.
     ].
-    photometric == #rgb ifTrue:[
-        "r,g,b - no alpha"
-        "/ Logger warning:'oops - image has depth 32, but photometric is #rgb'.
-        ^ 0.
-    ].
-    self error:'unsupported photometric: ',(photometric printString)
+    "/ r,g,b,a - alpha in low byte 
+    "/ or r,g,b,0 - no alpha
+    ^ 0
 
-    "Modified (format): / 21-02-2017 / 16:42:42 / cg"
+    "Modified: / 22-08-2017 / 17:19:36 / cg"
 !
 
 bitsPerPixel
@@ -974,17 +972,14 @@
 blueBitsOf:pixel
     "given a pixel-value, return the blue component as byteValue (0..255)"
 
-    ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[
-        "r,g,b,a or r,g,b,0"
-        ^ (pixel bitShift:-8) bitAnd:16rFF.
-    ].
     photometric == #argb ifTrue:[
         "a,r,g,b"
         ^ pixel bitAnd:16rFF.
     ].
-    self error:'unsupported photometric'
+    "r,g,b,a or r,g,b,0"
+    ^ (pixel bitShift:-8) bitAnd:16rFF.
 
-    "Modified: / 21-02-2017 / 16:45:12 / cg"
+    "Modified: / 22-08-2017 / 17:16:43 / cg"
 !
 
 blueComponentOf:pixel
@@ -1002,17 +997,14 @@
 blueShiftForPixelValue
     "return the shift amount used with translation from pixelValues to blueBits"
 
-    ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[
-        "r,g,b,a or r,g,b,0"
-        ^ -8
-    ].
     photometric == #argb ifTrue:[
         "a,r,g,b"
         ^ 0.
     ].
-    self error:'unsupported photometric'
+    "r,g,b,a or r,g,b,0"
+    ^ -8
 
-    "Modified: / 21-02-2017 / 17:03:36 / cg"
+    "Modified: / 22-08-2017 / 17:19:55 / cg"
 !
 
 bytesPerRow
@@ -1026,17 +1018,14 @@
 greenBitsOf:pixel
     "given a pixel-value, return the green component as byteValue (0..255)"
 
-    ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[
-        "r,g,b,a or r,g,b,0"
-        ^ (pixel bitShift:-16) bitAnd:16rFF.
-    ].
     photometric == #argb ifTrue:[
         "a,r,g,b"
         ^ (pixel bitShift:-8) bitAnd:16rFF.
     ].
-    self error:'unsupported photometric'
+    "r,g,b,a or r,g,b,0"
+    ^ (pixel bitShift:-16) bitAnd:16rFF.
 
-    "Modified (format): / 21-02-2017 / 16:44:50 / cg"
+    "Modified: / 22-08-2017 / 17:17:12 / cg"
 !
 
 greenComponentOf:pixel
@@ -1054,17 +1043,14 @@
 greenShiftForPixelValue
     "return the shift amount used with translation from pixelValues to greenBits"
 
-    ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[
-        "r,g,b,a or r,g,b,0"
-        ^ -16
-    ].
     photometric == #argb ifTrue:[
         "a,r,g,b"
         ^ -8.
     ].
-    self error:'unsupported photometric'
+    "r,g,b,a or r,g,b,0"
+    ^ -16
 
-    "Modified: / 21-02-2017 / 17:03:47 / cg"
+    "Modified: / 22-08-2017 / 17:20:14 / cg"
 !
 
 hasAlphaChannel
@@ -1075,20 +1061,47 @@
     "Modified: / 21-02-2017 / 15:00:17 / cg"
 !
 
+numAlphaBits
+    photometric == #argb ifTrue:[
+        ^ 8.
+    ].
+    photometric == #rgba ifTrue:[
+        ^ 8.
+    ].
+    ^ 0
+
+    "Created: / 22-08-2017 / 17:38:59 / cg"
+!
+
+numBlueBits
+    ^ 8
+
+    "Created: / 22-08-2017 / 17:38:31 / cg"
+!
+
+numGreenBits
+    ^ 8
+
+    "Created: / 22-08-2017 / 17:38:28 / cg"
+!
+
+numRedBits
+    ^ 8
+
+    "Created: / 22-08-2017 / 17:38:25 / cg"
+!
+
 redBitsOf:pixel
     "given a pixel-value, return the red component as byteValue (0..255)"
 
-    ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[
-        "r,g,b,a or r,g,b,0"
-        ^ (pixel bitShift:-24) bitAnd:16rFF.
-    ].
     photometric == #argb ifTrue:[
         "a,r,g,b"
         ^ (pixel bitShift:-16) bitAnd:16rFF.
     ].
-    self error:'unsupported photometric'
+    "r,g,b,a or r,g,b,0"
+    ^ (pixel bitShift:-24) bitAnd:16rFF.
 
-    "Modified (format): / 21-02-2017 / 16:45:18 / cg"
+    "Modified: / 22-08-2017 / 17:17:34 / cg"
 !
 
 redComponentOf:pixel
@@ -1106,17 +1119,14 @@
 redShiftForPixelValue
     "return the shift amount used with translation from pixelValues to redBits"
 
-    ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[
-        "r,g,b,a or r,g,b,0"
-        ^ -24
-    ].
     photometric == #argb ifTrue:[
         "a,r,g,b"
         ^ -16.
     ].
-    self error:'unsupported photometric'
+    "r,g,b,a or r,g,b,0"
+    ^ -24
 
-    "Modified: / 21-02-2017 / 17:04:04 / cg"
+    "Modified: / 22-08-2017 / 17:20:29 / cg"
 !
 
 rgbFromValue:pixelValue
@@ -1141,7 +1151,7 @@
 !
 
 valueFromRedBits:redBits greenBits:greenBits blueBits:blueBits
-    ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[
+    ((photometric == #rgba) or:[photometric == #rgbX]) ifTrue:[
         "/ alpha in low byte
         ^ (((((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:blueBits) bitShift:8) bitOr:16rFF
     ].
@@ -1149,9 +1159,13 @@
         "/ alpha in high byte
         ^ (((((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:blueBits)) bitOr:16rFF000000
     ].
+    (photometric == #rgb) ifTrue:[
+        "/ no alpha in low byte
+        ^ (((((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:blueBits) bitShift:8) bitOr:0
+    ].
     self error:'unsupported photometric'
 
-    "Modified: / 21-02-2017 / 17:07:11 / cg"
+    "Modified: / 22-08-2017 / 17:21:19 / cg"
 ! !
 
 !Depth32Image class methodsFor:'documentation'!