Skip to content

fix the pngsave bitdepth param #4516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 54 additions & 51 deletions libvips/colour/colourspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,15 @@ typedef struct _VipsColourRoute {
#define scRGB VIPS_INTERPRETATION_scRGB
#define sRGB VIPS_INTERPRETATION_sRGB
#define HSV VIPS_INTERPRETATION_HSV
#define BW VIPS_INTERPRETATION_B_W
#define RGB16 VIPS_INTERPRETATION_RGB16
#define GREY16 VIPS_INTERPRETATION_GREY16
#define YXY VIPS_INTERPRETATION_YXY
#define BW VIPS_INTERPRETATION_B_W

/* All the routes we know about.
*/
static VipsColourRoute vips_colour_routes[] = {
{ XYZ, XYZ, { vips_cast_float, NULL } },
{ XYZ, LAB, { vips_XYZ2Lab, NULL } },
{ XYZ, LABQ, { vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ XYZ, LCH, { vips_XYZ2Lab, vips_Lab2LCh, NULL } },
Expand All @@ -234,6 +235,7 @@ static VipsColourRoute vips_colour_routes[] = {
{ XYZ, YXY, { vips_XYZ2Yxy, NULL } },

{ LAB, XYZ, { vips_Lab2XYZ, NULL } },
{ LAB, LAB, { vips_cast_float, NULL } },
{ LAB, LABQ, { vips_Lab2LabQ, NULL } },
{ LAB, LCH, { vips_Lab2LCh, NULL } },
{ LAB, CMC, { vips_Lab2LCh, vips_LCh2CMC, NULL } },
Expand All @@ -249,6 +251,7 @@ static VipsColourRoute vips_colour_routes[] = {

{ LABQ, XYZ, { vips_LabQ2Lab, vips_Lab2XYZ, NULL } },
{ LABQ, LAB, { vips_LabQ2Lab, NULL } },
{ LABQ, LABQ, { NULL } },
{ LABQ, LCH, { vips_LabQ2Lab, vips_Lab2LCh, NULL } },
{ LABQ, CMC, { vips_LabQ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ LABQ, LABS, { vips_LabQ2LabS, NULL } },
Expand All @@ -264,6 +267,7 @@ static VipsColourRoute vips_colour_routes[] = {
{ LCH, XYZ, { vips_LCh2Lab, vips_Lab2XYZ, NULL } },
{ LCH, LAB, { vips_LCh2Lab, NULL } },
{ LCH, LABQ, { vips_LCh2Lab, vips_Lab2LabQ, NULL } },
{ LCH, LCH, { vips_cast_float, NULL } },
{ LCH, CMC, { vips_LCh2CMC, NULL } },
{ LCH, LABS, { vips_LCh2Lab, vips_Lab2LabS, NULL } },
{ LCH, CMYK, { vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2CMYK, NULL } },
Expand All @@ -279,6 +283,7 @@ static VipsColourRoute vips_colour_routes[] = {
{ CMC, LAB, { vips_CMC2LCh, vips_LCh2Lab, NULL } },
{ CMC, LABQ, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2LabQ, NULL } },
{ CMC, LCH, { vips_CMC2LCh, NULL } },
{ CMC, CMC, { vips_cast_float, NULL } },
{ CMC, LABS, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2LabS, NULL } },
{ CMC, CMYK, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2CMYK, NULL } },
{ CMC, scRGB, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, NULL } },
Expand All @@ -294,6 +299,7 @@ static VipsColourRoute vips_colour_routes[] = {
{ LABS, LABQ, { vips_LabS2LabQ, NULL } },
{ LABS, LCH, { vips_LabS2Lab, vips_Lab2LCh, NULL } },
{ LABS, CMC, { vips_LabS2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ LABS, LABS, { vips_cast_short, NULL } },
{ LABS, CMYK, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2CMYK, NULL } },
{ LABS, scRGB, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, NULL } },
{ LABS, sRGB, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, vips_scRGB2sRGB, NULL } },
Expand All @@ -303,44 +309,48 @@ static VipsColourRoute vips_colour_routes[] = {
{ LABS, GREY16, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, vips_scRGB2BW16, NULL } },
{ LABS, YXY, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2Yxy, NULL } },

{ scRGB, XYZ, { vips_scRGB2XYZ, NULL } },
{ scRGB, LAB, { vips_scRGB2XYZ, vips_XYZ2Lab, NULL } },
{ scRGB, LABQ, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ scRGB, LCH, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ scRGB, CMC, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ scRGB, CMYK, { vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ scRGB, sRGB, { vips_scRGB2sRGB, NULL } },
{ scRGB, HSV, { vips_scRGB2sRGB, vips_sRGB2HSV, NULL } },
{ scRGB, BW, { vips_scRGB2BW, NULL } },
{ scRGB, LABS, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ scRGB, RGB16, { vips_scRGB2RGB16, NULL } },
{ scRGB, GREY16, { vips_scRGB2BW16, NULL } },
{ scRGB, YXY, { vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },

{ CMYK, XYZ, { vips_CMYK2XYZ, NULL } },
{ CMYK, LAB, { vips_CMYK2XYZ, vips_XYZ2Lab, NULL } },
{ CMYK, LABQ, { vips_CMYK2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ CMYK, LCH, { vips_CMYK2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ CMYK, CMC, { vips_CMYK2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ CMYK, LABS, { vips_CMYK2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
// can be 8 or 16 bit, so do nothing
{ CMYK, CMYK, { NULL } },
{ CMYK, scRGB, { vips_CMYK2XYZ, vips_XYZ2scRGB, NULL } },
{ CMYK, sRGB, { vips_CMYK2XYZ, vips_XYZ2scRGB, vips_scRGB2sRGB, NULL } },
{ CMYK, HSV, { vips_CMYK2XYZ, vips_XYZ2scRGB, vips_scRGB2sRGB, vips_sRGB2HSV, NULL } },
{ CMYK, BW, { vips_CMYK2XYZ, vips_XYZ2scRGB, vips_scRGB2BW, NULL } },
{ CMYK, LABS, { vips_CMYK2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ CMYK, RGB16, { vips_CMYK2XYZ, vips_XYZ2scRGB, vips_scRGB2RGB16, NULL } },
{ CMYK, GREY16, { vips_CMYK2XYZ, vips_XYZ2scRGB, vips_scRGB2BW16, NULL } },
{ CMYK, YXY, { vips_CMYK2XYZ, vips_XYZ2Yxy, NULL } },

{ scRGB, XYZ, { vips_scRGB2XYZ, NULL } },
{ scRGB, LAB, { vips_scRGB2XYZ, vips_XYZ2Lab, NULL } },
{ scRGB, LABQ, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ scRGB, LCH, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ scRGB, CMC, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ scRGB, LABS, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ scRGB, CMYK, { vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ scRGB, scRGB, { vips_cast_float, NULL } },
{ scRGB, sRGB, { vips_scRGB2sRGB, NULL } },
{ scRGB, HSV, { vips_scRGB2sRGB, vips_sRGB2HSV, NULL } },
{ scRGB, BW, { vips_scRGB2BW, NULL } },
{ scRGB, RGB16, { vips_scRGB2RGB16, NULL } },
{ scRGB, GREY16, { vips_scRGB2BW16, NULL } },
{ scRGB, YXY, { vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },

{ sRGB, XYZ, { vips_sRGB2scRGB, vips_scRGB2XYZ, NULL } },
{ sRGB, LAB, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, NULL } },
{ sRGB, LABQ, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ sRGB, LCH, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ sRGB, CMC, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ sRGB, LABS, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ sRGB, CMYK, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ sRGB, scRGB, { vips_sRGB2scRGB, NULL } },
{ sRGB, sRGB, { vips_cast_uchar, NULL } },
{ sRGB, HSV, { vips_sRGB2HSV, NULL } },
{ sRGB, BW, { vips_sRGB2scRGB, vips_scRGB2BW, NULL } },
{ sRGB, LABS, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ sRGB, RGB16, { vips_sRGB2RGB16, NULL } },
{ sRGB, GREY16, { vips_sRGB2scRGB, vips_scRGB2BW16, NULL } },
{ sRGB, YXY, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },
Expand All @@ -350,26 +360,43 @@ static VipsColourRoute vips_colour_routes[] = {
{ HSV, LABQ, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ HSV, LCH, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ HSV, CMC, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ HSV, LABS, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ HSV, CMYK, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ HSV, scRGB, { vips_HSV2sRGB, vips_sRGB2scRGB, NULL } },
{ HSV, sRGB, { vips_HSV2sRGB, NULL } },
{ HSV, HSV, { vips_cast_uchar, NULL } },
{ HSV, BW, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2BW, NULL } },
{ HSV, LABS, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ HSV, RGB16, { vips_HSV2sRGB, vips_sRGB2RGB16, NULL } },
{ HSV, GREY16, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2BW16, NULL } },
{ HSV, YXY, { vips_HSV2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },

{ BW, XYZ, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, NULL } },
{ BW, LAB, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, NULL } },
{ BW, LABQ, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ BW, LCH, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ BW, CMC, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ BW, LABS, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ BW, CMYK, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ BW, scRGB, { vips_BW2sRGB, vips_sRGB2scRGB, NULL } },
{ BW, sRGB, { vips_BW2sRGB, NULL } },
{ BW, HSV, { vips_BW2sRGB, vips_sRGB2HSV, NULL } },
{ BW, BW, { vips_cast_uchar, NULL } },
{ BW, RGB16, { vips_BW2sRGB, vips_sRGB2RGB16, NULL } },
{ BW, GREY16, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2BW16, NULL } },
{ BW, YXY, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },

{ RGB16, XYZ, { vips_sRGB2scRGB, vips_scRGB2XYZ, NULL } },
{ RGB16, LAB, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, NULL } },
{ RGB16, LABQ, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ RGB16, LCH, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ RGB16, CMC, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ RGB16, LABS, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ RGB16, CMYK, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ RGB16, scRGB, { vips_sRGB2scRGB, NULL } },
{ RGB16, sRGB, { vips_RGB162sRGB, NULL } },
{ RGB16, HSV, { vips_RGB162sRGB, vips_sRGB2HSV, NULL } },
{ RGB16, BW, { vips_sRGB2scRGB, vips_scRGB2BW, NULL } },
{ RGB16, LABS, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ RGB16, RGB16, { vips_cast_ushort, NULL } },
{ RGB16, GREY16, { vips_sRGB2scRGB, vips_scRGB2BW16, NULL } },
{ RGB16, YXY, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },

Expand All @@ -378,29 +405,16 @@ static VipsColourRoute vips_colour_routes[] = {
{ GREY16, LABQ, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ GREY16, LCH, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ GREY16, CMC, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ GREY16, LABS, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ GREY16, CMYK, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ GREY16, scRGB, { vips_GREY162RGB16, vips_sRGB2scRGB, NULL } },
{ GREY16, sRGB, { vips_GREY162RGB16, vips_RGB162sRGB, NULL } },
{ GREY16, HSV, { vips_GREY162RGB16, vips_RGB162sRGB, vips_sRGB2HSV, NULL } },
{ GREY16, BW, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2BW, NULL } },
{ GREY16, LABS, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ GREY16, RGB16, { vips_GREY162RGB16, NULL } },
{ GREY16, GREY16, { vips_cast_ushort, NULL } },
{ GREY16, YXY, { vips_GREY162RGB16, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },

{ BW, XYZ, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, NULL } },
{ BW, LAB, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, NULL } },
{ BW, LABQ, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
{ BW, LCH, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } },
{ BW, CMC, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } },
{ BW, CMYK, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2CMYK, NULL } },
{ BW, scRGB, { vips_BW2sRGB, vips_sRGB2scRGB, NULL } },
{ BW, sRGB, { vips_BW2sRGB, NULL } },
{ BW, HSV, { vips_BW2sRGB, vips_sRGB2HSV, NULL } },
{ BW, LABS, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } },
{ BW, RGB16, { vips_BW2sRGB, vips_sRGB2RGB16, NULL } },
{ BW, GREY16, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2BW16, NULL } },
{ BW, YXY, { vips_BW2sRGB, vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } },

{ YXY, XYZ, { vips_Yxy2XYZ, NULL } },
{ YXY, LAB, { vips_Yxy2XYZ, vips_XYZ2Lab, NULL } },
{ YXY, LABQ, { vips_Yxy2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } },
Expand All @@ -413,7 +427,8 @@ static VipsColourRoute vips_colour_routes[] = {
{ YXY, HSV, { vips_Yxy2XYZ, vips_XYZ2scRGB, vips_scRGB2sRGB, vips_sRGB2HSV, NULL } },
{ YXY, BW, { vips_Yxy2XYZ, vips_XYZ2scRGB, vips_scRGB2BW, NULL } },
{ YXY, RGB16, { vips_Yxy2XYZ, vips_XYZ2scRGB, vips_scRGB2RGB16, NULL } },
{ YXY, GREY16, { vips_Yxy2XYZ, vips_XYZ2scRGB, vips_scRGB2BW16, NULL } }
{ YXY, GREY16, { vips_Yxy2XYZ, vips_XYZ2scRGB, vips_scRGB2BW16, NULL } },
{ YXY, YXY, { vips_cast_float, NULL } },

};

Expand Down Expand Up @@ -468,8 +483,7 @@ vips_colourspace_build(VipsObject *object)

int i, j;
VipsImage *x;
VipsImage **t = (VipsImage **)
vips_object_local_array(object, 1);
VipsImage **t = (VipsImage **) vips_object_local_array(object, 1);
VipsImage **pipe = (VipsImage **)
vips_object_local_array(object, MAX_STEPS);

Expand Down Expand Up @@ -502,25 +516,14 @@ vips_colourspace_build(VipsObject *object)
if (interpretation == VIPS_INTERPRETATION_RGB)
interpretation = VIPS_INTERPRETATION_sRGB;

/* No conversion necessary.
*/
if (interpretation == colourspace->space) {
g_object_set(colourspace, "out", vips_image_new(), NULL);

return vips_image_write(colourspace->in, colourspace->out);
}

for (i = 0; i < VIPS_NUMBER(vips_colour_routes); i++)
if (vips_colour_routes[i].from == interpretation &&
vips_colour_routes[i].to == colourspace->space)
break;
if (i == VIPS_NUMBER(vips_colour_routes)) {
vips_error("vips_colourspace",
_("no known route from '%s' to '%s'"),
vips_enum_nick(VIPS_TYPE_INTERPRETATION,
interpretation),
vips_enum_nick(VIPS_TYPE_INTERPRETATION,
colourspace->space));
vips_error("vips_colourspace", _("no known route from '%s' to '%s'"),
vips_enum_nick(VIPS_TYPE_INTERPRETATION, interpretation),
vips_enum_nick(VIPS_TYPE_INTERPRETATION, colourspace->space));
return -1;
}

Expand Down
17 changes: 10 additions & 7 deletions libvips/foreign/foreign.c
Original file line number Diff line number Diff line change
Expand Up @@ -1375,13 +1375,16 @@ vips_foreign_save_new_from_string(const char *string)

/* Apply a set of saveable flags.
*
* - unpack rad and labq
* - if the saver supports mono and we have a mono-looking image, we are done
* - if the saver supports CMYK and we have a CMYK-looking image, we are done
* - if this is a CMYK-looking image, import to XYZ
* - go to rgb
* - if the saver supports rgb, we are done
* - if the saver supports rgb, go to rgb
* - if the saver supports cmyk, go to cmyk
* - if the saver supports mono, go to mono
*
* we output 16 bit images if the source is 16 bits ... a later stage
* uses the format[] table to cut this down to the size the saver wants
*/
static int
vips_foreign_apply_saveable(VipsImage *in, VipsImage **ready,
Expand All @@ -1404,7 +1407,7 @@ vips_foreign_apply_saveable(VipsImage *in, VipsImage **ready,
return 0;
}

/* If this is an VIPS_CODING_LABQ, we can go straight to RGB.
/* If this is VIPS_CODING_LABQ, we can go straight to RGB.
*/
if (in->Coding == VIPS_CODING_LABQ) {
if (vips_LabQ2sRGB(in, &out, NULL)) {
Expand All @@ -1415,7 +1418,7 @@ vips_foreign_apply_saveable(VipsImage *in, VipsImage **ready,
in = out;
}

/* If this is an VIPS_CODING_RAD, we unpack to float. This could be
/* If this is VIPS_CODING_RAD, we unpack to float. This could be
* scRGB or XYZ.
*/
if (in->Coding == VIPS_CODING_RAD) {
Expand Down Expand Up @@ -1478,7 +1481,7 @@ vips_foreign_apply_saveable(VipsImage *in, VipsImage **ready,
return 0;
}

/* If the saver supports CMYK, go to RGB, or RGB16 if this is a ushort
/* If the saver supports CMYK, go to CMYK, 16 bits if this is a ushort
* source.
*/
if (saveable & VIPS_FOREIGN_SAVEABLE_CMYK) {
Expand Down Expand Up @@ -1639,10 +1642,10 @@ vips__foreign_convert_saveable(VipsImage *in, VipsImage **ready,
}
}

/* Convert to the format the saver likes, based on the original format.
/* Convert to the format the saver likes.
*/
if (in->Coding == VIPS_CODING_NONE) {
if (vips_cast(in, &out, format[original_format], NULL)) {
if (vips_cast(in, &out, format[in->BandFmt], NULL)) {
g_object_unref(in);
return -1;
}
Expand Down
34 changes: 21 additions & 13 deletions libvips/foreign/pngsave.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/* save to png
*
* 2/12/11
Expand Down Expand Up @@ -102,6 +102,7 @@
VipsForeignSavePng *png = (VipsForeignSavePng *) object;

VipsImage *in;
VipsImage *x;

if (VIPS_OBJECT_CLASS(vips_foreign_save_png_parent_class)->build(object))
return -1;
Expand All @@ -124,18 +125,27 @@
if (vips_object_argument_isset(object, "colours"))
png->bitdepth = ceil(log2(png->colours));

/* Cast in down to 8 bit if we can.
/* The bitdepth param can change the interpretation.
*/
if (png->bitdepth <= 8) {
VipsImage *x;

if (vips_cast(in, &x, VIPS_FORMAT_UCHAR, NULL)) {
g_object_unref(in);
return -1;
}
VipsInterpretation interpretation;
if (in->Bands > 2) {
if (png->bitdepth > 8)
interpretation = VIPS_INTERPRETATION_RGB16;
else
interpretation = VIPS_INTERPRETATION_sRGB;
}
else {
if (png->bitdepth > 8)
interpretation = VIPS_INTERPRETATION_GREY16;
else
interpretation = VIPS_INTERPRETATION_B_W;
}
if (vips_colourspace(in, &x, interpretation, NULL)) {
g_object_unref(in);
in = x;
return -1;
}
g_object_unref(in);
in = x;

/* If this is a RGB or RGBA image and a low bit depth has been
* requested, enable palettization.
Expand Down Expand Up @@ -358,10 +368,8 @@
if (!(png->target = vips_target_new_to_file(file->filename)))
return -1;

if (VIPS_OBJECT_CLASS(vips_foreign_save_png_file_parent_class)->build(object))
return -1;

return 0;
return VIPS_OBJECT_CLASS(vips_foreign_save_png_file_parent_class)->
build(object);
}

static void
Expand Down
Loading
Loading