Port variable image resolution support from libgd 2.1.0

The PHP binding for this feature will be submitted as a separate PR.
This commit is contained in:
Christoph M. Becker 2016-09-19 19:00:58 +02:00
parent 77ba2483d9
commit 932c20fb8d
5 changed files with 59 additions and 2 deletions

View file

@ -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)
{

View file

@ -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. */

View file

@ -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. */

View file

@ -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]
*/

View file

@ -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 */