2626
2727#include "Imaging.h"
2828
29+ #define ROUND_UP (f ) ((int)((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F))
30+
2931static inline UINT8
3032clip8 (float in ) {
3133 if (in <= 0.0 ) {
@@ -105,6 +107,22 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin) {
105107 return imOut ;
106108}
107109
110+ float
111+ kernel_i16 (int size , UINT8 * in0 , int x , const float * kernel , int bigendian ) {
112+ int i ;
113+ float result = 0 ;
114+ int half_size = (size - 1 ) / 2 ;
115+ for (i = 0 ; i < size ; i ++ ) {
116+ int x1 = x + i - half_size ;
117+ result += _i2f (
118+ in0 [x1 * 2 + (bigendian ? 1 : 0 )] +
119+ (in0 [x1 * 2 + (bigendian ? 0 : 1 )] >> 8 )
120+ ) *
121+ kernel [i ];
122+ }
123+ return result ;
124+ }
125+
108126void
109127ImagingFilter3x3 (Imaging imOut , Imaging im , const float * kernel , float offset ) {
110128#define KERNEL1x3 (in0 , x , kernel , d ) \
@@ -135,21 +153,48 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float *kernel, float offset) {
135153 out [x ] = in0 [x ];
136154 }
137155 } else {
156+ int bigendian = 0 ;
157+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
158+ if (strcmp (im -> mode , "I;16B" ) == 0
159+ #ifdef WORDS_BIGENDIAN
160+ || strcmp (im -> mode , "I;16N" ) == 0
161+ #endif
162+ ) {
163+ bigendian = 1 ;
164+ }
165+ }
138166 for (y = 1 ; y < im -> ysize - 1 ; y ++ ) {
139167 UINT8 * in_1 = (UINT8 * )im -> image [y - 1 ];
140168 UINT8 * in0 = (UINT8 * )im -> image [y ];
141169 UINT8 * in1 = (UINT8 * )im -> image [y + 1 ];
142170 UINT8 * out = (UINT8 * )imOut -> image [y ];
143171
144172 out [0 ] = in0 [0 ];
173+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
174+ out [1 ] = in0 [1 ];
175+ }
145176 for (x = 1 ; x < im -> xsize - 1 ; x ++ ) {
146177 float ss = offset ;
147- ss += KERNEL1x3 (in1 , x , & kernel [0 ], 1 );
148- ss += KERNEL1x3 (in0 , x , & kernel [3 ], 1 );
149- ss += KERNEL1x3 (in_1 , x , & kernel [6 ], 1 );
150- out [x ] = clip8 (ss );
178+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
179+ ss += kernel_i16 (3 , in1 , x , & kernel [0 ], bigendian );
180+ ss += kernel_i16 (3 , in0 , x , & kernel [3 ], bigendian );
181+ ss += kernel_i16 (3 , in_1 , x , & kernel [6 ], bigendian );
182+ int ss_int = ROUND_UP (ss );
183+ out [x * 2 + (bigendian ? 1 : 0 )] = clip8 (ss_int % 256 );
184+ out [x * 2 + (bigendian ? 0 : 1 )] = clip8 (ss_int >> 8 );
185+ } else {
186+ ss += KERNEL1x3 (in1 , x , & kernel [0 ], 1 );
187+ ss += KERNEL1x3 (in0 , x , & kernel [3 ], 1 );
188+ ss += KERNEL1x3 (in_1 , x , & kernel [6 ], 1 );
189+ out [x ] = clip8 (ss );
190+ }
191+ }
192+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
193+ out [x * 2 ] = in0 [x * 2 ];
194+ out [x * 2 + 1 ] = in0 [x * 2 + 1 ];
195+ } else {
196+ out [x ] = in0 [x ];
151197 }
152- out [x ] = in0 [x ];
153198 }
154199 }
155200 } else {
@@ -261,6 +306,16 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float *kernel, float offset) {
261306 out [x + 1 ] = in0 [x + 1 ];
262307 }
263308 } else {
309+ int bigendian = 0 ;
310+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
311+ if (strcmp (im -> mode , "I;16B" ) == 0
312+ #ifdef WORDS_BIGENDIAN
313+ || strcmp (im -> mode , "I;16N" ) == 0
314+ #endif
315+ ) {
316+ bigendian = 1 ;
317+ }
318+ }
264319 for (y = 2 ; y < im -> ysize - 2 ; y ++ ) {
265320 UINT8 * in_2 = (UINT8 * )im -> image [y - 2 ];
266321 UINT8 * in_1 = (UINT8 * )im -> image [y - 1 ];
@@ -271,17 +326,39 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float *kernel, float offset) {
271326
272327 out [0 ] = in0 [0 ];
273328 out [1 ] = in0 [1 ];
329+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
330+ out [2 ] = in0 [2 ];
331+ out [3 ] = in0 [3 ];
332+ }
274333 for (x = 2 ; x < im -> xsize - 2 ; x ++ ) {
275334 float ss = offset ;
276- ss += KERNEL1x5 (in2 , x , & kernel [0 ], 1 );
277- ss += KERNEL1x5 (in1 , x , & kernel [5 ], 1 );
278- ss += KERNEL1x5 (in0 , x , & kernel [10 ], 1 );
279- ss += KERNEL1x5 (in_1 , x , & kernel [15 ], 1 );
280- ss += KERNEL1x5 (in_2 , x , & kernel [20 ], 1 );
281- out [x ] = clip8 (ss );
335+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
336+ ss += kernel_i16 (5 , in2 , x , & kernel [0 ], bigendian );
337+ ss += kernel_i16 (5 , in1 , x , & kernel [5 ], bigendian );
338+ ss += kernel_i16 (5 , in0 , x , & kernel [10 ], bigendian );
339+ ss += kernel_i16 (5 , in_1 , x , & kernel [15 ], bigendian );
340+ ss += kernel_i16 (5 , in_2 , x , & kernel [20 ], bigendian );
341+ int ss_int = ROUND_UP (ss );
342+ out [x * 2 + (bigendian ? 1 : 0 )] = clip8 (ss_int % 256 );
343+ out [x * 2 + (bigendian ? 0 : 1 )] = clip8 (ss_int >> 8 );
344+ } else {
345+ ss += KERNEL1x5 (in2 , x , & kernel [0 ], 1 );
346+ ss += KERNEL1x5 (in1 , x , & kernel [5 ], 1 );
347+ ss += KERNEL1x5 (in0 , x , & kernel [10 ], 1 );
348+ ss += KERNEL1x5 (in_1 , x , & kernel [15 ], 1 );
349+ ss += KERNEL1x5 (in_2 , x , & kernel [20 ], 1 );
350+ out [x ] = clip8 (ss );
351+ }
352+ }
353+ if (im -> type == IMAGING_TYPE_SPECIAL ) {
354+ out [x * 2 + 0 ] = in0 [x * 2 + 0 ];
355+ out [x * 2 + 1 ] = in0 [x * 2 + 1 ];
356+ out [x * 2 + 2 ] = in0 [x * 2 + 2 ];
357+ out [x * 2 + 3 ] = in0 [x * 2 + 3 ];
358+ } else {
359+ out [x + 0 ] = in0 [x + 0 ];
360+ out [x + 1 ] = in0 [x + 1 ];
282361 }
283- out [x + 0 ] = in0 [x + 0 ];
284- out [x + 1 ] = in0 [x + 1 ];
285362 }
286363 }
287364 } else {
@@ -383,7 +460,8 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32 *kernel, FLOAT32 o
383460 Imaging imOut ;
384461 ImagingSectionCookie cookie ;
385462
386- if (im -> type != IMAGING_TYPE_UINT8 && im -> type != IMAGING_TYPE_INT32 ) {
463+ if (im -> type == IMAGING_TYPE_FLOAT32 ||
464+ (im -> type == IMAGING_TYPE_SPECIAL && im -> bands != 1 )) {
387465 return (Imaging )ImagingError_ModeError ();
388466 }
389467
0 commit comments