@@ -214,7 +214,7 @@ union [[gnu::packed]] Pixel {
214
214
};
215
215
static_assert (AssertSize<Pixel, 4 >());
216
216
217
- template <bool include_alpha>
217
+ template <bool include_alpha, bool include_colors >
218
218
static ErrorOr<void > add_image_data_to_chunk_impl (Gfx::Bitmap const & bitmap, PNGChunk& png_chunk, Compress::ZlibCompressionLevel compression_level)
219
219
{
220
220
ByteBuffer uncompressed_block_data;
@@ -259,7 +259,9 @@ static ErrorOr<void> add_image_data_to_chunk_impl(Gfx::Bitmap const& bitmap, PNG
259
259
260
260
u32 sum_of_abs_values () const
261
261
{
262
- u32 result = sum[0 ] + sum[1 ] + sum[2 ];
262
+ u32 result = sum[0 ];
263
+ if constexpr (include_colors)
264
+ result += sum[1 ] + sum[2 ];
263
265
if constexpr (include_alpha)
264
266
result += sum[3 ];
265
267
return result;
@@ -315,8 +317,10 @@ static ErrorOr<void> add_image_data_to_chunk_impl(Gfx::Bitmap const& bitmap, PNG
315
317
auto pixel_y_minus_1 = Pixel::argb32_to_simd (scanline_minus_1[x]);
316
318
317
319
auto predicted_pixel = best_filter.predict (pixel, pixel_x_minus_1, pixel_y_minus_1, pixel_xy_minus_1);
318
- TRY (uncompressed_block_data.try_append (predicted_pixel[2 ]));
319
- TRY (uncompressed_block_data.try_append (predicted_pixel[1 ]));
320
+ if constexpr (include_colors) {
321
+ TRY (uncompressed_block_data.try_append (predicted_pixel[2 ]));
322
+ TRY (uncompressed_block_data.try_append (predicted_pixel[1 ]));
323
+ }
320
324
TRY (uncompressed_block_data.try_append (predicted_pixel[0 ]));
321
325
if constexpr (include_alpha)
322
326
TRY (uncompressed_block_data.try_append (predicted_pixel[3 ]));
@@ -335,15 +339,15 @@ static ErrorOr<void> add_image_data_to_chunk(Gfx::Bitmap const& bitmap, PNG::Col
335
339
{
336
340
switch (color_type) {
337
341
case PNG::ColorType::Greyscale:
338
- VERIFY_NOT_REACHED ( );
342
+ return add_image_data_to_chunk_impl< false , false >(bitmap, png_chunk, compression_level );
339
343
case PNG::ColorType::Truecolor:
340
- return add_image_data_to_chunk_impl<false >(bitmap, png_chunk, compression_level);
344
+ return add_image_data_to_chunk_impl<false , true >(bitmap, png_chunk, compression_level);
341
345
case PNG::ColorType::IndexedColor:
342
346
VERIFY_NOT_REACHED ();
343
347
case PNG::ColorType::GreyscaleWithAlpha:
344
- VERIFY_NOT_REACHED ( );
348
+ return add_image_data_to_chunk_impl< true , false >(bitmap, png_chunk, compression_level );
345
349
case PNG::ColorType::TruecolorWithAlpha:
346
- return add_image_data_to_chunk_impl<true >(bitmap, png_chunk, compression_level);
350
+ return add_image_data_to_chunk_impl<true , true >(bitmap, png_chunk, compression_level);
347
351
}
348
352
VERIFY_NOT_REACHED ();
349
353
}
@@ -375,13 +379,34 @@ static bool bitmap_has_transparency(Bitmap const& bitmap)
375
379
return false ;
376
380
}
377
381
378
- ErrorOr< void > PNGWriter::encode (Stream& stream, Bitmap const & bitmap, Options const & options )
382
+ static bool bitmap_has_color ( Bitmap const & bitmap)
379
383
{
380
- bool has_transparency = options.force_alpha || bitmap_has_transparency (bitmap);
384
+ for (auto pixel : bitmap) {
385
+ auto color = Color::from_argb (pixel);
386
+ if (color.red () != color.green () || color.green () != color.blue ())
387
+ return true ;
388
+ }
389
+ return false ;
390
+ }
381
391
392
+ static PNG::ColorType find_color_type (Bitmap const & bitmap, bool force_alpha)
393
+ {
394
+ bool has_alpha = force_alpha || bitmap_has_transparency (bitmap);
395
+ if (bitmap_has_color (bitmap)) {
396
+ if (has_alpha)
397
+ return PNG::ColorType::TruecolorWithAlpha;
398
+ return PNG::ColorType::Truecolor;
399
+ }
400
+ if (has_alpha)
401
+ return PNG::ColorType::GreyscaleWithAlpha;
402
+ return PNG::ColorType::Greyscale;
403
+ }
404
+
405
+ ErrorOr<void > PNGWriter::encode (Stream& stream, Bitmap const & bitmap, Options const & options)
406
+ {
382
407
PNGWriter writer { stream };
383
408
TRY (writer.add_png_header ());
384
- auto color_type = has_transparency ? PNG::ColorType::TruecolorWithAlpha : PNG::ColorType::Truecolor ;
409
+ auto color_type = find_color_type (bitmap, options. force_alpha ) ;
385
410
TRY (writer.add_IHDR_chunk (bitmap.width (), bitmap.height (), 8 , color_type, 0 , 0 , 0 ));
386
411
if (options.icc_data .has_value ())
387
412
TRY (writer.add_iCCP_chunk (options.icc_data .value (), options.compression_level ));
0 commit comments