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 |