42 #include "magick/studio.h"
43 #include "magick/attribute.h"
44 #include "magick/cache.h"
45 #include "magick/color.h"
46 #include "magick/colorspace-private.h"
47 #include "magick/configure.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/hashmap.h"
51 #include "magick/image.h"
52 #include "magick/memory_.h"
53 #include "magick/monitor.h"
54 #include "magick/monitor-private.h"
55 #include "magick/option.h"
56 #include "magick/option-private.h"
57 #include "magick/profile.h"
58 #include "magick/property.h"
59 #include "magick/quantum.h"
60 #include "magick/quantum-private.h"
61 #include "magick/resource_.h"
62 #include "magick/splay-tree.h"
63 #include "magick/string_.h"
64 #include "magick/string-private.h"
65 #include "magick/thread-private.h"
66 #include "magick/token.h"
67 #include "magick/utility.h"
68 #if defined(MAGICKCORE_LCMS_DELEGATE)
69 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
71 #include <lcms/lcms2.h>
77 #if defined(MAGICKCORE_XML_DELEGATE)
78 # if defined(MAGICKCORE_WINDOWS_SUPPORT)
79 # if !defined(__MINGW32__)
80 # include <win32config.h>
83 # include <libxml/parser.h>
84 # include <libxml/tree.h>
90 static MagickBooleanType
92 const MagickBooleanType);
122 MagickExport MagickBooleanType CloneImageProfiles(
Image *image,
123 const Image *clone_image)
125 assert(image != (
Image *) NULL);
126 assert(image->signature == MagickCoreSignature);
127 assert(clone_image != (
const Image *) NULL);
128 assert(clone_image->signature == MagickCoreSignature);
129 if (IsEventLogging() != MagickFalse)
130 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
131 image->color_profile.length=clone_image->color_profile.length;
132 image->color_profile.info=clone_image->color_profile.info;
133 image->iptc_profile.length=clone_image->iptc_profile.length;
134 image->iptc_profile.info=clone_image->iptc_profile.info;
135 if (clone_image->profiles != (
void *) NULL)
137 if (image->profiles != (
void *) NULL)
138 DestroyImageProfiles(image);
139 image->profiles=CloneSplayTree((
SplayTreeInfo *) clone_image->profiles,
140 (
void *(*)(
void *)) ConstantString,(
void *(*)(
void *)) CloneStringInfo);
169 MagickExport MagickBooleanType DeleteImageProfile(
Image *image,
const char *name)
171 assert(image != (
Image *) NULL);
172 assert(image->signature == MagickCoreSignature);
173 if (image->debug != MagickFalse)
174 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
177 if (LocaleCompare(name,
"icc") == 0)
182 image->color_profile.length=0;
183 image->color_profile.info=(
unsigned char *) NULL;
185 if (LocaleCompare(name,
"iptc") == 0)
190 image->iptc_profile.length=0;
191 image->iptc_profile.info=(
unsigned char *) NULL;
193 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
194 return(DeleteNodeFromSplayTree((
SplayTreeInfo *) image->profiles,name));
219 MagickExport
void DestroyImageProfiles(
Image *image)
222 image->profiles=DestroySplayTree((
SplayTreeInfo *) image->profiles);
255 assert(image != (
Image *) NULL);
256 assert(image->signature == MagickCoreSignature);
257 if (image->debug != MagickFalse)
258 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
262 image->profiles,name);
288 MagickExport
char *GetNextImageProfile(
const Image *image)
290 assert(image != (
Image *) NULL);
291 assert(image->signature == MagickCoreSignature);
292 if (IsEventLogging() != MagickFalse)
293 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
295 return((
char *) NULL);
296 return((
char *) GetNextKeyInSplayTree((
SplayTreeInfo *) image->profiles));
340 #if defined(MAGICKCORE_LCMS_DELEGATE)
342 typedef struct _LCMSInfo
360 **magick_restrict pixels,
365 #if LCMS_VERSION < 2060
366 static void* cmsGetContextUserData(cmsContext ContextID)
371 static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
373 magick_unreferenced(Plugin);
374 return((cmsContext) UserData);
377 static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
378 cmsLogErrorHandlerFunction Fn)
380 magick_unreferenced(ContextID);
381 cmsSetLogErrorHandler(Fn);
384 static void cmsDeleteContext(cmsContext magick_unused(ContextID))
386 magick_unreferenced(ContextID);
390 static double **DestroyPixelTLS(
double **pixels)
395 if (pixels == (
double **) NULL)
396 return((
double **) NULL);
397 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
398 if (pixels[i] != (
double *) NULL)
399 pixels[i]=(
double *) RelinquishMagickMemory(pixels[i]);
400 pixels=(
double **) RelinquishMagickMemory(pixels);
404 static double **AcquirePixelTLS(
const size_t columns,
405 const size_t channels)
416 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
417 pixels=(
double **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
418 if (pixels == (
double **) NULL)
419 return((
double **) NULL);
420 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
421 for (i=0; i < (ssize_t) number_threads; i++)
423 pixels[i]=(
double *) AcquireQuantumMemory(columns,channels*
sizeof(**pixels));
424 if (pixels[i] == (
double *) NULL)
425 return(DestroyPixelTLS(pixels));
430 static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
435 assert(transform != (cmsHTRANSFORM *) NULL);
436 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
437 if (transform[i] != (cmsHTRANSFORM) NULL)
438 cmsDeleteTransform(transform[i]);
439 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
443 static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
444 const LCMSInfo *target_info,
const cmsUInt32Number flags,
445 cmsContext cms_context)
456 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
457 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
459 if (transform == (cmsHTRANSFORM *) NULL)
460 return((cmsHTRANSFORM *) NULL);
461 (void) memset(transform,0,number_threads*
sizeof(*transform));
462 for (i=0; i < (ssize_t) number_threads; i++)
464 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
465 source_info->type,target_info->profile,target_info->type,
466 target_info->intent,flags);
467 if (transform[i] == (cmsHTRANSFORM) NULL)
468 return(DestroyTransformTLS(transform));
473 static void LCMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
479 if (IsEventLogging() != MagickFalse)
480 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
481 severity,message != (
char *) NULL ? message :
"no message");
482 image=(
Image *) cmsGetContextUserData(context);
483 if (image != (
Image *) NULL)
484 (
void) ThrowMagickException(&image->exception,GetMagickModule(),
485 ImageWarning,
"UnableToTransformColorspace",
"`%s'",image->filename);
488 static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
490 info->translate[0]=translate;
491 info->translate[1]=translate;
492 info->translate[2]=translate;
493 info->translate[3]=translate;
496 static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
498 info->scale[0]=scale;
499 info->scale[1]=scale;
500 info->scale[2]=scale;
501 info->scale[3]=scale;
505 static MagickBooleanType SetsRGBImageProfile(
Image *image)
510 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
511 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
512 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
513 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
514 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
516 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
521 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
522 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
523 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
524 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
525 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
526 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
527 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
528 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
529 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
530 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
531 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
532 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
533 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
534 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
535 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
536 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
537 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
538 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
539 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
540 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
541 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
542 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
543 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
544 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
546 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
547 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
548 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
549 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
550 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
552 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
553 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
554 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
555 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
556 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
557 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
558 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
559 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
561 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
562 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
564 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
565 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
570 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
571 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
572 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
573 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
575 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
576 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
577 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
578 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
581 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
583 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
585 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
591 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
592 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
593 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
594 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
599 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
602 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
604 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
606 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
607 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
608 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
609 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
610 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
611 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
612 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
613 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
614 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
615 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
616 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
617 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
618 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
619 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
620 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
621 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
622 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
623 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
624 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
625 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
626 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
627 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
628 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
629 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
630 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
631 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
632 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
633 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
634 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
635 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
636 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
637 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
638 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
639 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
640 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
641 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
642 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
643 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
644 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
645 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
646 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
647 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
648 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
649 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
650 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
651 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
652 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
653 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
654 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
655 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
656 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
657 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
658 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
659 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
660 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
661 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
662 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
663 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
664 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
665 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
666 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
667 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
668 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
669 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
670 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
671 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
672 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
673 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
674 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
675 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
676 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
677 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
678 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
679 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
680 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
681 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
682 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
683 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
684 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
685 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
686 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
687 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
688 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
689 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
690 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
691 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
692 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
693 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
694 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
695 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
696 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
697 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
698 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
699 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
700 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
701 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
702 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
703 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
704 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
705 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
706 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
707 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
708 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
709 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
710 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
711 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
712 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
713 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
714 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
715 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
716 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
717 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
718 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
719 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
720 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
721 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
722 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
723 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
724 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
725 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
726 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
727 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
728 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
729 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
730 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
731 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
732 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
733 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
734 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
735 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
736 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
737 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
738 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
739 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
740 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
741 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
742 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
743 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
744 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
745 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
746 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
747 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
748 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
749 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
750 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
751 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
752 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
753 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
754 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
755 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
756 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
757 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
758 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
759 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
760 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
761 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
762 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
763 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
764 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
765 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
766 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
767 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
768 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
769 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
770 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
771 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
772 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
773 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
774 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
775 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
776 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
777 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
786 assert(image != (
Image *) NULL);
787 assert(image->signature == MagickCoreSignature);
788 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
790 profile=AcquireStringInfo(
sizeof(sRGBProfile));
791 SetStringInfoDatum(profile,sRGBProfile);
792 status=SetImageProfile(image,
"icc",profile);
793 profile=DestroyStringInfo(profile);
797 MagickExport MagickBooleanType ProfileImage(
Image *image,
const char *name,
798 const void *datum,
const size_t length,
799 const MagickBooleanType magick_unused(clone))
801 #define GetLCMSPixel(source_info,pixel,index) (source_info.scale[index]* \
802 ((QuantumScale*(MagickRealType) (pixel))+source_info.translate[index]))
803 #define ProfileImageTag "Profile/Image"
804 #define SetLCMSPixel(target_info,pixel,index) ClampToQuantum( \
805 target_info.scale[index]*(((MagickRealType) QuantumRange*pixel)+ \
806 target_info.translate[index]))
807 #define ThrowProfileException(severity,tag,context) \
809 if (profile != (StringInfo *) NULL) \
810 profile=DestroyStringInfo(profile); \
811 if (cms_context != (cmsContext) NULL) \
812 cmsDeleteContext(cms_context); \
813 if (source_info.profile != (cmsHPROFILE) NULL) \
814 (void) cmsCloseProfile(source_info.profile); \
815 if (target_info.profile != (cmsHPROFILE) NULL) \
816 (void) cmsCloseProfile(target_info.profile); \
817 ThrowBinaryException(severity,tag,context); \
826 magick_unreferenced(clone);
828 assert(image != (
Image *) NULL);
829 assert(image->signature == MagickCoreSignature);
830 assert(name != (
const char *) NULL);
831 if (IsEventLogging() != MagickFalse)
832 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
833 if ((datum == (
const void *) NULL) || (length == 0))
841 ResetImageProfileIterator(image);
842 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
844 if (IsOptionMember(next,name) != MagickFalse)
846 (void) DeleteImageProfile(image,next);
847 ResetImageProfileIterator(image);
849 next=GetNextImageProfile(image);
857 profile=AcquireStringInfo((
size_t) length);
858 SetStringInfoDatum(profile,(
unsigned char *) datum);
859 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
860 status=SetImageProfile(image,name,profile);
866 icc_profile=GetImageProfile(image,
"icc");
867 if ((icc_profile != (
const StringInfo *) NULL) &&
868 (CompareStringInfo(icc_profile,profile) == 0))
873 value=GetImageProperty(image,
"exif:ColorSpace");
875 if (LocaleCompare(value,
"1") != 0)
876 (
void) SetsRGBImageProfile(image);
877 value=GetImageProperty(image,
"exif:InteroperabilityIndex");
878 if (LocaleCompare(value,
"R98.") != 0)
879 (void) SetsRGBImageProfile(image);
880 icc_profile=GetImageProfile(image,
"icc");
882 if ((icc_profile != (
const StringInfo *) NULL) &&
883 (CompareStringInfo(icc_profile,profile) == 0))
885 profile=DestroyStringInfo(profile);
888 #if !defined(MAGICKCORE_LCMS_DELEGATE)
889 (void) ThrowMagickException(&image->exception,GetMagickModule(),
890 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (LCMS)",
904 cms_context=cmsCreateContext(NULL,image);
905 if (cms_context == (cmsContext) NULL)
907 profile=DestroyStringInfo(profile);
908 ThrowBinaryImageException(ResourceLimitError,
909 "ColorspaceColorProfileMismatch",name);
911 cmsSetLogErrorHandlerTHR(cms_context,LCMSExceptionHandler);
912 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
913 GetStringInfoDatum(profile),(cmsUInt32Number)
914 GetStringInfoLength(profile));
915 if (source_info.profile == (cmsHPROFILE) NULL)
917 profile=DestroyStringInfo(profile);
918 cmsDeleteContext(cms_context);
919 ThrowBinaryImageException(ResourceLimitError,
920 "ColorspaceColorProfileMismatch",name);
922 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
924 status=SetImageProfile(image,name,profile);
930 cmsColorSpaceSignature
934 *magick_restrict transform;
948 exception=(&image->exception);
949 target_info.profile=(cmsHPROFILE) NULL;
952 target_info.profile=source_info.profile;
953 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
954 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
955 GetStringInfoLength(icc_profile));
956 if (source_info.profile == (cmsHPROFILE) NULL)
957 ThrowProfileException(ResourceLimitError,
958 "ColorspaceColorProfileMismatch",name);
960 SetLCMSInfoScale(&source_info,1.0);
961 SetLCMSInfoTranslate(&source_info,0.0);
962 source_info.colorspace=sRGBColorspace;
963 source_info.channels=3;
964 switch (cmsGetColorSpace(source_info.profile))
968 source_info.colorspace=CMYKColorspace;
969 source_info.channels=4;
970 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
971 SetLCMSInfoScale(&source_info,100.0);
976 source_info.colorspace=GRAYColorspace;
977 source_info.channels=1;
978 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
983 source_info.colorspace=LabColorspace;
984 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
985 source_info.scale[0]=100.0;
986 source_info.scale[1]=255.0;
987 source_info.scale[2]=255.0;
988 source_info.translate[1]=(-0.5);
989 source_info.translate[2]=(-0.5);
994 source_info.colorspace=sRGBColorspace;
995 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1000 source_info.colorspace=XYZColorspace;
1001 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1005 ThrowProfileException(ImageError,
1006 "ColorspaceColorProfileMismatch",name);
1008 signature=cmsGetPCS(source_info.profile);
1009 if (target_info.profile != (cmsHPROFILE) NULL)
1010 signature=cmsGetColorSpace(target_info.profile);
1011 SetLCMSInfoScale(&target_info,1.0);
1012 SetLCMSInfoTranslate(&target_info,0.0);
1013 target_info.channels=3;
1016 case cmsSigCmykData:
1018 target_info.colorspace=CMYKColorspace;
1019 target_info.channels=4;
1020 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1021 SetLCMSInfoScale(&target_info,0.01);
1024 case cmsSigGrayData:
1026 target_info.colorspace=GRAYColorspace;
1027 target_info.channels=1;
1028 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1033 target_info.colorspace=LabColorspace;
1034 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1035 target_info.scale[0]=0.01;
1036 target_info.scale[1]=1/255.0;
1037 target_info.scale[2]=1/255.0;
1038 target_info.translate[1]=0.5;
1039 target_info.translate[2]=0.5;
1044 target_info.colorspace=sRGBColorspace;
1045 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1050 target_info.colorspace=XYZColorspace;
1051 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1055 ThrowProfileException(ImageError,
1056 "ColorspaceColorProfileMismatch",name);
1058 switch (image->rendering_intent)
1060 case AbsoluteIntent:
1062 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1065 case PerceptualIntent:
1067 target_info.intent=INTENT_PERCEPTUAL;
1070 case RelativeIntent:
1072 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1075 case SaturationIntent:
1077 target_info.intent=INTENT_SATURATION;
1082 target_info.intent=INTENT_PERCEPTUAL;
1086 flags=cmsFLAGS_HIGHRESPRECALC;
1087 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1088 if (image->black_point_compensation != MagickFalse)
1089 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1091 transform=AcquireTransformTLS(&source_info,&target_info,
1093 if (transform == (cmsHTRANSFORM *) NULL)
1094 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1099 source_info.pixels=AcquirePixelTLS(image->columns,
1100 source_info.channels);
1101 target_info.pixels=AcquirePixelTLS(image->columns,
1102 target_info.channels);
1103 if ((source_info.pixels == (
double **) NULL) ||
1104 (target_info.pixels == (
double **) NULL))
1106 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1107 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1108 transform=DestroyTransformTLS(transform);
1109 ThrowProfileException(ResourceLimitError,
1110 "MemoryAllocationFailed",image->filename);
1112 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1114 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1115 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1116 transform=DestroyTransformTLS(transform);
1117 profile=DestroyStringInfo(profile);
1118 if (source_info.profile != (cmsHPROFILE) NULL)
1119 (void) cmsCloseProfile(source_info.profile);
1120 if (target_info.profile != (cmsHPROFILE) NULL)
1121 (
void) cmsCloseProfile(target_info.profile);
1122 return(MagickFalse);
1124 if (target_info.colorspace == CMYKColorspace)
1125 (void) SetImageColorspace(image,target_info.colorspace);
1127 image_view=AcquireAuthenticCacheView(image,exception);
1128 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1129 #pragma omp parallel for schedule(static) shared(status) \
1130 magick_number_threads(image,image,image->rows,1)
1132 for (y=0; y < (ssize_t) image->rows; y++)
1135 id = GetOpenMPThreadId();
1141 *magick_restrict indexes;
1152 if (status == MagickFalse)
1154 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1161 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1162 p=source_info.pixels[id];
1163 for (x=0; x < (ssize_t) image->columns; x++)
1165 *p++=GetLCMSPixel(source_info,GetPixelRed(q),0);
1166 if (source_info.channels > 1)
1168 *p++=GetLCMSPixel(source_info,GetPixelGreen(q),1);
1169 *p++=GetLCMSPixel(source_info,GetPixelBlue(q),2);
1171 if (source_info.channels > 3)
1173 *p=GetLCMSPixel(source_info,0,3);
1174 if (indexes != (IndexPacket *) NULL)
1175 *p=GetLCMSPixel(source_info,GetPixelIndex(indexes+x),3);
1180 cmsDoTransform(transform[
id],source_info.pixels[
id],
1181 target_info.pixels[
id],(
unsigned int) image->columns);
1182 p=target_info.pixels[id];
1184 for (x=0; x < (ssize_t) image->columns; x++)
1186 SetPixelRed(q,SetLCMSPixel(target_info,*p,0));
1187 SetPixelGreen(q,GetPixelRed(q));
1188 SetPixelBlue(q,GetPixelRed(q));
1190 if (target_info.channels > 1)
1192 SetPixelGreen(q,SetLCMSPixel(target_info,*p,1));
1194 SetPixelBlue(q,SetLCMSPixel(target_info,*p,2));
1197 if (target_info.channels > 3)
1199 if (indexes != (IndexPacket *) NULL)
1200 SetPixelIndex(indexes+x,SetLCMSPixel(target_info,*p,3));
1205 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1206 if (sync == MagickFalse)
1208 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1213 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1217 proceed=SetImageProgress(image,ProfileImageTag,progress,
1219 if (proceed == MagickFalse)
1223 image_view=DestroyCacheView(image_view);
1224 (void) SetImageColorspace(image,target_info.colorspace);
1229 image->type=image->matte == MagickFalse ? TrueColorType :
1233 case cmsSigCmykData:
1235 image->type=image->matte == MagickFalse ? ColorSeparationType :
1236 ColorSeparationMatteType;
1239 case cmsSigGrayData:
1241 image->type=image->matte == MagickFalse ? GrayscaleType :
1248 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1249 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1250 transform=DestroyTransformTLS(transform);
1251 if ((status != MagickFalse) &&
1252 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1253 status=SetImageProfile(image,name,profile);
1254 if (target_info.profile != (cmsHPROFILE) NULL)
1255 (void) cmsCloseProfile(target_info.profile);
1257 (void) cmsCloseProfile(source_info.profile);
1258 cmsDeleteContext(cms_context);
1262 profile=DestroyStringInfo(profile);
1291 MagickExport
StringInfo *RemoveImageProfile(
Image *image,
const char *name)
1296 assert(image != (
Image *) NULL);
1297 assert(image->signature == MagickCoreSignature);
1298 if (IsEventLogging() != MagickFalse)
1299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1302 if (LocaleCompare(name,
"icc") == 0)
1307 image->color_profile.length=0;
1308 image->color_profile.info=(
unsigned char *) NULL;
1310 if (LocaleCompare(name,
"iptc") == 0)
1315 image->iptc_profile.length=0;
1316 image->iptc_profile.info=(
unsigned char *) NULL;
1318 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
1320 image->profiles,name);
1348 MagickExport
void ResetImageProfileIterator(
const Image *image)
1350 assert(image != (
Image *) NULL);
1351 assert(image->signature == MagickCoreSignature);
1352 if (IsEventLogging() != MagickFalse)
1353 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1390 static void *DestroyProfile(
void *profile)
1392 return((
void *) DestroyStringInfo((
StringInfo *) profile));
1395 static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1396 unsigned char *quantum)
1402 static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1403 unsigned int *quantum)
1405 *quantum=(
unsigned int) (*p++) << 24;
1406 *quantum|=(
unsigned int) (*p++) << 16;
1407 *quantum|=(
unsigned int) (*p++) << 8;
1408 *quantum|=(
unsigned int) (*p++);
1412 static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1413 unsigned short *quantum)
1415 *quantum=(
unsigned short) (*p++) << 8;
1416 *quantum|=(
unsigned short) (*p++);
1420 static inline void WriteResourceLong(
unsigned char *p,
1421 const unsigned int quantum)
1426 buffer[0]=(
unsigned char) (quantum >> 24);
1427 buffer[1]=(
unsigned char) (quantum >> 16);
1428 buffer[2]=(
unsigned char) (quantum >> 8);
1429 buffer[3]=(
unsigned char) quantum;
1430 (void) memcpy(p,buffer,4);
1433 static void WriteTo8BimProfile(
Image *image,
const char *name,
1463 if (LocaleCompare(name,
"icc") == 0)
1466 if (LocaleCompare(name,
"iptc") == 0)
1469 if (LocaleCompare(name,
"xmp") == 0)
1474 image->profiles,
"8bim");
1477 datum=GetStringInfoDatum(profile_8bim);
1478 length=GetStringInfoLength(profile_8bim);
1479 for (p=datum; p < (datum+length-16); )
1482 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1485 p=ReadResourceShort(p,&
id);
1486 p=ReadResourceByte(p,&length_byte);
1488 if (((length_byte+1) & 0x01) != 0)
1490 if (p > (datum+length-4))
1492 p=ReadResourceLong(p,&value);
1493 count=(ssize_t) value;
1494 if ((count & 0x01) != 0)
1496 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1498 if (
id != profile_id)
1513 extent=(datum+length)-(p+count);
1517 extract_profile=AcquireStringInfo(offset+extent);
1518 (void) memcpy(extract_profile->datum,datum,offset);
1523 extract_extent=profile->length;
1524 if ((extract_extent & 0x01) != 0)
1526 extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1527 (void) memcpy(extract_profile->datum,datum,offset-4);
1528 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1530 (void) memcpy(extract_profile->datum+offset,
1531 profile->datum,profile->length);
1533 (void) memcpy(extract_profile->datum+offset+extract_extent,
1535 (void) AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1536 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1537 extract_profile=DestroyStringInfo(extract_profile);
1543 static void GetProfilesFromResourceBlock(
Image *image,
1570 datum=GetStringInfoDatum(resource_block);
1571 length=GetStringInfoLength(resource_block);
1572 for (p=datum; p < (datum+length-16); )
1574 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1577 p=ReadResourceShort(p,&
id);
1578 p=ReadResourceByte(p,&length_byte);
1580 if (((length_byte+1) & 0x01) != 0)
1582 if (p > (datum+length-4))
1584 p=ReadResourceLong(p,&value);
1585 count=(ssize_t) value;
1586 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1604 p=ReadResourceLong(p,&resolution);
1605 image->x_resolution=((double) resolution)/65536.0;
1606 p=ReadResourceShort(p,&units)+2;
1607 p=ReadResourceLong(p,&resolution)+4;
1608 image->y_resolution=((double) resolution)/65536.0;
1612 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1613 image->units=PixelsPerInchResolution;
1616 image->units=PixelsPerCentimeterResolution;
1617 image->x_resolution/=2.54;
1618 image->y_resolution/=2.54;
1627 profile=AcquireStringInfo(count);
1628 SetStringInfoDatum(profile,p);
1629 (void) SetImageProfileInternal(image,
"iptc",profile,MagickTrue);
1630 profile=DestroyStringInfo(profile);
1647 profile=AcquireStringInfo(count);
1648 SetStringInfoDatum(profile,p);
1649 (void) SetImageProfileInternal(image,
"icc",profile,MagickTrue);
1650 profile=DestroyStringInfo(profile);
1659 profile=AcquireStringInfo(count);
1660 SetStringInfoDatum(profile,p);
1661 (void) SetImageProfileInternal(image,
"exif",profile,MagickTrue);
1662 profile=DestroyStringInfo(profile);
1671 profile=AcquireStringInfo(count);
1672 SetStringInfoDatum(profile,p);
1673 (void) SetImageProfileInternal(image,
"xmp",profile,MagickTrue);
1674 profile=DestroyStringInfo(profile);
1684 if ((count & 0x01) != 0)
1689 #if defined(MAGICKCORE_XML_DELEGATE)
1690 static MagickBooleanType ValidateXMPProfile(
Image *image,
1699 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1700 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1701 XML_PARSE_NOWARNING);
1702 if (document == (xmlDocPtr) NULL)
1704 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1705 ImageWarning,
"CorruptImageProfile",
"`%s' (XMP)",image->filename);
1706 return(MagickFalse);
1708 xmlFreeDoc(document);
1712 static MagickBooleanType ValidateXMPProfile(
Image *image,
1715 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1716 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"'%s' (XML)",
1718 return(MagickFalse);
1722 static MagickBooleanType SetImageProfileInternal(
Image *image,
const char *name,
1723 const StringInfo *profile,
const MagickBooleanType recursive)
1731 assert(image != (
Image *) NULL);
1732 assert(image->signature == MagickCoreSignature);
1733 if (IsEventLogging() != MagickFalse)
1734 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1735 if ((LocaleCompare(name,
"xmp") == 0) &&
1736 (ValidateXMPProfile(image,profile) == MagickFalse))
1739 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1741 (void) CopyMagickString(key,name,MaxTextExtent);
1743 status=AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1744 ConstantString(key),CloneStringInfo(profile));
1745 if ((status != MagickFalse) &&
1746 ((LocaleCompare(name,
"icc") == 0) || (LocaleCompare(name,
"icm") == 0)))
1754 icc_profile=GetImageProfile(image,name);
1755 if (icc_profile != (
const StringInfo *) NULL)
1757 image->color_profile.length=GetStringInfoLength(icc_profile);
1758 image->color_profile.info=GetStringInfoDatum(icc_profile);
1761 if ((status != MagickFalse) &&
1762 ((LocaleCompare(name,
"iptc") == 0) || (LocaleCompare(name,
"8bim") == 0)))
1770 iptc_profile=GetImageProfile(image,name);
1771 if (iptc_profile != (
const StringInfo *) NULL)
1773 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1774 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1777 if (status != MagickFalse)
1779 if (LocaleCompare(name,
"8bim") == 0)
1780 GetProfilesFromResourceBlock(image,profile);
1782 if (recursive == MagickFalse)
1783 WriteTo8BimProfile(image,name,profile);
1788 MagickExport MagickBooleanType SetImageProfile(
Image *image,
const char *name,
1791 return(SetImageProfileInternal(image,name,profile,MagickFalse));
1818 static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
1830 static inline signed short ReadProfileShort(
const EndianType endian,
1831 unsigned char *buffer)
1845 if (endian == LSBEndian)
1847 value=(
unsigned short) buffer[1] << 8;
1848 value|=(
unsigned short) buffer[0];
1849 quantum.unsigned_value=value & 0xffff;
1850 return(quantum.signed_value);
1852 value=(
unsigned short) buffer[0] << 8;
1853 value|=(
unsigned short) buffer[1];
1854 quantum.unsigned_value=value & 0xffff;
1855 return(quantum.signed_value);
1858 static inline signed int ReadProfileLong(
const EndianType endian,
1859 unsigned char *buffer)
1873 if (endian == LSBEndian)
1875 value=(
unsigned int) buffer[3] << 24;
1876 value|=(
unsigned int) buffer[2] << 16;
1877 value|=(
unsigned int) buffer[1] << 8;
1878 value|=(
unsigned int) buffer[0];
1879 quantum.unsigned_value=value & 0xffffffff;
1880 return(quantum.signed_value);
1882 value=(
unsigned int) buffer[0] << 24;
1883 value|=(
unsigned int) buffer[1] << 16;
1884 value|=(
unsigned int) buffer[2] << 8;
1885 value|=(
unsigned int) buffer[3];
1886 quantum.unsigned_value=value & 0xffffffff;
1887 return(quantum.signed_value);
1890 static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
1897 value=ReadProfileLong(MSBEndian,*p);
1903 static inline signed short ReadProfileMSBShort(
unsigned char **p,
1911 value=ReadProfileShort(MSBEndian,*p);
1917 static inline void WriteProfileLong(
const EndianType endian,
1918 const size_t value,
unsigned char *p)
1923 if (endian == LSBEndian)
1925 buffer[0]=(
unsigned char) value;
1926 buffer[1]=(
unsigned char) (value >> 8);
1927 buffer[2]=(
unsigned char) (value >> 16);
1928 buffer[3]=(
unsigned char) (value >> 24);
1929 (void) memcpy(p,buffer,4);
1932 buffer[0]=(
unsigned char) (value >> 24);
1933 buffer[1]=(
unsigned char) (value >> 16);
1934 buffer[2]=(
unsigned char) (value >> 8);
1935 buffer[3]=(
unsigned char) value;
1936 (void) memcpy(p,buffer,4);
1939 static void WriteProfileShort(
const EndianType endian,
1940 const unsigned short value,
unsigned char *p)
1945 if (endian == LSBEndian)
1947 buffer[0]=(
unsigned char) value;
1948 buffer[1]=(
unsigned char) (value >> 8);
1949 (void) memcpy(p,buffer,2);
1952 buffer[0]=(
unsigned char) (value >> 8);
1953 buffer[1]=(
unsigned char) value;
1954 (void) memcpy(p,buffer,2);
1957 static MagickBooleanType SyncExifProfile(
const Image *image,
unsigned char *exif,
1960 #define MaxDirectoryStack 16
1961 #define EXIF_DELIMITER "\n"
1962 #define EXIF_NUM_FORMATS 12
1963 #define TAG_EXIF_OFFSET 0x8769
1964 #define TAG_INTEROP_OFFSET 0xa005
1966 typedef struct _DirectoryInfo
1976 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
1994 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2000 return(MagickFalse);
2001 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2002 if ((
id != 0x4949) && (
id != 0x4D4D))
2006 if (ReadProfileByte(&exif,&length) != 0x45)
2008 if (ReadProfileByte(&exif,&length) != 0x78)
2010 if (ReadProfileByte(&exif,&length) != 0x69)
2012 if (ReadProfileByte(&exif,&length) != 0x66)
2014 if (ReadProfileByte(&exif,&length) != 0x00)
2016 if (ReadProfileByte(&exif,&length) != 0x00)
2021 return(MagickFalse);
2022 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2031 return(MagickFalse);
2032 if (ReadProfileShort(endian,exif+2) != 0x002a)
2033 return(MagickFalse);
2037 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2038 if ((offset < 0) || ((size_t) offset >= length))
2039 return(MagickFalse);
2040 directory=exif+offset;
2043 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2044 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2050 directory=directory_stack[level].directory;
2051 entry=directory_stack[level].entry;
2053 if ((directory < exif) || (directory > (exif+length-2)))
2058 number_entries=ReadProfileShort(endian,directory);
2059 for ( ; entry < number_entries; entry++)
2075 q=(
unsigned char *) (directory+2+(12*entry));
2076 if (q > (exif+length-12))
2078 if (GetValueFromSplayTree(exif_resources,q) == q)
2080 (void) AddValueToSplayTree(exif_resources,q,q);
2081 tag_value=(ssize_t) ReadProfileShort(endian,q);
2082 format=(ssize_t) ReadProfileShort(endian,q+2);
2083 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2085 components=(int) ReadProfileLong(endian,q+4);
2088 number_bytes=(size_t) components*format_bytes[format];
2089 if ((ssize_t) number_bytes < components)
2091 if (number_bytes <= 4)
2098 offset=(ssize_t) ReadProfileLong(endian,q+8);
2099 if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2101 if (~length < number_bytes)
2103 p=(
unsigned char *) (exif+offset);
2109 (void) WriteProfileLong(endian,(
size_t) (image->x_resolution+0.5),p);
2110 if (number_bytes == 8)
2111 (void) WriteProfileLong(endian,1UL,p+4);
2116 (void) WriteProfileLong(endian,(
size_t) (image->y_resolution+0.5),p);
2117 if (number_bytes == 8)
2118 (void) WriteProfileLong(endian,1UL,p+4);
2123 if (number_bytes == 4)
2125 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2128 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2134 if (number_bytes == 4)
2136 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2139 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2145 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2147 offset=(ssize_t) ReadProfileLong(endian,p);
2148 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2150 directory_stack[level].directory=directory;
2152 directory_stack[level].entry=entry;
2154 directory_stack[level].directory=exif+offset;
2155 directory_stack[level].entry=0;
2157 if ((directory+2+(12*number_entries)) > (exif+length))
2159 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2161 if ((offset != 0) && ((size_t) offset < length) &&
2162 (level < (MaxDirectoryStack-2)))
2164 directory_stack[level].directory=exif+offset;
2165 directory_stack[level].entry=0;
2172 }
while (level > 0);
2173 exif_resources=DestroySplayTree(exif_resources);
2177 static MagickBooleanType Sync8BimProfile(
const Image *image,
2192 length=GetStringInfoLength(profile);
2193 p=GetStringInfoDatum(profile);
2196 if (ReadProfileByte(&p,&length) != 0x38)
2198 if (ReadProfileByte(&p,&length) != 0x42)
2200 if (ReadProfileByte(&p,&length) != 0x49)
2202 if (ReadProfileByte(&p,&length) != 0x4D)
2205 return(MagickFalse);
2206 id=ReadProfileMSBShort(&p,&length);
2207 count=(ssize_t) ReadProfileByte(&p,&length);
2208 if ((count >= (ssize_t) length) || (count < 0))
2209 return(MagickFalse);
2212 if ((*p & 0x01) == 0)
2213 (
void) ReadProfileByte(&p,&length);
2214 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2215 if ((count > (ssize_t) length) || (count < 0))
2216 return(MagickFalse);
2217 if ((
id == 0x3ED) && (count == 16))
2219 if (image->units == PixelsPerCentimeterResolution)
2220 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2221 image->x_resolution*2.54*65536.0),p);
2223 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2224 image->x_resolution*65536.0),p);
2225 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2226 if (image->units == PixelsPerCentimeterResolution)
2227 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2228 image->y_resolution*2.54*65536.0),p+8);
2230 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2231 image->y_resolution*65536.0),p+8);
2232 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2235 (void) SyncExifProfile(image,p,count);
2242 MagickExport MagickBooleanType SyncImageProfiles(
Image *image)
2251 profile=(
StringInfo *) GetImageProfile(image,
"8BIM");
2253 if (Sync8BimProfile(image,profile) == MagickFalse)
2255 profile=(
StringInfo *) GetImageProfile(image,
"EXIF");
2257 if (SyncExifProfile(image,GetStringInfoDatum(profile),
2258 GetStringInfoLength(profile)) == MagickFalse)