1 | /* |
2 | * << Haru Free PDF Library >> -- hpdf_image.c |
3 | * |
4 | * URL: http://libharu.org |
5 | * |
6 | * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp> |
7 | * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org> |
8 | * |
9 | * Permission to use, copy, modify, distribute and sell this software |
10 | * and its documentation for any purpose is hereby granted without fee, |
11 | * provided that the above copyright notice appear in all copies and |
12 | * that both that copyright notice and this permission notice appear |
13 | * in supporting documentation. |
14 | * It is provided "as is" without express or implied warranty. |
15 | * |
16 | */ |
17 | |
18 | #include "hpdf_conf.h" |
19 | #include "hpdf_utils.h" |
20 | #include "hpdf.h" |
21 | |
22 | static const char *COL_CMYK = "DeviceCMYK" ; |
23 | static const char *COL_RGB = "DeviceRGB" ; |
24 | static const char *COL_GRAY = "DeviceGray" ; |
25 | |
26 | static HPDF_STATUS |
27 | LoadJpegHeader (HPDF_Image image, |
28 | HPDF_Stream stream); |
29 | |
30 | |
31 | /*---------------------------------------------------------------------------*/ |
32 | |
33 | static HPDF_STATUS |
34 | (HPDF_Image image, |
35 | HPDF_Stream stream) |
36 | { |
37 | HPDF_UINT16 tag; |
38 | HPDF_UINT16 height; |
39 | HPDF_UINT16 width; |
40 | HPDF_BYTE precision; |
41 | HPDF_BYTE num_components; |
42 | const char *color_space_name; |
43 | HPDF_UINT len; |
44 | HPDF_STATUS ret; |
45 | HPDF_Array array; |
46 | |
47 | HPDF_PTRACE ((" HPDF_Image_LoadJpegHeader\n" )); |
48 | |
49 | len = 2; |
50 | if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&tag, &len) != HPDF_OK) |
51 | return HPDF_Error_GetCode (stream->error); |
52 | |
53 | HPDF_UInt16Swap (&tag); |
54 | if (tag != 0xFFD8) |
55 | return HPDF_INVALID_JPEG_DATA; |
56 | |
57 | /* find SOF record */ |
58 | for (;;) { |
59 | HPDF_UINT16 size; |
60 | |
61 | len = 2; |
62 | if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&tag, &len) != HPDF_OK) |
63 | return HPDF_Error_GetCode (stream->error); |
64 | |
65 | HPDF_UInt16Swap (&tag); |
66 | |
67 | len = 2; |
68 | if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&size, &len) != HPDF_OK) |
69 | return HPDF_Error_GetCode (stream->error); |
70 | |
71 | HPDF_UInt16Swap (&size); |
72 | |
73 | HPDF_PTRACE (("tag=%04X size=%u\n" , tag, size)); |
74 | |
75 | if (tag == 0xFFC0 || tag == 0xFFC1 || |
76 | tag == 0xFFC2 || tag == 0xFFC9) { |
77 | |
78 | len = 1; |
79 | if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&precision, &len) != |
80 | HPDF_OK) |
81 | return HPDF_Error_GetCode (stream->error); |
82 | |
83 | len = 2; |
84 | if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&height, &len) != |
85 | HPDF_OK) |
86 | return HPDF_Error_GetCode (stream->error); |
87 | |
88 | HPDF_UInt16Swap (&height); |
89 | |
90 | len = 2; |
91 | if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&width, &len) != HPDF_OK) |
92 | return HPDF_Error_GetCode (stream->error); |
93 | |
94 | HPDF_UInt16Swap (&width); |
95 | |
96 | len = 1; |
97 | if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&num_components, &len) != |
98 | HPDF_OK) |
99 | return HPDF_Error_GetCode (stream->error); |
100 | |
101 | break; |
102 | } else if ((tag | 0x00FF) != 0xFFFF) |
103 | /* lost marker */ |
104 | return HPDF_SetError (image->error, HPDF_UNSUPPORTED_JPEG_FORMAT, |
105 | 0); |
106 | |
107 | if (HPDF_Stream_Seek (stream, size - 2, HPDF_SEEK_CUR) != HPDF_OK) |
108 | return HPDF_Error_GetCode (stream->error); |
109 | } |
110 | |
111 | if (HPDF_Dict_AddNumber (image, "Height" , height) != HPDF_OK) |
112 | return HPDF_Error_GetCode (stream->error); |
113 | |
114 | if (HPDF_Dict_AddNumber (image, "Width" , width) != HPDF_OK) |
115 | return HPDF_Error_GetCode (stream->error); |
116 | |
117 | /* classification of RGB and CMYK is less than perfect |
118 | * YCbCr and YCCK are classified into RGB or CMYK. |
119 | * |
120 | * It is necessary to read APP14 data to distinguish colorspace perfectly. |
121 | |
122 | */ |
123 | switch (num_components) { |
124 | case 1: |
125 | color_space_name = COL_GRAY; |
126 | break; |
127 | case 3: |
128 | color_space_name = COL_RGB; |
129 | break; |
130 | case 4: |
131 | array = HPDF_Array_New (image->mmgr); |
132 | if (!array) |
133 | return HPDF_Error_GetCode (stream->error); |
134 | |
135 | ret = HPDF_Dict_Add (image, "Decode" , array); |
136 | if (ret != HPDF_OK) |
137 | return HPDF_Error_GetCode (stream->error); |
138 | |
139 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); |
140 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); |
141 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); |
142 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); |
143 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); |
144 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); |
145 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); |
146 | ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); |
147 | |
148 | if (ret != HPDF_OK) |
149 | return HPDF_Error_GetCode (stream->error); |
150 | |
151 | color_space_name = COL_CMYK; |
152 | |
153 | break; |
154 | default: |
155 | return HPDF_SetError (image->error, HPDF_UNSUPPORTED_JPEG_FORMAT, |
156 | 0); |
157 | } |
158 | |
159 | if (HPDF_Dict_Add (image, "ColorSpace" , |
160 | HPDF_Name_New (image->mmgr, color_space_name)) != HPDF_OK) |
161 | return HPDF_Error_GetCode (stream->error); |
162 | |
163 | if (HPDF_Dict_Add (image, "BitsPerComponent" , |
164 | HPDF_Number_New (image->mmgr, precision)) != HPDF_OK) |
165 | return HPDF_Error_GetCode (stream->error); |
166 | |
167 | return HPDF_OK; |
168 | } |
169 | |
170 | HPDF_Image |
171 | HPDF_Image_LoadJpegImage (HPDF_MMgr mmgr, |
172 | HPDF_Stream jpeg_data, |
173 | HPDF_Xref xref) |
174 | { |
175 | HPDF_Dict image; |
176 | HPDF_STATUS ret = HPDF_OK; |
177 | |
178 | HPDF_PTRACE ((" HPDF_Image_LoadJpegImage\n" )); |
179 | |
180 | image = HPDF_DictStream_New (mmgr, xref); |
181 | if (!image) |
182 | return NULL; |
183 | |
184 | image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT; |
185 | |
186 | /* add requiered elements */ |
187 | image->filter = HPDF_STREAM_FILTER_DCT_DECODE; |
188 | ret += HPDF_Dict_AddName (image, "Type" , "XObject" ); |
189 | ret += HPDF_Dict_AddName (image, "Subtype" , "Image" ); |
190 | if (ret != HPDF_OK) |
191 | return NULL; |
192 | |
193 | if (LoadJpegHeader (image, jpeg_data) != HPDF_OK) |
194 | return NULL; |
195 | |
196 | if (HPDF_Stream_Seek (jpeg_data, 0, HPDF_SEEK_SET) != HPDF_OK) |
197 | return NULL; |
198 | |
199 | for (;;) { |
200 | HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ]; |
201 | HPDF_UINT len = HPDF_STREAM_BUF_SIZ; |
202 | HPDF_STATUS ret = HPDF_Stream_Read (jpeg_data, buf, |
203 | &len); |
204 | |
205 | if (ret != HPDF_OK) { |
206 | if (ret == HPDF_STREAM_EOF) { |
207 | if (len > 0) { |
208 | ret = HPDF_Stream_Write (image->stream, buf, len); |
209 | if (ret != HPDF_OK) |
210 | return NULL; |
211 | } |
212 | break; |
213 | } else |
214 | return NULL; |
215 | } |
216 | |
217 | if (HPDF_Stream_Write (image->stream, buf, len) != HPDF_OK) |
218 | return NULL; |
219 | } |
220 | |
221 | return image; |
222 | } |
223 | |
224 | HPDF_Image |
225 | HPDF_Image_LoadJpegImageFromMem (HPDF_MMgr mmgr, |
226 | const HPDF_BYTE *buf, |
227 | HPDF_UINT size, |
228 | HPDF_Xref xref) |
229 | { |
230 | HPDF_Stream jpeg_data; |
231 | HPDF_Image image; |
232 | |
233 | HPDF_PTRACE ((" HPDF_Image_LoadJpegImageFromMem\n" )); |
234 | |
235 | jpeg_data = HPDF_MemStream_New(mmgr,size); |
236 | if (!HPDF_Stream_Validate (jpeg_data)) { |
237 | HPDF_RaiseError (mmgr->error, HPDF_INVALID_STREAM, 0); |
238 | return NULL; |
239 | } |
240 | |
241 | if (HPDF_Stream_Write (jpeg_data, buf, size) != HPDF_OK) { |
242 | HPDF_Stream_Free (jpeg_data); |
243 | return NULL; |
244 | } |
245 | |
246 | image = HPDF_Image_LoadJpegImage(mmgr,jpeg_data,xref); |
247 | |
248 | /* destroy file stream */ |
249 | HPDF_Stream_Free (jpeg_data); |
250 | |
251 | return image; |
252 | } |
253 | |
254 | |
255 | HPDF_Image |
256 | HPDF_Image_LoadRawImage (HPDF_MMgr mmgr, |
257 | HPDF_Stream raw_data, |
258 | HPDF_Xref xref, |
259 | HPDF_UINT width, |
260 | HPDF_UINT height, |
261 | HPDF_ColorSpace color_space) |
262 | { |
263 | HPDF_Dict image; |
264 | HPDF_STATUS ret = HPDF_OK; |
265 | HPDF_UINT size; |
266 | |
267 | HPDF_PTRACE ((" HPDF_Image_LoadRawImage\n" )); |
268 | |
269 | if (color_space != HPDF_CS_DEVICE_GRAY && |
270 | color_space != HPDF_CS_DEVICE_RGB && |
271 | color_space != HPDF_CS_DEVICE_CMYK) { |
272 | HPDF_SetError (mmgr->error, HPDF_INVALID_COLOR_SPACE, 0); |
273 | return NULL; |
274 | } |
275 | |
276 | image = HPDF_DictStream_New (mmgr, xref); |
277 | if (!image) |
278 | return NULL; |
279 | |
280 | image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT; |
281 | ret += HPDF_Dict_AddName (image, "Type" , "XObject" ); |
282 | ret += HPDF_Dict_AddName (image, "Subtype" , "Image" ); |
283 | if (ret != HPDF_OK) |
284 | return NULL; |
285 | |
286 | if (color_space == HPDF_CS_DEVICE_GRAY) { |
287 | size = width * height; |
288 | ret = HPDF_Dict_AddName (image, "ColorSpace" , COL_GRAY); |
289 | } else if (color_space == HPDF_CS_DEVICE_CMYK) { |
290 | size = width * height * 4; |
291 | ret = HPDF_Dict_AddName (image, "ColorSpace" , COL_CMYK); |
292 | } else { |
293 | size = width * height * 3; |
294 | ret = HPDF_Dict_AddName (image, "ColorSpace" , COL_RGB); |
295 | } |
296 | |
297 | if (ret != HPDF_OK) |
298 | return NULL; |
299 | |
300 | if (HPDF_Dict_AddNumber (image, "Width" , width) != HPDF_OK) |
301 | return NULL; |
302 | |
303 | if (HPDF_Dict_AddNumber (image, "Height" , height) != HPDF_OK) |
304 | return NULL; |
305 | |
306 | if (HPDF_Dict_AddNumber (image, "BitsPerComponent" , 8) != HPDF_OK) |
307 | return NULL; |
308 | |
309 | if (HPDF_Stream_WriteToStream (raw_data, image->stream, 0, NULL) != HPDF_OK) |
310 | return NULL; |
311 | |
312 | if (image->stream->size != size) { |
313 | HPDF_SetError (image->error, HPDF_INVALID_IMAGE, 0); |
314 | return NULL; |
315 | } |
316 | |
317 | return image; |
318 | } |
319 | |
320 | |
321 | HPDF_Image |
322 | HPDF_Image_LoadRawImageFromMem (HPDF_MMgr mmgr, |
323 | const HPDF_BYTE *buf, |
324 | HPDF_Xref xref, |
325 | HPDF_UINT width, |
326 | HPDF_UINT height, |
327 | HPDF_ColorSpace color_space, |
328 | HPDF_UINT bits_per_component) |
329 | { |
330 | HPDF_Dict image; |
331 | HPDF_STATUS ret = HPDF_OK; |
332 | HPDF_UINT size=0; |
333 | |
334 | HPDF_PTRACE ((" HPDF_Image_LoadRawImageFromMem\n" )); |
335 | |
336 | if (color_space != HPDF_CS_DEVICE_GRAY && |
337 | color_space != HPDF_CS_DEVICE_RGB && |
338 | color_space != HPDF_CS_DEVICE_CMYK) { |
339 | HPDF_SetError (mmgr->error, HPDF_INVALID_COLOR_SPACE, 0); |
340 | return NULL; |
341 | } |
342 | |
343 | if (bits_per_component != 1 && bits_per_component != 2 && |
344 | bits_per_component != 4 && bits_per_component != 8) { |
345 | HPDF_SetError (mmgr->error, HPDF_INVALID_IMAGE, 0); |
346 | return NULL; |
347 | } |
348 | |
349 | image = HPDF_DictStream_New (mmgr, xref); |
350 | if (!image) |
351 | return NULL; |
352 | |
353 | image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT; |
354 | ret += HPDF_Dict_AddName (image, "Type" , "XObject" ); |
355 | ret += HPDF_Dict_AddName (image, "Subtype" , "Image" ); |
356 | if (ret != HPDF_OK) |
357 | return NULL; |
358 | |
359 | switch (color_space) { |
360 | case HPDF_CS_DEVICE_GRAY: |
361 | size = (HPDF_UINT)((HPDF_DOUBLE)width * height / (8 / bits_per_component) + 0.876); |
362 | ret = HPDF_Dict_AddName (image, "ColorSpace" , COL_GRAY); |
363 | break; |
364 | case HPDF_CS_DEVICE_RGB: |
365 | size = (HPDF_UINT)((HPDF_DOUBLE)width * height / (8 / bits_per_component) + 0.876); |
366 | size *= 3; |
367 | ret = HPDF_Dict_AddName (image, "ColorSpace" , COL_RGB); |
368 | break; |
369 | case HPDF_CS_DEVICE_CMYK: |
370 | size = (HPDF_UINT)((HPDF_DOUBLE)width * height / (8 / bits_per_component) + 0.876); |
371 | size *= 4; |
372 | ret = HPDF_Dict_AddName (image, "ColorSpace" , COL_CMYK); |
373 | break; |
374 | default:; |
375 | } |
376 | |
377 | if (ret != HPDF_OK) |
378 | return NULL; |
379 | |
380 | if (HPDF_Dict_AddNumber (image, "Width" , width) != HPDF_OK) |
381 | return NULL; |
382 | |
383 | if (HPDF_Dict_AddNumber (image, "Height" , height) != HPDF_OK) |
384 | return NULL; |
385 | |
386 | if (HPDF_Dict_AddNumber (image, "BitsPerComponent" , bits_per_component) |
387 | != HPDF_OK) |
388 | return NULL; |
389 | |
390 | if (HPDF_Stream_Write (image->stream, buf, size) != HPDF_OK) |
391 | return NULL; |
392 | |
393 | return image; |
394 | } |
395 | |
396 | |
397 | HPDF_BOOL |
398 | HPDF_Image_Validate (HPDF_Image image) |
399 | { |
400 | HPDF_Name subtype; |
401 | |
402 | HPDF_PTRACE ((" HPDF_Image_Validate\n" )); |
403 | |
404 | if (!image) |
405 | return HPDF_FALSE; |
406 | |
407 | if (image->header.obj_class != (HPDF_OSUBCLASS_XOBJECT | |
408 | HPDF_OCLASS_DICT)) { |
409 | HPDF_RaiseError (image->error, HPDF_INVALID_IMAGE, 0); |
410 | return HPDF_FALSE; |
411 | } |
412 | |
413 | subtype = HPDF_Dict_GetItem (image, "Subtype" , HPDF_OCLASS_NAME); |
414 | if (!subtype || HPDF_StrCmp (subtype->value, "Image" ) != 0) { |
415 | HPDF_RaiseError (image->error, HPDF_INVALID_IMAGE, 0); |
416 | return HPDF_FALSE; |
417 | } |
418 | |
419 | return HPDF_TRUE; |
420 | } |
421 | |
422 | |
423 | HPDF_EXPORT(HPDF_Point) |
424 | HPDF_Image_GetSize (HPDF_Image image) |
425 | { |
426 | HPDF_Number width; |
427 | HPDF_Number height; |
428 | HPDF_Point ret = {0, 0}; |
429 | |
430 | HPDF_PTRACE ((" HPDF_Image_GetSize\n" )); |
431 | |
432 | if (!HPDF_Image_Validate (image)) |
433 | return ret; |
434 | |
435 | width = HPDF_Dict_GetItem (image, "Width" , HPDF_OCLASS_NUMBER); |
436 | height = HPDF_Dict_GetItem (image, "Height" , HPDF_OCLASS_NUMBER); |
437 | |
438 | if (width && height) { |
439 | ret.x = (HPDF_REAL)width->value; |
440 | ret.y = (HPDF_REAL)height->value; |
441 | } |
442 | |
443 | return ret; |
444 | } |
445 | |
446 | HPDF_EXPORT(HPDF_STATUS) |
447 | HPDF_Image_GetSize2 (HPDF_Image image, HPDF_Point *size) |
448 | { |
449 | HPDF_Number width; |
450 | HPDF_Number height; |
451 | size->x = 0; |
452 | size->y = 0; |
453 | |
454 | HPDF_PTRACE ((" HPDF_Image_GetSize\n" )); |
455 | |
456 | if (!HPDF_Image_Validate (image)) |
457 | return HPDF_INVALID_IMAGE; |
458 | |
459 | width = HPDF_Dict_GetItem (image, "Width" , HPDF_OCLASS_NUMBER); |
460 | height = HPDF_Dict_GetItem (image, "Height" , HPDF_OCLASS_NUMBER); |
461 | |
462 | if (width && height) { |
463 | size->x = (HPDF_REAL)width->value; |
464 | size->y = (HPDF_REAL)height->value; |
465 | } |
466 | |
467 | return HPDF_OK; |
468 | } |
469 | |
470 | HPDF_EXPORT(HPDF_UINT) |
471 | HPDF_Image_GetBitsPerComponent (HPDF_Image image) |
472 | { |
473 | HPDF_Number n; |
474 | |
475 | HPDF_PTRACE ((" HPDF_Image_GetBitsPerComponent\n" )); |
476 | |
477 | if (!HPDF_Image_Validate (image)) |
478 | return 0; |
479 | |
480 | n = HPDF_Dict_GetItem (image, "BitsPerComponent" , HPDF_OCLASS_NUMBER); |
481 | |
482 | if (!n) |
483 | return 0; |
484 | |
485 | return n->value; |
486 | } |
487 | |
488 | HPDF_EXPORT(const char*) |
489 | HPDF_Image_GetColorSpace (HPDF_Image image) |
490 | { |
491 | HPDF_Name n; |
492 | |
493 | HPDF_PTRACE ((" HPDF_Image_GetColorSpace\n" )); |
494 | |
495 | n = HPDF_Dict_GetItem (image, "ColorSpace" , HPDF_OCLASS_NAME); |
496 | |
497 | if (!n) { |
498 | HPDF_Array a; |
499 | |
500 | HPDF_Error_Reset(image->error); |
501 | |
502 | a = HPDF_Dict_GetItem (image, "ColorSpace" , HPDF_OCLASS_ARRAY); |
503 | |
504 | if (a) { |
505 | n = HPDF_Array_GetItem (a, 0, HPDF_OCLASS_NAME); |
506 | } |
507 | } |
508 | |
509 | if (!n) { |
510 | HPDF_CheckError (image->error); |
511 | return NULL; |
512 | } |
513 | |
514 | return n->value; |
515 | } |
516 | |
517 | HPDF_EXPORT(HPDF_UINT) |
518 | HPDF_Image_GetWidth (HPDF_Image image) |
519 | { |
520 | return (HPDF_UINT)HPDF_Image_GetSize (image).x; |
521 | } |
522 | |
523 | HPDF_EXPORT(HPDF_UINT) |
524 | HPDF_Image_GetHeight (HPDF_Image image) |
525 | { |
526 | return (HPDF_UINT)HPDF_Image_GetSize (image).y; |
527 | } |
528 | |
529 | HPDF_STATUS |
530 | HPDF_Image_SetMask (HPDF_Image image, |
531 | HPDF_BOOL mask) |
532 | { |
533 | HPDF_Boolean image_mask; |
534 | |
535 | if (!HPDF_Image_Validate (image)) |
536 | return HPDF_INVALID_IMAGE; |
537 | |
538 | if (mask && HPDF_Image_GetBitsPerComponent (image) != 1) |
539 | return HPDF_SetError (image->error, HPDF_INVALID_BIT_PER_COMPONENT, |
540 | 0); |
541 | |
542 | image_mask = HPDF_Dict_GetItem (image, "ImageMask" , HPDF_OCLASS_BOOLEAN); |
543 | if (!image_mask) { |
544 | HPDF_STATUS ret; |
545 | image_mask = HPDF_Boolean_New (image->mmgr, HPDF_FALSE); |
546 | |
547 | if ((ret = HPDF_Dict_Add (image, "ImageMask" , image_mask)) != HPDF_OK) |
548 | return ret; |
549 | } |
550 | |
551 | image_mask->value = mask; |
552 | return HPDF_OK; |
553 | } |
554 | |
555 | |
556 | HPDF_EXPORT(HPDF_STATUS) |
557 | HPDF_Image_SetMaskImage (HPDF_Image image, |
558 | HPDF_Image mask_image) |
559 | { |
560 | if (!HPDF_Image_Validate (image)) |
561 | return HPDF_INVALID_IMAGE; |
562 | |
563 | if (!HPDF_Image_Validate (mask_image)) |
564 | return HPDF_INVALID_IMAGE; |
565 | |
566 | if (HPDF_Image_SetMask (mask_image, HPDF_TRUE) != HPDF_OK) |
567 | return HPDF_CheckError (image->error); |
568 | |
569 | return HPDF_Dict_Add (image, "Mask" , mask_image); |
570 | } |
571 | |
572 | |
573 | HPDF_EXPORT(HPDF_STATUS) |
574 | HPDF_Image_SetColorMask (HPDF_Image image, |
575 | HPDF_UINT rmin, |
576 | HPDF_UINT rmax, |
577 | HPDF_UINT gmin, |
578 | HPDF_UINT gmax, |
579 | HPDF_UINT bmin, |
580 | HPDF_UINT bmax) |
581 | { |
582 | HPDF_Array array; |
583 | const char *name; |
584 | HPDF_STATUS ret = HPDF_OK; |
585 | |
586 | if (!HPDF_Image_Validate (image)) |
587 | return HPDF_INVALID_IMAGE; |
588 | |
589 | if (HPDF_Dict_GetItem (image, "ImageMask" , HPDF_OCLASS_BOOLEAN)) |
590 | return HPDF_RaiseError (image->error, HPDF_INVALID_OPERATION, 0); |
591 | |
592 | if (HPDF_Image_GetBitsPerComponent (image) != 8) |
593 | return HPDF_RaiseError (image->error, HPDF_INVALID_BIT_PER_COMPONENT, |
594 | 0); |
595 | |
596 | name = HPDF_Image_GetColorSpace (image); |
597 | if (!name || HPDF_StrCmp (COL_RGB, name) != 0) |
598 | return HPDF_RaiseError (image->error, HPDF_INVALID_COLOR_SPACE, 0); |
599 | |
600 | /* Each integer must be in the range 0 to 2^BitsPerComponent - 1 */ |
601 | if (rmax > 255 || gmax > 255 || bmax > 255) |
602 | return HPDF_RaiseError (image->error, HPDF_INVALID_PARAMETER, 0); |
603 | |
604 | array = HPDF_Array_New (image->mmgr); |
605 | if (!array) |
606 | return HPDF_CheckError (image->error); |
607 | |
608 | ret += HPDF_Dict_Add (image, "Mask" , array); |
609 | ret += HPDF_Array_AddNumber (array, rmin); |
610 | ret += HPDF_Array_AddNumber (array, rmax); |
611 | ret += HPDF_Array_AddNumber (array, gmin); |
612 | ret += HPDF_Array_AddNumber (array, gmax); |
613 | ret += HPDF_Array_AddNumber (array, bmin); |
614 | ret += HPDF_Array_AddNumber (array, bmax); |
615 | |
616 | if (ret != HPDF_OK) |
617 | return HPDF_CheckError (image->error); |
618 | |
619 | return HPDF_OK; |
620 | } |
621 | |
622 | HPDF_EXPORT(HPDF_STATUS) |
623 | HPDF_Image_AddSMask (HPDF_Image image, |
624 | HPDF_Image smask) |
625 | { |
626 | |
627 | const char *name; |
628 | |
629 | if (!HPDF_Image_Validate (image)) |
630 | return HPDF_INVALID_IMAGE; |
631 | if (!HPDF_Image_Validate (smask)) |
632 | return HPDF_INVALID_IMAGE; |
633 | |
634 | if (HPDF_Dict_GetItem (image, "SMask" , HPDF_OCLASS_BOOLEAN)) |
635 | return HPDF_RaiseError (image->error, HPDF_INVALID_OPERATION, 0); |
636 | |
637 | name = HPDF_Image_GetColorSpace (smask); |
638 | if (!name || HPDF_StrCmp (COL_GRAY, name) != 0) |
639 | return HPDF_RaiseError (smask->error, HPDF_INVALID_COLOR_SPACE, 0); |
640 | |
641 | return HPDF_Dict_Add (image, "SMask" , smask); |
642 | } |
643 | |
644 | HPDF_STATUS |
645 | HPDF_Image_SetColorSpace (HPDF_Image image, |
646 | HPDF_Array colorspace) |
647 | { |
648 | if (!HPDF_Image_Validate (image)) |
649 | return HPDF_INVALID_IMAGE; |
650 | |
651 | return HPDF_Dict_Add (image, "ColorSpace" , colorspace); |
652 | } |
653 | |
654 | |
655 | HPDF_STATUS |
656 | HPDF_Image_SetRenderingIntent (HPDF_Image image, |
657 | const char* intent) |
658 | { |
659 | if (!HPDF_Image_Validate (image)) |
660 | return HPDF_INVALID_IMAGE; |
661 | |
662 | return HPDF_Dict_AddName (image, "Intent" , intent); |
663 | } |
664 | |
665 | |