@@ -47,15 +47,53 @@ static inline float byte_to_float(uint8 b/*, uniform bool degamma*/) {
4747 return (float )b * inv_255;
4848}
4949
50- static inline uint8 float_to_byte (float d, bool gamma) {
50+ static inline uint8 float_to_byte (float d, uniform bool gamma) {
5151 if (gamma) {
5252 d = pow (d, DEGAMMA );
5353 }
5454 int b = d * 255 ;
5555 return clamp (b, 0 , 255 );
5656}
5757
58- static inline float < 4 > resample_internal (const uniform Image src_image, const float < 2 > uv, const uniform uint8 num_channels) {
58+ template < typename IT >
59+ static float < 4 > sample_image (const uniform IT &image, const int < 2 > coord, const uniform uint8 num_channels) {
60+ return 0.0f ;
61+ }
62+
63+ template <>
64+ static float < 4 > sample_image< Image> (const uniform Image &image, const int < 2 > coord, const uniform uint8 num_channels) {
65+ float < 4 > col = 0.0 ;
66+ int x = clamp (coord. x, 0 , image. size. x - 1 );
67+ int y = clamp (coord. y, 0 , image. size. y - 1 );
68+ int addr = (x + y * image. size. x) * num_channels;
69+
70+ col[0 ] = byte_to_float (image. data[addr + 0 ]);
71+ col[1 ] = byte_to_float (image. data[addr + 1 ]);
72+ col[2 ] = byte_to_float (image. data[addr + 2 ]);
73+ if (num_channels == 4 )
74+ col[3 ] = byte_to_float (image. data[addr + 3 ]);
75+
76+ return col;
77+ }
78+
79+ template <>
80+ static float < 4 > sample_image< FloatImage> (const uniform FloatImage &image, const int < 2 > coord, const uniform uint8 num_channels) {
81+ float < 4 > col = 0.0 ;
82+ int x = clamp (coord. x, 0 , image. size. x - 1 );
83+ int y = clamp (coord. y, 0 , image. size. y - 1 );
84+ int addr = (x + y * image. size. x) * num_channels;
85+
86+ col[0 ] = image. data[addr + 0 ];
87+ col[1 ] = image. data[addr + 1 ];
88+ col[2 ] = image. data[addr + 2 ];
89+ if (num_channels == 4 )
90+ col[3 ] = image. data[addr + 3 ];
91+
92+ return col;
93+ }
94+
95+ template < typename IT >
96+ static inline float < 4 > resample_internal (const uniform IT src_image, const float < 2 > uv, const uniform uint8 num_channels) {
5997 float < 4 > col = 0.0 ;
6098 uniform float weight = 0.0 ;
6199 // Truncate floating point coordinate to integer:
@@ -72,61 +110,57 @@ static inline float<4> resample_internal(const uniform Image src_image, const fl
72110 const uniform float w = wx * wy;
73111 const uniform int < 2 > texel_offset = {x, y};
74112
75- int < 2 > src_kernel_coord = src_coord + texel_offset;
113+ int < 2 > c = src_coord + texel_offset;
76114 // TODO: Let the user specify a boundary mode!
77115 // https://github.com/Traverse-Research/ispc-downsampler/issues/25#issuecomment-1584915050
78- src_kernel_coord . x = clamp (src_kernel_coord . x, 0 , src_image . size . x - 1 );
79- src_kernel_coord . y = clamp (src_kernel_coord . y, 0 , src_image . size . y - 1 );
80-
81- const int addr = (src_kernel_coord . x + src_kernel_coord . y * src_image. size. x) * num_channels ;
116+ // TODO: For some obscure reason this must happen in sample_image() or the whole thing segfaults because
117+ // values become <0 !?!?
118+ // c.x = clamp(c.x, 0, src_image.size.x - 1);
119+ // c.y = clamp(c.y, 0, src_image.size.y - 1) ;
82120
83- float < 4 > texel;
84- texel. x = byte_to_float (src_image. data[addr + 0 ]);
85- texel. y = byte_to_float (src_image. data[addr + 1 ]);
86- texel. z = byte_to_float (src_image. data[addr + 2 ]);
87- if (num_channels >= 4 )
88- texel. w = byte_to_float (src_image. data[addr + 3 ]);
89-
90- col += w * texel;
91121 weight += w;
122+ col += w * sample_image< IT > (src_image, c, num_channels);
92123 }
93124 }
94125 col /= weight;
95126 return col;
96-
97127}
98128
99129export void resample (
100- uniform const Parameters * uniform params,
101- uniform const Image * uniform src,
102- uniform Image * uniform dst,
130+ uniform const Parameters ¶ms,
131+ uniform const Image &src,
132+ uniform FloatImage °amma,
133+ uniform Image &dst,
103134 // Passed separately because it should be the same between input and output:
104135 uniform uint8 num_channels
105136) {
106- const uniform float < 2 > inv_target_size = 1.0f / dst-> size;
137+ const uniform float < 2 > inv_target_size = 1.0f / dst. size;
107138
108- if (params-> degamma) {
109- foreach_tiled (y = 0 ... src-> size. y, x = 0 ... src-> size. x)
139+ if (params. degamma) {
140+ foreach_tiled (y = 0 ... src. size. y, x = 0 ... src. size. x)
110141 {
111- uint p = (x + y * src-> size. x) * num_channels;
142+ uint p = (x + y * src. size. x) * num_channels;
112143 for (uniform int i = 0 ; i < num_channels; i++ ) {
113144 uint c = p + i;
114- // TODO: This texture should be writeonly!
115- src-> data[c] = float_to_byte (pow (byte_to_float (src-> data[c]), GAMMA ), false );
145+ degamma. data[c] = pow (byte_to_float (src. data[c]), GAMMA );
116146 }
117147 }
118148 }
119149
120- foreach_tiled (y = 0 ... dst-> size. y, x = 0 ... dst-> size. x) {
150+ foreach_tiled (y = 0 ... dst. size. y, x = 0 ... dst. size. x) {
121151 float < 2 > uv = {x, y};
122152 // Use the center of each pixel, not the top-left:
123153 uv += 0.5f ;
124154 // Convert to uniform space:
125155 uv *= inv_target_size;
126156
127- const float < 4 > col = resample_internal (* src, uv, num_channels);
157+ float < 4 > col;
158+ if (params. degamma)
159+ col = resample_internal (degamma, uv, num_channels);
160+ else
161+ col = resample_internal (src, uv, num_channels);
128162
129163 for (uniform int i = 0 ; i < num_channels; i++ )
130- dst-> data[(x + y * dst-> size. x) * num_channels + i] = float_to_byte (col[i], params-> gamma);
164+ dst. data[(x + y * dst. size. x) * num_channels + i] = float_to_byte (col[i], params. gamma);
131165 }
132166}
0 commit comments