Skip to content
This repository was archived by the owner on Mar 7, 2025. It is now read-only.

Commit f836f17

Browse files
filipnavaraakoeplinger
authored andcommitted
Emit tRNS PNG chunk for images with alpha channel in palette. (#47)
* Emit tRNS PNG chunk for images with alpha channel in palette. * Add test case for PNG tRNS round-tripping
1 parent bfe37a2 commit f836f17

File tree

5 files changed

+86
-6
lines changed

5 files changed

+86
-6
lines changed

src/pngcodec.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ gdip_save_png_image_to_file_or_stream (FILE *fp, PutBytesDelegate putBytesFunc,
708708

709709
if (gdip_is_an_indexed_pixelformat (image->active_bitmap->pixel_format)) {
710710
png_color palette[256];
711+
png_byte trans_alpha[256];
711712

712713
int palette_entries = image->active_bitmap->palette->Count;
713714
if (image->active_bitmap->pixel_format == PixelFormat4bppIndexed) {
@@ -716,13 +717,13 @@ gdip_save_png_image_to_file_or_stream (FILE *fp, PutBytesDelegate putBytesFunc,
716717

717718
for (i=0; i < palette_entries; i++) {
718719
ARGB entry = image->active_bitmap->palette->Entries[i];
719-
720-
int dummy;
721-
722-
get_pixel_bgra(entry, palette[i].blue, palette[i].green, palette[i].red, dummy);
720+
get_pixel_bgra(entry, palette[i].blue, palette[i].green, palette[i].red, trans_alpha[i]);
723721
}
724722

725723
png_set_PLTE (png_ptr, info_ptr, palette, palette_entries);
724+
if ((image->active_bitmap->palette->Flags & PaletteFlagsHasAlpha) == PaletteFlagsHasAlpha) {
725+
png_set_tRNS (png_ptr, info_ptr, trans_alpha, palette_entries, NULL);
726+
}
726727
}
727728

728729
png_set_filter (png_ptr, 0, PNG_NO_FILTERS);

tests/.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ testbits
77
testclip
88
testgdi
99
testreversepath
10-
10+
testpng

tests/Makefile.am

+9-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LDADDS = \
1717
-lm
1818

1919
noinst_PROGRAMS = \
20-
testbits testclip testreversepath
20+
testbits testclip testreversepath testpng
2121

2222
if HAS_X11
2323
noinst_PROGRAMS =
@@ -48,14 +48,22 @@ testreversepath_SOURCES = \
4848
testreversepath_DEPENDENCIES = $(TEST_DEPS)
4949
testreversepath_LDADD = $(LDADDS)
5050

51+
testpng_DEPENDENCIES = $(TEST_DEPS)
52+
testpng_LDADD = $(LDADDS)
53+
54+
testpng_SOURCES = \
55+
testpng.c
56+
5157
EXTRA_DIST = \
5258
$(testgdi_SOURCES) \
5359
$(testbits_SOURCES) \
5460
$(testclip_SOURCES) \
61+
$(testpng_SOURCES) \
5562
$(testreversepath_SOURCES)
5663

5764
TESTS = \
5865
testbits \
5966
testclip \
6067
testreversepath \
68+
testpng \
6169
$(NULL)

tests/test-trns.png

237 Bytes
Loading

tests/testpng.c

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <unistd.h>
4+
#include <string.h>
5+
6+
#include "GdiPlusFlat.h"
7+
8+
static int status_counter = 0;
9+
10+
#define CHECK_STATUS(x) do { if (status != Ok) { printf ("status[%d] == %d!\n", status_counter++, status); if(x) { exit(-1); } } else { printf ("status[%d] == Ok\n", status_counter++); } } while (0)
11+
#define CHECK_ASSERT(x) do { if (!(x)) { printf ("check %s at %s:%d failed\n", #x, __FILE__, __LINE__); exit(-1); } else { printf("check %s at %s:%d passed\n", #x, __FILE__, __LINE__); } } while (0)
12+
13+
CLSID png_clsid = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
14+
15+
int
16+
main (int argc, char **argv)
17+
{
18+
GpImage *img;
19+
gunichar2 *unis;
20+
GpBitmap *bitmap;
21+
GpStatus status;
22+
int original_palette_size;
23+
int reloaded_palette_size;
24+
ColorPalette *original_palette;
25+
ColorPalette *reloaded_palette;
26+
GdiplusStartupInput gdiplusStartupInput;
27+
ULONG_PTR gdiplusToken;
28+
29+
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
30+
31+
// PNG resave should preserve the palette transparency. Let's test it
32+
// by loading a PNG file and its palette, then resaving it and loading
33+
// it again for comparison.
34+
unis = g_utf8_to_utf16 ("test-trns.png", -1, NULL, NULL, NULL);
35+
status = GdipLoadImageFromFile (unis, &img);
36+
CHECK_STATUS(1);
37+
g_free (unis);
38+
39+
status = GdipGetImagePaletteSize (img, &original_palette_size);
40+
CHECK_STATUS(1);
41+
CHECK_ASSERT(original_palette_size > 0);
42+
original_palette = malloc (original_palette_size);
43+
GdipGetImagePalette (img, original_palette, original_palette_size);
44+
CHECK_STATUS(1);
45+
46+
unis = g_utf8_to_utf16 ("test-trns-resave.png", -1, NULL, NULL, NULL);
47+
status = GdipSaveImageToFile (img, unis, &png_clsid, NULL);
48+
CHECK_STATUS(1);
49+
GdipDisposeImage (img);
50+
status = GdipLoadImageFromFile (unis, &img);
51+
CHECK_STATUS(1);
52+
g_free (unis);
53+
54+
status = GdipGetImagePaletteSize (img, &reloaded_palette_size);
55+
CHECK_STATUS(1);
56+
CHECK_ASSERT(reloaded_palette_size > 0);
57+
CHECK_ASSERT(reloaded_palette_size == original_palette_size);
58+
reloaded_palette = malloc (reloaded_palette_size);
59+
GdipGetImagePalette (img, reloaded_palette, reloaded_palette_size);
60+
CHECK_STATUS(1);
61+
62+
CHECK_ASSERT(memcmp (original_palette, reloaded_palette, original_palette_size) == 0);
63+
64+
GdipDisposeImage (img);
65+
img = NULL;
66+
unlink ("test-trns-resave.png");
67+
free (original_palette);
68+
free (reloaded_palette);
69+
70+
return 0;
71+
}

0 commit comments

Comments
 (0)