LibGd 2.4.0-dev
GD Graphics library
Loading...
Searching...
No Matches
gd_intern.h
1/* Internal header for random common utility functions. */
2
3#ifndef GD_INTERN_H
4#define GD_INTERN_H
5
6#include "gd.h"
7
8#include <limits.h>
9#include <string.h>
10
11#ifndef MAXPATHLEN
12#ifdef PATH_MAX
13#define MAXPATHLEN PATH_MAX
14#elif defined(MAX_PATH)
15#define MAXPATHLEN MAX_PATH
16#else
17#if defined(__GNU__)
18#define MAXPATHLEN 4096
19#else
20#define MAXPATHLEN 256 /* Should be safe for any weird systems that do not define it */
21#endif
22#endif
23#endif
24
25#ifdef HAVE_STDINT_H
26#include <stdint.h>
27#else
28#if defined(HAVE_INTTYPES_H)
29#include <inttypes.h>
30#else
31#include "msinttypes/inttypes.h"
32#endif
33#endif
34
35#ifdef _MSC_VER
36#define ssize_t SSIZE_T
37#define MAXSIZE_T ((SIZE_T) ~((SIZE_T)0))
38#define MAXSSIZE_T ((SSIZE_T)(MAXSIZE_T >> 1))
39#define MINSSIZE_T ((SSIZE_T)~MAXSSIZE_T)
40#define SSIZE_MAX MAXSSIZE_T
41#endif
42#if defined(_MSC_VER)
43#define UNUSED_PARAM(x) x
44#elif defined(__GNUC__) || defined(__clang__)
45#define UNUSED_PARAM(x) x __attribute__((unused))
46#else
47#define UNUSED_PARAM(x) x
48#endif
49#ifndef MIN
50#define MIN(a, b) ((a) < (b) ? (a) : (b))
51#endif
52#define MIN3(a, b, c) ((a) < (b) ? (MIN(a, c)) : (MIN(b, c)))
53#ifndef MAX
54#define MAX(a, b) ((a) < (b) ? (b) : (a))
55#endif
56#define MAX3(a, b, c) ((a) < (b) ? (MAX(b, c)) : (MAX(a, c)))
57#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
58/* 2.0.12: this now checks the clipping rectangle */
59#define gdImageBoundsSafeMacro(im, x, y) \
60 (!((((y) < (im)->cy1) || ((y) > (im)->cy2)) || (((x) < (im)->cx1) || ((x) > (im)->cx2))))
61
62#ifdef _MSC_VER
63#define gd_strcasecmp _stricmp
64#else
65#define gd_strcasecmp strcasecmp
66#endif
67
68typedef enum {
69 HORIZONTAL,
70 VERTICAL,
71} gdAxis;
72
73/* Convert a double to an unsigned char, rounding to the nearest
74 * integer and clamping the result between 0 and max. The absolute
75 * value of clr must be less than the maximum value of an unsigned
76 * short. */
77static inline unsigned char uchar_clamp(double clr, unsigned char max)
78{
79 unsigned short result;
80
81 // assert(fabs(clr) <= SHRT_MAX);
82
83 /* Casting a negative float to an unsigned short is undefined.
84 * However, casting a float to a signed truncates toward zero and
85 * casting a negative signed value to an unsigned of the same size
86 * results in a bit-identical value (assuming twos-complement
87 * arithmetic). This is what we want: all legal negative values
88 * for clr will be greater than 255. */
89
90 /* Convert and clamp. */
91 result = (unsigned short)(short)(clr + 0.5);
92 if (result > max) {
93 result = (clr < 0) ? 0 : max;
94 } /* if */
95
96 return result;
97} /* uchar_clamp*/
98
99/* Internal prototypes: */
100
101/* gd_metadata.c */
102static inline int gdMetadataGetExifTiff(const unsigned char *data, size_t size,
103 const unsigned char **tiff, size_t *tiff_size)
104{
105 static const unsigned char exif_signature[] = {'E', 'x', 'i', 'f', '\0', '\0'};
106
107 if (tiff == NULL || tiff_size == NULL || (data == NULL && size != 0)) {
108 return GD_META_ERR_INVALID;
109 }
110 if (size >= sizeof(exif_signature) &&
111 memcmp(data, exif_signature, sizeof(exif_signature)) == 0) {
112 data += sizeof(exif_signature);
113 size -= sizeof(exif_signature);
114 }
115 if (size < 8 || data == NULL ||
116 !((data[0] == 'I' && data[1] == 'I' && data[2] == 42 && data[3] == 0) ||
117 (data[0] == 'M' && data[1] == 'M' && data[2] == 0 && data[3] == 42))) {
118 return GD_META_ERR_PARSE;
119 }
120 *tiff = data;
121 *tiff_size = size;
122 return GD_META_OK;
123}
124
125/* gd_jpeg.c */
126
127/* gd_rotate.c */
128gdImagePtr gdImageRotate90(gdImagePtr src, int ignoretransparent);
129gdImagePtr gdImageRotate180(gdImagePtr src, int ignoretransparent);
130gdImagePtr gdImageRotate270(gdImagePtr src, int ignoretransparent);
131
138static inline int gdImageClipCopy(gdImagePtr dst, int *dstX, int *dstY, int *srcX, int *srcY,
139 int *w, int *h)
140{
141 int x1, y1, x2, y2;
142
143 /* overflow-safe dst rect: [dstX, dstY] to [dstX+w, dstY+h] */
144 x1 = *dstX;
145 y1 = *dstY;
146
147 /* check w/h are positive */
148 if (*w <= 0 || *h <= 0) {
149 return 0;
150 }
151
152 /* overflow check for dstX+w and dstY+h */
153 if (*dstX > 0 && *w > INT_MAX - *dstX) {
154 x2 = INT_MAX;
155 } else {
156 x2 = *dstX + *w;
157 }
158 if (*dstY > 0 && *h > INT_MAX - *dstY) {
159 y2 = INT_MAX;
160 } else {
161 y2 = *dstY + *h;
162 }
163
164 /* entirely outside dst? */
165 if (x1 >= gdImageSX(dst) || y1 >= gdImageSY(dst) || x2 <= 0 || y2 <= 0) {
166 return 0;
167 }
168
169 /* clip left */
170 if (x1 < 0) {
171 *srcX -= x1; /* advance srcX by the same amount */
172 *w += x1; /* reduce width */
173 *dstX = 0;
174 }
175
176 /* clip top */
177 if (y1 < 0) {
178 *srcY -= y1;
179 *h += y1;
180 *dstY = 0;
181 }
182
183 /* clip right */
184 if (*dstX + *w > gdImageSX(dst)) {
185 *w = gdImageSX(dst) - *dstX;
186 }
187
188 /* clip bottom */
189 if (*dstY + *h > gdImageSY(dst)) {
190 *h = gdImageSY(dst) - *dstY;
191 }
192
193 /* sanity: clipping may have reduced w/h to zero */
194 if (*w <= 0 || *h <= 0) {
195 return 0;
196 }
197
198 return 1;
199}
200static inline int gdImageClipCopyResized(gdImagePtr dst, int *dstX, int *dstY, int *dstW, int *dstH,
201 int *srcX, int *srcY, int *srcW, int *srcH)
202{
203 int orig_dstW = *dstW;
204 int orig_dstH = *dstH;
205
206 if (*dstW <= 0 || *dstH <= 0 || *srcW <= 0 || *srcH <= 0) {
207 return 0;
208 }
209 if (*dstX >= gdImageSX(dst) || *dstY >= gdImageSY(dst) || *dstX + *dstW <= 0 ||
210 *dstY + *dstH <= 0) {
211 return 0;
212 }
213
214 /* clip left — adjust srcX proportionally */
215 if (*dstX < 0) {
216 *srcX += (-*dstX) * *srcW / orig_dstW;
217 *srcW -= (-*dstX) * *srcW / orig_dstW;
218 *dstW += *dstX;
219 *dstX = 0;
220 }
221 /* clip top */
222 if (*dstY < 0) {
223 *srcY += (-*dstY) * *srcH / orig_dstH;
224 *srcH -= (-*dstY) * *srcH / orig_dstH;
225 *dstH += *dstY;
226 *dstY = 0;
227 }
228 /* clip right */
229 if (*dstX + *dstW > gdImageSX(dst)) {
230 int clip = *dstX + *dstW - gdImageSX(dst);
231 *srcW -= clip * *srcW / orig_dstW;
232 *dstW = gdImageSX(dst) - *dstX;
233 }
234 /* clip bottom */
235 if (*dstY + *dstH > gdImageSY(dst)) {
236 int clip = *dstY + *dstH - gdImageSY(dst);
237 *srcH -= clip * *srcH / orig_dstH;
238 *dstH = gdImageSY(dst) - *dstY;
239 }
240
241 if (*dstW <= 0 || *dstH <= 0)
242 return 0;
243 return 1;
244}
245#endif /* GD_INTERN_H */