@@ -162,8 +162,9 @@ union [[gnu::packed]] Pixel {
162
162
static_assert (sizeof (Pixel) == 4 );
163
163
164
164
template <bool has_alpha, byte filter_type>
165
- [[gnu::always_inline]] static inline void unfilter_impl (const GraphicsBitmap& bitmap, int y)
165
+ [[gnu::always_inline]] static inline void unfilter_impl (const GraphicsBitmap& bitmap, int y, const void * dummy_scanline_data )
166
166
{
167
+ auto * dummy_scanline = (const Pixel*)dummy_scanline_data;
167
168
if constexpr (filter_type == 1 ) {
168
169
auto * pixels = (Pixel*)bitmap.scanline (y);
169
170
for (int i = 0 ; i < bitmap.width (); ++i) {
@@ -181,11 +182,12 @@ template<bool has_alpha, byte filter_type>
181
182
}
182
183
if constexpr (filter_type == 2 ) {
183
184
auto * pixels = (Pixel*)bitmap.scanline (y);
185
+ auto * pixels_y_minus_1 = y == 0 ? dummy_scanline : (Pixel*)bitmap.scanline (y - 1 );
184
186
for (int i = 0 ; i < bitmap.width (); ++i) {
185
187
auto & x = pixels[i];
186
188
swap (x.r , x.b );
187
189
Pixel b;
188
- if (y != 0 ) b.rgba = bitmap. scanline (y - 1 ) [i];
190
+ b.rgba = pixels_y_minus_1 [i]. rgba ;
189
191
x.r += b.r ;
190
192
x.g += b.g ;
191
193
x.b += b.b ;
@@ -197,13 +199,14 @@ template<bool has_alpha, byte filter_type>
197
199
198
200
if constexpr (filter_type == 3 ) {
199
201
auto * pixels = (Pixel*)bitmap.scanline (y);
202
+ auto * pixels_y_minus_1 = y == 0 ? dummy_scanline : (Pixel*)bitmap.scanline (y - 1 );
200
203
for (int i = 0 ; i < bitmap.width (); ++i) {
201
204
auto & x = pixels[i];
202
205
swap (x.r , x.b );
203
206
Pixel a;
204
207
Pixel b;
205
208
if (i != 0 ) a.rgba = bitmap.scanline (y)[i - 1 ];
206
- if (y != 0 ) b.rgba = bitmap. scanline (y - 1 ) [i];
209
+ b.rgba = pixels_y_minus_1 [i]. rgba ;
207
210
x.r = x.r + ((a.r + b.r ) / 2 );
208
211
x.g = x.g + ((a.g + b.g ) / 2 );
209
212
x.b = x.b + ((a.b + b.b ) / 2 );
@@ -215,15 +218,18 @@ template<bool has_alpha, byte filter_type>
215
218
216
219
if constexpr (filter_type == 4 ) {
217
220
auto * pixels = (Pixel*)bitmap.scanline (y);
221
+ auto * pixels_y_minus_1 = y == 0 ? dummy_scanline : (Pixel*)bitmap.scanline (y - 1 );
218
222
for (int i = 0 ; i < bitmap.width (); ++i) {
219
223
auto & x = pixels[i];
220
224
swap (x.r , x.b );
221
225
Pixel a;
222
226
Pixel b;
223
227
Pixel c;
224
- if (i != 0 ) a.rgba = bitmap.scanline (y)[i - 1 ];
225
- if (y != 0 ) b.rgba = bitmap.scanline (y - 1 )[i];
226
- if (y != 0 && i != 0 ) c.rgba = bitmap.scanline (y - 1 )[i - 1 ];
228
+ if (i != 0 ) {
229
+ a.rgba = bitmap.scanline (y)[i - 1 ];
230
+ c.rgba = pixels_y_minus_1[i - 1 ].rgba ;
231
+ }
232
+ b.rgba = pixels_y_minus_1[i].rgba ;
227
233
x.r += paeth_predictor (a.r , b.r , c.r );
228
234
x.g += paeth_predictor (a.g , b.g , c.g );
229
235
x.b += paeth_predictor (a.b , b.b , c.b );
@@ -233,9 +239,6 @@ template<bool has_alpha, byte filter_type>
233
239
}
234
240
}
235
241
236
-
237
-
238
-
239
242
[[gnu::noinline]] static void unfilter (PNGLoadingContext& context)
240
243
{
241
244
{
@@ -266,37 +269,39 @@ template<bool has_alpha, byte filter_type>
266
269
}
267
270
}
268
271
272
+ auto dummy_scanline = ByteBuffer::create_zeroed (context.width * sizeof (RGBA32));
273
+
269
274
Stopwatch sw (" load_png_impl: unfilter: process" );
270
275
for (int y = 0 ; y < context.height ; ++y) {
271
276
auto filter = context.scanlines [y].filter ;
272
277
if (filter == 0 )
273
278
continue ;
274
279
if (filter == 1 ) {
275
280
if (context.has_alpha ())
276
- unfilter_impl<true , 1 >(*context.bitmap , y);
281
+ unfilter_impl<true , 1 >(*context.bitmap , y, dummy_scanline. pointer () );
277
282
else
278
- unfilter_impl<false , 1 >(*context.bitmap , y);
283
+ unfilter_impl<false , 1 >(*context.bitmap , y, dummy_scanline. pointer () );
279
284
continue ;
280
285
}
281
286
if (filter == 2 ) {
282
287
if (context.has_alpha ())
283
- unfilter_impl<true , 2 >(*context.bitmap , y);
288
+ unfilter_impl<true , 2 >(*context.bitmap , y, dummy_scanline. pointer () );
284
289
else
285
- unfilter_impl<false , 2 >(*context.bitmap , y);
290
+ unfilter_impl<false , 2 >(*context.bitmap , y, dummy_scanline. pointer () );
286
291
continue ;
287
292
}
288
293
if (filter == 3 ) {
289
294
if (context.has_alpha ())
290
- unfilter_impl<true , 3 >(*context.bitmap , y);
295
+ unfilter_impl<true , 3 >(*context.bitmap , y, dummy_scanline. pointer () );
291
296
else
292
- unfilter_impl<false , 3 >(*context.bitmap , y);
297
+ unfilter_impl<false , 3 >(*context.bitmap , y, dummy_scanline. pointer () );
293
298
continue ;
294
299
}
295
300
if (filter == 4 ) {
296
301
if (context.has_alpha ())
297
- unfilter_impl<true , 4 >(*context.bitmap , y);
302
+ unfilter_impl<true , 4 >(*context.bitmap , y, dummy_scanline. pointer () );
298
303
else
299
- unfilter_impl<false , 4 >(*context.bitmap , y);
304
+ unfilter_impl<false , 4 >(*context.bitmap , y, dummy_scanline. pointer () );
300
305
continue ;
301
306
}
302
307
}
0 commit comments