2 docCopyright("Steve Dekorte", 2002)
3 docLicense("BSD revised")
19 #include "TIFFImage.h"
23 typedef void (*TIFFErrorHandler)(const char* module, const char* fmt, va_list ap);
24 TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler handler);
27 Image
*Image_new(void)
29 Image
*self
= (Image
*)calloc(1, sizeof(Image
));
30 Image_path_(self
, "");
31 Image_fileType_(self
, "");
32 self
->byteArray
= UArray_new();
34 self
->componentCount
= 4;
35 self
->encodingQuality
= 1.0;
39 Image
*Image_newWithPath_(char *path
)
41 Image
*self
= Image_new();
42 Image_path_(self
, path
);
47 Image
*Image_copyWithUArray_(Image
*self
, UArray
*ba
)
49 Image
*image
= Image_new();
51 Image_setExternalUArray_(image
, ba
);
52 Image_path_(image
, self
->path
);
53 Image_error_(image
, self
->error
);
55 image
->width
= self
->width
;
56 image
->height
= self
->height
;
57 image
->componentCount
= self
->componentCount
;
59 image
->encodingQuality
= self
->encodingQuality
;
60 image
->decodingWidthHint
= self
->decodingWidthHint
;
61 image
->decodingHeightHint
= self
->decodingHeightHint
;
66 void Image_free(Image
*self
)
70 UArray_free(self
->byteArray
);
84 UArray
*Image_byteArray(Image
*self
)
86 return self
->byteArray
;
89 void Image_copyUArray_(Image
*self
, UArray
*ba
) /* private */
91 UArray_copy_(self
->byteArray
, ba
);
94 void Image_setExternalUArray_(Image
*self
, UArray
*ba
)
96 if (self
->ownsUArray
) UArray_free(self
->byteArray
);
101 void Image_getFileType(Image
*self
) /* private */
103 char *ext
= strrchr(self
->path
, '.');
105 if (!ext
) { Image_fileType_(self
, ""); return; }
108 Image_fileType_(self
, ext
);
111 while (*e
) { *e
= tolower(*e
); e
++; }
112 if (strcmp(self
->fileType
, "jpeg")==0) Image_fileType_(self
, "jpg");
115 void Image_path_(Image
*self
, const char *path
)
117 self
->path
= strcpy((char *)realloc(self
->path
, strlen(path
)+1), path
);
118 Image_getFileType(self
);
121 char *Image_path(Image
*self
)
126 void Image_fileType_(Image
*self
, const char *fileType
)
128 self
->fileType
= strcpy((char *)realloc(self
->fileType
, strlen(fileType
)+1), fileType
);
131 char *Image_fileType(Image
*self
) { return self
->fileType
; }
133 void Image_error_(Image
*self
, const char *error
)
135 if (error
&& strlen(error
))
137 /*printf("Image_error_(%s)\n", error);*/
138 self
->error
= strcpy((char *)realloc(self
->error
, strlen(error
)+1), error
);
142 if (self
->error
) free(self
->error
);
147 char *Image_error(Image
*self
) { return self
->error
; }
150 void Image_setData_width_height_componentCount_(Image
*self
, UArray
*ba
, int width
, int height
, int componentCount
)
152 int size
= width
* height
* componentCount
;
154 if (size
!= UArray_size(ba
))
156 printf("Image_setData_width_height_componentCount_() error - %i x %i x %i = %i, but buffer is %i\n",
157 width
, height
, componentCount
, size
, (int)UArray_size(ba
));
161 Image_copyUArray_(self
, ba
);
163 self
->height
= height
;
164 self
->componentCount
= componentCount
;
167 void Image_load(Image
*self
)
169 if (strcmp(self
->fileType
, "png")==0)
171 PNGImage
*image
= PNGImage_new();
172 PNGImage_setExternalUArray_(image
, self
->byteArray
);
173 PNGImage_path_(image
, self
->path
);
174 PNGImage_load(image
);
175 Image_error_(self
, PNGImage_error(image
));
176 self
->width
= PNGImage_width(image
);
177 self
->height
= PNGImage_height(image
);
178 self
->componentCount
= PNGImage_components(image
);
179 PNGImage_free(image
);
181 else if (strcmp(self
->fileType
, "jpg")==0)
183 JPGImage
*image
= JPGImage_new();
184 JPGImage_setExternalUArray_(image
, self
->byteArray
);
185 JPGImage_path_(image
, self
->path
);
186 JPGImage_decodingWidthHint_(image
, self
->decodingWidthHint
);
187 JPGImage_decodingHeightHint_(image
, self
->decodingHeightHint
);
188 JPGImage_load(image
);
189 Image_error_(self
, JPGImage_error(image
));
190 self
->width
= JPGImage_width(image
);
191 self
->height
= JPGImage_height(image
);
192 self
->componentCount
= JPGImage_components(image
);
193 JPGImage_free(image
);
195 else if (strcmp(self
->fileType
, "tif")==0 || strcmp(self
->fileType
, "tiff")==0)
197 TIFFImage
*image
= TIFFImage_new();
198 TIFFImage_setExternalUArray_(image
, self
->byteArray
);
199 TIFFImage_path_(image
, self
->path
);
200 TIFFImage_load(image
);
201 Image_error_(self
, TIFFImage_error(image
));
202 self
->width
= TIFFImage_width(image
);
203 self
->height
= TIFFImage_height(image
);
204 self
->componentCount
= TIFFImage_components(image
);
205 TIFFImage_free(image
);
209 Image_error_(self
, "unknown file type");
212 if (UArray_size(self
->byteArray
) == 0)
214 Image_error_(self
, "error reading file");
218 void Image_save(Image
*self
)
222 if (strcmp(self
->fileType
, "png")==0)
224 PNGImage
*image
= PNGImage_new();
225 PNGImage_setExternalUArray_(image
, self
->byteArray
);
226 PNGImage_path_(image
, self
->path
);
227 PNGImage_width_(image
, self
->width
);
228 PNGImage_height_(image
, self
->height
);
229 PNGImage_components_(image
, Image_componentCount(self
));
230 PNGImage_save(image
);
231 Image_error_(self
, PNGImage_error(image
));
232 PNGImage_free(image
);
234 else if (strcmp(self
->fileType
, "jpg")==0)
236 JPGImage
*image
= JPGImage_new();
237 JPGImage_setExternalUArray_(image
, self
->byteArray
);
238 JPGImage_path_(image
, self
->path
);
239 JPGImage_quality_(image
, self
->encodingQuality
);
240 JPGImage_width_(image
, self
->width
);
241 JPGImage_height_(image
, self
->height
);
242 /* TODO - convert image to RGB first */
243 if (Image_componentCount(self
) != 3)
245 Image_error_(self
, "can only save RGB images to JPEG");
248 JPGImage_components_(image
, Image_componentCount(self
));
249 JPGImage_save(image
);
250 Image_error_(self
, JPGImage_error(image
));
251 JPGImage_free(image
);
253 else if (strcmp(self
->fileType
, "tiff")==0 || strcmp(self
->fileType
, "tif")==0)
255 TIFFImage
*image
= TIFFImage_new();
256 TIFFImage_setExternalUArray_(image
, self
->byteArray
);
257 TIFFImage_path_(image
, self
->path
);
258 TIFFImage_width_(image
, self
->width
);
259 TIFFImage_height_(image
, self
->height
);
260 TIFFImage_components_(image
, Image_componentCount(self
));
261 TIFFImage_save(image
);
262 Image_error_(self
, TIFFImage_error(image
));
263 TIFFImage_free(image
);
267 Image_error_(self
, "unknown file type");
273 int Image_width(Image
*self
)
278 int Image_height(Image
*self
)
283 int Image_componentCount(Image
*self
)
285 return self
->componentCount
;
288 int Image_sizeInBytes(Image
*self
)
290 return self
->height
* self
->width
* self
->componentCount
;
293 uint8_t *Image_data(Image
*self
)
295 return (uint8_t *)UArray_bytes(self
->byteArray
);
298 void Image_data_length_(Image
*self
, unsigned char *data
, size_t length
)
300 UArray_setData_type_size_copy_(self
->byteArray
, data
, CTYPE_uint8_t
, length
, 1);
304 void Image_flipY(Image
*self
)
308 int h
= self
->height
;
309 int componentCount
= self
->componentCount
;
310 uint8_t *bytes
= UArray_mutableBytes(self
->byteArray
);
311 int bytesPerLine
= componentCount
* w
;
312 unsigned char *buf
= malloc(bytesPerLine
);
314 for (y
= 0; y
< self
->height
/2; y
++)
316 uint8_t *a
= bytes
+ componentCount
* (y
* w
);
317 uint8_t *b
= bytes
+ componentCount
* ((h
-1-y
) * w
);
319 memcpy(buf
, a
, bytesPerLine
);
320 memcpy(a
, b
, bytesPerLine
);
321 memcpy(b
, buf
, bytesPerLine
);
326 void Image_resizeTo(Image
*self
, int w
, int h
, Image
*outImage
)
328 int componentCount
= self
->componentCount
;
330 int inStride
= self
->width
* componentCount
;
331 uint8_t *inPtr
= Image_data(self
);
333 int outStride
= w
* componentCount
;
334 UArray
*outUArray
= UArray_new();
335 UArray_setSize_(outUArray
, h
* outStride
);
336 uint8_t *outPtr
= (uint8_t *)UArray_bytes(outUArray
);
339 for (y
=0; y
< self
->height
; y
++, inPtr
+= inStride
, outPtr
+= outStride
)
340 memcpy(outPtr
, inPtr
, inStride
);
342 Image_setData_width_height_componentCount_(outImage
, outUArray
, w
, h
, componentCount
);
345 inline unsigned char *Image_pixelAt(Image
*self
, int x
, int y
)
348 int spp
= Image_componentCount(self
);
350 int h
= self
->height
;
351 uint8_t *p
= (uint8_t *)UArray_bytes(self
->byteArray
);
353 if (x
< 0) { x
= 0; } else if (x
> w
- 1) { x
= w
- 1; }
354 if (y
< 0) { y
= 0; } else if (y
> h
- 1) { y
= h
- 1; }
355 return p
+ (((x
+ (y
* w
)) * (spp
* bps
)) / 8);
358 void Image_crop(Image
*self
, int cx
, int cy
, int w
, int h
)
360 int pixelSize
= Image_componentCount(self
);
363 if (cx
> self
->width
) { Image_error_(self
, "crop x > width"); return; }
364 if (cy
> self
->height
) { Image_error_(self
, "crop y > height"); return; }
365 if (cx
+w
> self
->width
) { w
= self
->width
- cx
; }
366 if (cy
+h
> self
->height
) { h
= self
->height
- cy
; }
368 for (x
= 0; x
< w
; x
++)
370 for (y
= 0; y
< h
; y
++)
372 unsigned char *ip
= Image_pixelAt(self
, cx
+x
, cy
+y
);
373 unsigned char *op
= Image_pixelAt(self
, x
, y
);
374 memcpy(op
, ip
, pixelSize
);
377 UArray_setSize_(self
->byteArray
, w
*h
*pixelSize
);
383 /* --- extras --------------------------------------------------------- */
385 void Image_encodingQuality_(Image
*self
, float q
)
387 self
->encodingQuality
= q
;
390 float Image_encodingQuality(Image
*self
)
392 return self
->encodingQuality
;
395 void Image_decodingWidthHint_(Image
*self
, int v
)
397 self
->decodingWidthHint
= v
;
400 int Image_decodingWidthHint(Image
*self
)
402 return self
->decodingWidthHint
;
405 void Image_decodingHeightHint_(Image
*self
, int v
)
407 self
->decodingHeightHint
= v
;
410 int Image_decodingHeightHint(Image
*self
)
412 return self
->decodingHeightHint
;