From 932c20fb8d7d1b94c1615c8f0cb958f67bc24c53 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 19 Sep 2016 19:00:58 +0200 Subject: [PATCH] Port variable image resolution support from libgd 2.1.0 The PHP binding for this feature will be submitted as a separate PR. --- ext/gd/libgd/gd.c | 10 ++++++++++ ext/gd/libgd/gd.h | 5 +++++ ext/gd/libgd/gd_jpeg.c | 17 +++++++++++++++++ ext/gd/libgd/gd_png.c | 24 ++++++++++++++++++++++-- ext/gd/libgd/gdhelpers.h | 5 +++++ 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index 7a0af8de92..dd38a11cb9 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -170,6 +170,8 @@ gdImagePtr gdImageCreate (int sx, int sy) im->cy1 = 0; im->cx2 = im->sx - 1; im->cy2 = im->sy - 1; + im->res_x = GD_RESOLUTION; + im->res_y = GD_RESOLUTION; im->interpolation = NULL; im->interpolation_id = GD_BILINEAR_FIXED; return im; @@ -225,6 +227,8 @@ gdImagePtr gdImageCreateTrueColor (int sx, int sy) im->cy1 = 0; im->cx2 = im->sx - 1; im->cy2 = im->sy - 1; + im->res_x = GD_RESOLUTION; + im->res_y = GD_RESOLUTION; im->interpolation = NULL; im->interpolation_id = GD_BILINEAR_FIXED; return im; @@ -3056,6 +3060,12 @@ void gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P) *y2P = im->cy2; } +void gdImageSetResolution(gdImagePtr im, const unsigned int res_x, const unsigned int res_y) +{ + if (res_x > 0) im->res_x = res_x; + if (res_y > 0) im->res_y = res_y; +} + /* convert a palette image to true color */ int gdImagePaletteToTrueColor(gdImagePtr src) { diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h index 2eb4fd8e1c..251dbfb0be 100644 --- a/ext/gd/libgd/gd.h +++ b/ext/gd/libgd/gd.h @@ -253,6 +253,8 @@ typedef struct gdImageStruct { int cy1; int cx2; int cy2; + unsigned int res_x; + unsigned int res_y; gdInterpolationMethod interpolation_id; interpolation_method interpolation; } gdImage; @@ -433,6 +435,7 @@ void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color); void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color); void gdImageSetClip(gdImagePtr im, int x1, int y1, int x2, int y2); void gdImageGetClip(gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P); +void gdImageSetResolution(gdImagePtr im, const unsigned int res_x, const unsigned int res_y); void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color); void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color); void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color); @@ -746,6 +749,8 @@ int gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode); of image is also your responsibility. */ #define gdImagePalettePixel(im, x, y) (im)->pixels[(y)][(x)] #define gdImageTrueColorPixel(im, x, y) (im)->tpixels[(y)][(x)] +#define gdImageResolutionX(im) (im)->res_x +#define gdImageResolutionY(im) (im)->res_y /* I/O Support routines. */ diff --git a/ext/gd/libgd/gd_jpeg.c b/ext/gd/libgd/gd_jpeg.c index f239ef8acd..900b13504c 100644 --- a/ext/gd/libgd/gd_jpeg.c +++ b/ext/gd/libgd/gd_jpeg.c @@ -195,6 +195,11 @@ void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality) cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ jpeg_set_defaults (&cinfo); + + cinfo.density_unit = 1; + cinfo.X_density = im->res_x; + cinfo.Y_density = im->res_y; + if (quality >= 0) { jpeg_set_quality (&cinfo, quality, TRUE); } @@ -381,6 +386,18 @@ gdImagePtr gdImageCreateFromJpegCtxEx (gdIOCtx * infile, int ignore_warning) goto error; } + /* check if the resolution is specified */ + switch (cinfo.density_unit) { + case 1: + im->res_x = cinfo.X_density; + im->res_y = cinfo.Y_density; + break; + case 2: + im->res_x = DPCM2DPI(cinfo.X_density); + im->res_y = DPCM2DPI(cinfo.Y_density); + break; + } + /* 2.0.22: very basic support for reading CMYK colorspace files. Nice for * thumbnails but there's no support for fussy adjustment of the * assumed properties of inks and paper. */ diff --git a/ext/gd/libgd/gd_png.c b/ext/gd/libgd/gd_png.c index a012cc63b8..b521e45da4 100644 --- a/ext/gd/libgd/gd_png.c +++ b/ext/gd/libgd/gd_png.c @@ -120,8 +120,8 @@ gdImagePtr gdImageCreateFromPngCtx (gdIOCtx * infile) #endif png_structp png_ptr; png_infop info_ptr; - png_uint_32 width, height, rowbytes, w, h; - int bit_depth, color_type, interlace_type; + png_uint_32 width, height, rowbytes, w, h, res_x, res_y; + int bit_depth, color_type, interlace_type, unit_type; int num_palette, num_trans; png_colorp palette; png_color_16p trans_gray_rgb; @@ -226,6 +226,20 @@ gdImagePtr gdImageCreateFromPngCtx (gdIOCtx * infile) } #endif +#ifdef PNG_pHYs_SUPPORTED + /* check if the resolution is specified */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { + if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type)) { + switch (unit_type) { + case PNG_RESOLUTION_METER: + im->res_x = DPM2DPI(res_x); + im->res_y = DPM2DPI(res_y); + break; + } + } + } +#endif + switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); @@ -526,6 +540,12 @@ void gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level, int basefilte png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, basefilter); } +#ifdef PNG_pHYs_SUPPORTED + /* 2.1.0: specify the resolution */ + png_set_pHYs(png_ptr, info_ptr, DPI2DPM(im->res_x), DPI2DPM(im->res_y), + PNG_RESOLUTION_METER); +#endif + /* can set this to a smaller value without compromising compression if all * image data is 16K or less; will save some decoder memory [min == 8] */ diff --git a/ext/gd/libgd/gdhelpers.h b/ext/gd/libgd/gdhelpers.h index 768fde93b8..afb45f0e67 100644 --- a/ext/gd/libgd/gdhelpers.h +++ b/ext/gd/libgd/gdhelpers.h @@ -42,5 +42,10 @@ int overflow2(int a, int b); #define gdMutexUnlock(x) #endif +#define DPCM2DPI(dpcm) (unsigned int)((dpcm)*2.54 + 0.5) +#define DPM2DPI(dpm) (unsigned int)((dpm)*0.0254 + 0.5) +#define DPI2DPCM(dpi) (unsigned int)((dpi)/2.54 + 0.5) +#define DPI2DPM(dpi) (unsigned int)((dpi)/0.0254 + 0.5) + #endif /* GDHELPERS_H */ -- 2.40.0