161 "retrieve a pixel at x/y; return a pixelValue. |
161 "retrieve a pixel at x/y; return a pixelValue. |
162 The interpretation of the returned value depends on the photometric |
162 The interpretation of the returned value depends on the photometric |
163 and the colormap. See also Image>>atX:y:) |
163 and the colormap. See also Image>>atX:y:) |
164 Pixels start at x=0 , y=0 for upper left pixel, end at |
164 Pixels start at x=0 , y=0 for upper left pixel, end at |
165 x = width-1, y=height-1 for lower right pixel. |
165 x = width-1, y=height-1 for lower right pixel. |
166 The pixel value contains r/g/b/a in msb order (i.e. r at high, a at low bits)" |
166 With rgba photometric, the pixel value contains r/g/b/a in msb order (i.e. r at high, a at low bits); |
|
167 with argb, alpha is in the high byte" |
167 |
168 |
168 |pixelIndex "{ Class: SmallInteger }"| |
169 |pixelIndex "{ Class: SmallInteger }"| |
169 |
170 |
170 %{ /* NOCONTEXT */ |
171 %{ /* NOCONTEXT */ |
171 OBJ b = __INST(bytes); |
172 OBJ b = __INST(bytes); |
179 |
180 |
180 _idx = ((__intVal(w) * __intVal(y)) + __intVal(x))*4; |
181 _idx = ((__intVal(w) * __intVal(y)) + __intVal(x))*4; |
181 if (((unsigned)(_idx+3)) < __byteArraySize(b)) { |
182 if (((unsigned)(_idx+3)) < __byteArraySize(b)) { |
182 unsigned char *pPix = &(__ByteArrayInstPtr(b)->ba_element[_idx]); |
183 unsigned char *pPix = &(__ByteArrayInstPtr(b)->ba_element[_idx]); |
183 unsigned int _pix; |
184 unsigned int _pix; |
184 unsigned int _r, _g, _b, _a; |
185 |
185 |
186 #ifdef __MSBFIRST__ |
186 if (_INST(photometric) == @symbol(rgba)) { |
187 _pix = ((int *)pPix)[0]; |
187 _r = pPix[0]; |
188 #else |
188 _g = pPix[1]; |
189 _pix = pPix[0] << 24; |
189 _b = pPix[2]; |
190 _pix |= pPix[1] << 16; |
190 _a = pPix[3]; |
191 _pix |= pPix[2] << 8; |
191 } else if (_INST(photometric) == @symbol(argb)) { |
192 _pix |= pPix[3]; |
192 _a = pPix[0]; |
193 #endif |
193 _r = pPix[1]; |
194 |
194 _g = pPix[2]; |
|
195 _b = pPix[3]; |
|
196 } else { |
|
197 _r = pPix[0]; |
|
198 _g = pPix[1]; |
|
199 _b = pPix[2]; |
|
200 _a = 0; |
|
201 } |
|
202 _pix = (((((_a<<8)+_r)<<8)+_g)<<8)+_b; |
|
203 #if __POINTER_SIZE__ == 8 |
195 #if __POINTER_SIZE__ == 8 |
204 RETURN( __MKSMALLINT(_pix) ); |
196 RETURN( __MKSMALLINT(_pix) ); |
205 #else |
197 #else |
206 RETURN( __MKUINT(_pix) ); |
198 RETURN( __MKUINT(_pix) ); |
207 #endif |
199 #endif |
211 pixelFunction notNil ifTrue:[^ pixelFunction value:x value:y]. |
203 pixelFunction notNil ifTrue:[^ pixelFunction value:x value:y]. |
212 |
204 |
213 pixelIndex := 1 + (((width * y) + x) * 4). |
205 pixelIndex := 1 + (((width * y) + x) * 4). |
214 |
206 |
215 "left pixel in high bits" |
207 "left pixel in high bits" |
216 ^ bytes unsignedInt32At:pixelIndex MSB:false "true". |
208 ^ bytes unsignedInt32At:pixelIndex MSB:true. |
217 |
209 |
218 "Created: / 24-04-1997 / 19:00:28 / cg" |
210 "Created: / 24-04-1997 / 19:00:28 / cg" |
219 "Modified: / 21-02-2017 / 01:54:28 / cg" |
211 "Modified: / 21-02-2017 / 17:21:44 / cg" |
220 ! |
212 ! |
221 |
213 |
222 pixelAtX:x y:y put:aPixelValue |
214 pixelAtX:x y:y put:aPixelValue |
223 "set the pixel at x/y to aPixelValue. |
215 "set the pixel at x/y to aPixelValue. |
224 The interpretation of the pixelValue depends on the photometric |
216 The interpretation of the pixelValue depends on the photometric. |
225 and the colormap. (see also: Image>>atX:y:put:) |
|
226 Pixels start at x=0 , y=0 for upper left pixel, end at |
217 Pixels start at x=0 , y=0 for upper left pixel, end at |
227 x = width-1, y=height-1 for lower right pixel" |
218 x = width-1, y=height-1 for lower right pixel" |
228 |
219 |
229 |pixelIndex "{ Class: SmallInteger }"| |
220 |pixelIndex "{ Class: SmallInteger }"| |
230 |
221 |
231 pixelIndex := 1 + (((width * y) + x) * 4). |
222 pixelIndex := 1 + (((width * y) + x) * 4). |
232 bytes isNil ifTrue:[ |
223 bytes isNil ifTrue:[ |
233 self createPixelStore |
224 self createPixelStore |
234 ]. |
225 ]. |
235 "/ pixelValue is aarrggbb |
226 bytes unsignedInt32At:pixelIndex put:aPixelValue MSB:true. |
236 photometric == #rgba ifTrue:[ |
|
237 bytes at:pixelIndex put:((aPixelValue bitShift:-16) bitAnd:16rFF). |
|
238 bytes at:pixelIndex+1 put:((aPixelValue bitShift:-8) bitAnd:16rFF). |
|
239 bytes at:pixelIndex+2 put:((aPixelValue) bitAnd:16rFF). |
|
240 bytes at:pixelIndex+3 put:((aPixelValue bitShift:-24) bitAnd:16rFF). |
|
241 ^ self |
|
242 ]. |
|
243 photometric == #rgb ifTrue:[ |
|
244 bytes at:pixelIndex put:((aPixelValue bitShift:-16) bitAnd:16rFF). |
|
245 bytes at:pixelIndex+1 put:((aPixelValue bitShift:-8) bitAnd:16rFF). |
|
246 bytes at:pixelIndex+2 put:((aPixelValue) bitAnd:16rFF). |
|
247 bytes at:pixelIndex+3 put:0. |
|
248 ^ self |
|
249 ]. |
|
250 photometric == #argb ifTrue:[ |
|
251 bytes unsignedInt32At:pixelIndex put:aPixelValue MSB:false. "/ true |
|
252 ^ self |
|
253 ]. |
|
254 |
227 |
255 "Created: / 24-04-1997 / 19:00:28 / cg" |
228 "Created: / 24-04-1997 / 19:00:28 / cg" |
256 "Modified: / 21-02-2017 / 01:58:42 / cg" |
229 "Modified: / 21-02-2017 / 14:59:35 / cg" |
257 ! |
230 ! |
258 |
231 |
259 rowAt:y putAll:pixelArray startingAt:startIndex |
232 rowAt:y putAll:pixelArray startingAt:startIndex |
260 "store a single rows bits from bits in the pixelArray argument; |
233 "store a single rows bits from bits in the pixelArray argument; |
261 Return the pixelArray. |
234 Return the pixelArray. |
262 Notice: row coordinate starts at 0." |
235 Notice: row coordinate starts at 0." |
263 |
236 |
264 |bytes dstIdx pixel |
237 |bytes pixel |
|
238 dstIdx "{ Class: SmallInteger }" |
265 w "{ Class: SmallInteger }"| |
239 w "{ Class: SmallInteger }"| |
266 |
240 |
267 bytes := self bits. |
241 bytes := self bits. |
268 dstIdx := (y * self bytesPerRow) + 1. |
242 dstIdx := (y * self bytesPerRow) + 1. |
269 w := width - 1. |
243 w := width - 1. |
270 |
244 |
271 0 to:w do:[:col | |
245 0 to:w do:[:col | |
272 pixel := pixelArray at:(startIndex + col). |
246 pixel := pixelArray at:(startIndex + col). |
273 bytes unsignedInt32At:dstIdx put:pixel MSB:false. "/ true. |
247 bytes unsignedInt32At:dstIdx put:pixel MSB:true. |
274 dstIdx := dstIdx + 4. |
248 dstIdx := dstIdx + 4. |
275 ]. |
249 ]. |
276 ^ pixelArray |
250 ^ pixelArray |
277 |
251 |
278 "Modified: / 21-02-2017 / 01:47:58 / cg" |
252 "Modified (comment): / 21-02-2017 / 15:03:24 / cg" |
279 ! ! |
253 ! ! |
280 |
254 |
281 !Depth32Image methodsFor:'converting rgb images'! |
255 !Depth32Image methodsFor:'converting rgb images'! |
282 |
256 |
283 computeAlphaValuesFromMask:aMaskImage |
257 computeAlphaValuesFromMask:aMaskImage |
284 "convert a mask into alpha values; |
258 "convert a mask into alpha values; |
285 masked pixels get an alpha value of 0, |
259 masked pixels get an alpha value of 0, unmasked of 255" |
286 unmasked of 255" |
|
287 |
260 |
288 |alphaMask| |
261 |alphaMask| |
289 |
262 |
290 alphaMask := self alphaMaskForPixelValue. |
263 alphaMask := (self alphaMaskForPixelValue bitShift:self alphaShiftForPixelValue). |
291 self |
264 self |
292 valuesFromX:0 y:0 toX:(width-1) y:(height-1) |
265 valuesFromX:0 y:0 toX:(width-1) y:(height-1) |
293 do:[:x :y :pixelValue | |
266 do:[:x :y :pixelValue | |
294 (aMaskImage pixelAtX:x y:y) ~~ 0 ifTrue:[ |
267 (aMaskImage pixelAtX:x y:y) ~~ 0 ifTrue:[ |
295 self pixelAtX:x y:y put:(pixelValue bitOr:alphaMask). |
268 self pixelAtX:x y:y put:(pixelValue bitOr:alphaMask). |
931 |
908 |
932 ^ (self alphaBitsOf:pixel) * (100.0 / 255.0) |
909 ^ (self alphaBitsOf:pixel) * (100.0 / 255.0) |
933 ! |
910 ! |
934 |
911 |
935 alphaMaskForPixelValue |
912 alphaMaskForPixelValue |
936 "return the mask used with translation from pixelValues to alphaBits" |
913 "return the mask used with translation from pixelValues to alphaBits. |
|
914 Determines the number of bits of alpha" |
937 |
915 |
938 ^ 16rFF |
916 ^ 16rFF |
|
917 |
|
918 "Modified (comment): / 21-02-2017 / 16:37:31 / cg" |
939 ! |
919 ! |
940 |
920 |
941 alphaShiftForPixelValue |
921 alphaShiftForPixelValue |
942 "return the shift amount used with translation from pixelValues to alphaBits" |
922 "return the shift amount used with translation from pixelValues to alphaBits. |
|
923 That is the number of bits to shift the alpha value into the pixel value." |
943 |
924 |
944 photometric == #rgba ifTrue:[ |
925 photometric == #rgba ifTrue:[ |
|
926 "/ alpha in low byte |
945 "r,g,b,a" |
927 "r,g,b,a" |
946 ^ 0 |
928 ^ 0 |
947 ]. |
929 ]. |
948 photometric == #argb ifTrue:[ |
930 photometric == #argb ifTrue:[ |
|
931 "/ alpha in high byte |
949 "a,r,g,b" |
932 "a,r,g,b" |
950 ^ -24. |
933 ^ 24. |
951 ]. |
934 ]. |
952 photometric == #rgb ifTrue:[ |
935 photometric == #rgb ifTrue:[ |
953 "r,g,b, a" |
936 "r,g,b - no alpha" |
954 Logger warning:'oops - image has depth 32, but photometric is #rgb'. |
937 "/ Logger warning:'oops - image has depth 32, but photometric is #rgb'. |
955 ^ 0. |
938 ^ 0. |
956 ]. |
939 ]. |
957 self error:'unsupported photometric: ',(photometric printString) |
940 self error:'unsupported photometric: ',(photometric printString) |
958 |
941 |
959 "Modified (format): / 16-02-2017 / 17:16:25 / cg" |
942 "Modified (format): / 21-02-2017 / 16:42:42 / cg" |
960 ! |
943 ! |
961 |
944 |
962 bitsPerPixel |
945 bitsPerPixel |
963 "return the number of bits per pixel" |
946 "return the number of bits per pixel" |
964 |
947 |
987 |
970 |
988 blueBitsOf:pixel |
971 blueBitsOf:pixel |
989 "given a pixel-value, return the blue component as byteValue (0..255)" |
972 "given a pixel-value, return the blue component as byteValue (0..255)" |
990 |
973 |
991 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
974 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
992 "r,g,b,a" |
975 "r,g,b,a or r,g,b,0" |
993 ^ (pixel bitShift:-8) bitAnd:16rFF. |
976 ^ (pixel bitShift:-8) bitAnd:16rFF. |
994 ]. |
977 ]. |
995 photometric == #argb ifTrue:[ |
978 photometric == #argb ifTrue:[ |
996 "a,r,g,b" |
979 "a,r,g,b" |
997 ^ pixel bitAnd:16rFF. |
980 ^ pixel bitAnd:16rFF. |
998 ]. |
981 ]. |
999 self error:'unsupported photometric' |
982 self error:'unsupported photometric' |
|
983 |
|
984 "Modified: / 21-02-2017 / 16:45:12 / cg" |
1000 ! |
985 ! |
1001 |
986 |
1002 blueComponentOf:pixel |
987 blueComponentOf:pixel |
1003 "given a pixel-value, return the blue component in percent (0..100)" |
988 "given a pixel-value, return the blue component in percent (0..100)" |
1004 |
989 |
1035 |
1022 |
1036 greenBitsOf:pixel |
1023 greenBitsOf:pixel |
1037 "given a pixel-value, return the green component as byteValue (0..255)" |
1024 "given a pixel-value, return the green component as byteValue (0..255)" |
1038 |
1025 |
1039 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
1026 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
1040 "r,g,b,a" |
1027 "r,g,b,a or r,g,b,0" |
1041 ^ (pixel bitShift:-16) bitAnd:16rFF. |
1028 ^ (pixel bitShift:-16) bitAnd:16rFF. |
1042 ]. |
1029 ]. |
1043 photometric == #argb ifTrue:[ |
1030 photometric == #argb ifTrue:[ |
1044 "a,r,g,b" |
1031 "a,r,g,b" |
1045 ^ (pixel bitShift:-8) bitAnd:16rFF. |
1032 ^ (pixel bitShift:-8) bitAnd:16rFF. |
1046 ]. |
1033 ]. |
1047 self error:'unsupported photometric' |
1034 self error:'unsupported photometric' |
|
1035 |
|
1036 "Modified (format): / 21-02-2017 / 16:44:50 / cg" |
1048 ! |
1037 ! |
1049 |
1038 |
1050 greenComponentOf:pixel |
1039 greenComponentOf:pixel |
1051 "given a pixel-value, return the green component in percent (0..100)" |
1040 "given a pixel-value, return the green component in percent (0..100)" |
1052 |
1041 |
1060 ! |
1049 ! |
1061 |
1050 |
1062 greenShiftForPixelValue |
1051 greenShiftForPixelValue |
1063 "return the shift amount used with translation from pixelValues to greenBits" |
1052 "return the shift amount used with translation from pixelValues to greenBits" |
1064 |
1053 |
1065 photometric == #rgba ifTrue:[ |
1054 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
1066 "r,g,b,a" |
1055 "r,g,b,a or r,g,b,0" |
1067 ^ -16 |
1056 ^ -16 |
1068 ]. |
1057 ]. |
1069 photometric == #argb ifTrue:[ |
1058 photometric == #argb ifTrue:[ |
1070 "a,r,g,b" |
1059 "a,r,g,b" |
1071 ^ -8. |
1060 ^ -8. |
1072 ]. |
1061 ]. |
1073 self error:'unsupported photometric' |
1062 self error:'unsupported photometric' |
|
1063 |
|
1064 "Modified: / 21-02-2017 / 17:03:47 / cg" |
1074 ! |
1065 ! |
1075 |
1066 |
1076 hasAlphaChannel |
1067 hasAlphaChannel |
1077 ^ true |
1068 "could be #rgb in 32 bits..." |
|
1069 |
|
1070 ^ (photometric == #argb) or:[photometric == #rgba] |
|
1071 |
|
1072 "Modified: / 21-02-2017 / 15:00:17 / cg" |
1078 ! |
1073 ! |
1079 |
1074 |
1080 redBitsOf:pixel |
1075 redBitsOf:pixel |
1081 "given a pixel-value, return the red component as byteValue (0..255)" |
1076 "given a pixel-value, return the red component as byteValue (0..255)" |
1082 |
1077 |
1083 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
1078 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
1084 "r,g,b,a" |
1079 "r,g,b,a or r,g,b,0" |
1085 ^ (pixel bitShift:-24) bitAnd:16rFF. |
1080 ^ (pixel bitShift:-24) bitAnd:16rFF. |
1086 ]. |
1081 ]. |
1087 photometric == #argb ifTrue:[ |
1082 photometric == #argb ifTrue:[ |
1088 "a,r,g,b" |
1083 "a,r,g,b" |
1089 ^ (pixel bitShift:-16) bitAnd:16rFF. |
1084 ^ (pixel bitShift:-16) bitAnd:16rFF. |
1090 ]. |
1085 ]. |
1091 self error:'unsupported photometric' |
1086 self error:'unsupported photometric' |
|
1087 |
|
1088 "Modified (format): / 21-02-2017 / 16:45:18 / cg" |
1092 ! |
1089 ! |
1093 |
1090 |
1094 redComponentOf:pixel |
1091 redComponentOf:pixel |
1095 "given a pixel-value, return the red component in percent (0..100)" |
1092 "given a pixel-value, return the red component in percent (0..100)" |
1096 |
1093 |
1104 ! |
1101 ! |
1105 |
1102 |
1106 redShiftForPixelValue |
1103 redShiftForPixelValue |
1107 "return the shift amount used with translation from pixelValues to redBits" |
1104 "return the shift amount used with translation from pixelValues to redBits" |
1108 |
1105 |
1109 photometric == #rgba ifTrue:[ |
1106 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
1110 "r,g,b,a" |
1107 "r,g,b,a or r,g,b,0" |
1111 ^ -24 |
1108 ^ -24 |
1112 ]. |
1109 ]. |
1113 photometric == #argb ifTrue:[ |
1110 photometric == #argb ifTrue:[ |
1114 "a,r,g,b" |
1111 "a,r,g,b" |
1115 ^ -16. |
1112 ^ -16. |
1116 ]. |
1113 ]. |
1117 self error:'unsupported photometric' |
1114 self error:'unsupported photometric' |
|
1115 |
|
1116 "Modified: / 21-02-2017 / 17:04:04 / cg" |
1118 ! |
1117 ! |
1119 |
1118 |
1120 rgbFromValue:pixelValue |
1119 rgbFromValue:pixelValue |
1121 "given a pixel value, return the corresponding 24bit rgbValue (rrggbb, red is MSB)." |
1120 "given a pixel value, return the corresponding 24bit rgbValue (rrggbb, red is MSB)." |
1122 |
1121 |
1123 ^ pixelValue rightShift:8 "lsb is alpha channel" |
1122 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
|
1123 ^ pixelValue rightShift:8 "lsb is alpha channel" |
|
1124 ]. |
|
1125 (photometric == #argb) ifTrue:[ |
|
1126 ^ pixelValue bitAnd:16rFFFFFF "msb is alpha channel" |
|
1127 ]. |
|
1128 self error:'unsupported photometric' |
|
1129 |
|
1130 "Modified: / 21-02-2017 / 17:05:13 / cg" |
1124 ! |
1131 ! |
1125 |
1132 |
1126 samplesPerPixel |
1133 samplesPerPixel |
1127 "return the number of samples per pixel in the image." |
1134 "return the number of samples per pixel in the image." |
1128 |
1135 |
1129 samplesPerPixel notNil ifTrue:[^ samplesPerPixel]. |
1136 samplesPerPixel notNil ifTrue:[^ samplesPerPixel]. |
1130 ^ 4 |
1137 ^ 4 |
1131 ! |
1138 ! |
1132 |
1139 |
1133 valueFromRedBits:redBits greenBits:greenBits blueBits:blueBits |
1140 valueFromRedBits:redBits greenBits:greenBits blueBits:blueBits |
1134 ^ (((((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:blueBits) bitShift:8) bitOr:255 |
1141 ((photometric == #rgba) or:[photometric == #rgb]) ifTrue:[ |
|
1142 "/ alpha in low byte |
|
1143 ^ (((((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:blueBits) bitShift:8) bitOr:16rFF |
|
1144 ]. |
|
1145 (photometric == #argb) ifTrue:[ |
|
1146 "/ alpha in high byte |
|
1147 ^ (((((redBits bitShift:8) bitOr:greenBits) bitShift:8) bitOr:blueBits)) bitOr:16rFF000000 |
|
1148 ]. |
|
1149 self error:'unsupported photometric' |
|
1150 |
|
1151 "Modified: / 21-02-2017 / 17:07:11 / cg" |
1135 ! ! |
1152 ! ! |
1136 |
1153 |
1137 !Depth32Image class methodsFor:'documentation'! |
1154 !Depth32Image class methodsFor:'documentation'! |
1138 |
1155 |
1139 version |
1156 version |