42#include "MagickCore/studio.h"
43#include "MagickCore/artifact.h"
44#include "MagickCore/attribute.h"
45#include "MagickCore/cache.h"
46#include "MagickCore/color.h"
47#include "MagickCore/colorspace-private.h"
48#include "MagickCore/configure.h"
49#include "MagickCore/exception.h"
50#include "MagickCore/exception-private.h"
51#include "MagickCore/image.h"
52#include "MagickCore/linked-list.h"
53#include "MagickCore/memory_.h"
54#include "MagickCore/monitor.h"
55#include "MagickCore/monitor-private.h"
56#include "MagickCore/option.h"
57#include "MagickCore/option-private.h"
58#include "MagickCore/pixel-accessor.h"
59#include "MagickCore/profile.h"
60#include "MagickCore/profile-private.h"
61#include "MagickCore/property.h"
62#include "MagickCore/quantum.h"
63#include "MagickCore/quantum-private.h"
64#include "MagickCore/resource_.h"
65#include "MagickCore/splay-tree.h"
66#include "MagickCore/string_.h"
67#include "MagickCore/string-private.h"
68#include "MagickCore/thread-private.h"
69#include "MagickCore/token.h"
70#include "MagickCore/utility.h"
71#if defined(MAGICKCORE_LCMS_DELEGATE)
73#if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
74#include <lcms/lcms2.h>
79#if defined(MAGICKCORE_XML_DELEGATE)
80# include <libxml/parser.h>
81# include <libxml/tree.h>
87static MagickBooleanType
88 SetImageProfileInternal(Image *,
const char *,StringInfo *,
89 const MagickBooleanType,ExceptionInfo *);
92 WriteTo8BimProfile(Image *,
const char*,
const StringInfo *);
148 *(*CloneKeyFunc)(
const char *);
151 *(*CloneValueFunc)(
const StringInfo *);
153static inline void *CloneProfileKey(
void *key)
155 return((
void *) ((CloneKeyFunc) ConstantString)((
const char *) key));
158static inline void *CloneProfileValue(
void *value)
160 return((
void *) ((CloneValueFunc) CloneStringInfo)((
const StringInfo *) value));
163MagickExport MagickBooleanType CloneImageProfiles(Image *image,
164 const Image *clone_image)
166 assert(image != (Image *) NULL);
167 assert(image->signature == MagickCoreSignature);
168 assert(clone_image != (
const Image *) NULL);
169 assert(clone_image->signature == MagickCoreSignature);
170 if (IsEventLogging() != MagickFalse)
171 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
172 if (clone_image->profiles != (
void *) NULL)
174 if (image->profiles != (
void *) NULL)
175 DestroyImageProfiles(image);
176 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
177 CloneProfileKey,CloneProfileValue);
206MagickExport MagickBooleanType DeleteImageProfile(Image *image,
const char *name)
208 assert(image != (Image *) NULL);
209 assert(image->signature == MagickCoreSignature);
210 if (IsEventLogging() != MagickFalse)
211 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
212 if (image->profiles == (SplayTreeInfo *) NULL)
214 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
215 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
240MagickExport
void DestroyImageProfiles(Image *image)
242 if (image->profiles != (SplayTreeInfo *) NULL)
243 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
270MagickExport
const StringInfo *GetImageProfile(
const Image *image,
276 assert(image != (Image *) NULL);
277 assert(image->signature == MagickCoreSignature);
278 if (IsEventLogging() != MagickFalse)
279 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
280 if (image->profiles == (SplayTreeInfo *) NULL)
281 return((StringInfo *) NULL);
282 profile=(
const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
283 image->profiles,name);
309MagickExport
char *GetNextImageProfile(
const Image *image)
311 assert(image != (Image *) NULL);
312 assert(image->signature == MagickCoreSignature);
313 if (IsEventLogging() != MagickFalse)
314 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
315 if (image->profiles == (SplayTreeInfo *) NULL)
316 return((
char *) NULL);
317 return((
char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
361#if defined(MAGICKCORE_LCMS_DELEGATE)
363typedef struct _LCMSInfo
385 **magick_restrict pixels;
388#if LCMS_VERSION < 2060
389static void* cmsGetContextUserData(cmsContext ContextID)
394static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
396 magick_unreferenced(Plugin);
397 return((cmsContext) UserData);
400static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
401 cmsLogErrorHandlerFunction Fn)
403 magick_unreferenced(ContextID);
404 cmsSetLogErrorHandler(Fn);
407static void cmsDeleteContext(cmsContext magick_unused(ContextID))
409 magick_unreferenced(ContextID);
413static void **DestroyPixelTLS(
void **pixels)
418 if (pixels == (
void **) NULL)
419 return((
void **) NULL);
420 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
421 if (pixels[i] != (
void *) NULL)
422 pixels[i]=RelinquishMagickMemory(pixels[i]);
423 pixels=(
void **) RelinquishMagickMemory(pixels);
427static void **AcquirePixelTLS(
const size_t columns,
const size_t channels,
428 MagickBooleanType highres)
442 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
443 pixels=(
void **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
444 if (pixels == (
void **) NULL)
445 return((
void **) NULL);
446 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
448 if (highres == MagickFalse)
449 size=
sizeof(Quantum);
450 for (i=0; i < (ssize_t) number_threads; i++)
452 pixels[i]=AcquireQuantumMemory(columns,channels*size);
453 if (pixels[i] == (
void *) NULL)
454 return(DestroyPixelTLS(pixels));
459static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
464 assert(transform != (cmsHTRANSFORM *) NULL);
465 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
466 if (transform[i] != (cmsHTRANSFORM) NULL)
467 cmsDeleteTransform(transform[i]);
468 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
472static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
473 const LCMSInfo *target_info,
const cmsUInt32Number flags,
474 cmsContext cms_context)
485 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
486 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
488 if (transform == (cmsHTRANSFORM *) NULL)
489 return((cmsHTRANSFORM *) NULL);
490 (void) memset(transform,0,number_threads*
sizeof(*transform));
491 for (i=0; i < (ssize_t) number_threads; i++)
493 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
494 source_info->type,target_info->profile,target_info->type,
495 (cmsUInt32Number) target_info->intent,flags);
496 if (transform[i] == (cmsHTRANSFORM) NULL)
497 return(DestroyTransformTLS(transform));
502static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
514 cms_exception=(CMSExceptionInfo *) cmsGetContextUserData(context);
515 if (cms_exception == (CMSExceptionInfo *) NULL)
517 exception=cms_exception->exception;
518 if (exception == (ExceptionInfo *) NULL)
520 image=cms_exception->image;
521 if (image == (Image *) NULL)
523 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
524 "UnableToTransformColorspace",
"`%s'",
"unknown context");
527 if (image->debug != MagickFalse)
528 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
529 severity,message != (
char *) NULL ? message :
"no message");
530 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
531 "UnableToTransformColorspace",
"`%s', %s (#%u)",image->filename,
532 message != (
char *) NULL ? message :
"no message",severity);
535static void TransformDoublePixels(
const int id,
const Image* image,
536 const LCMSInfo *source_info,
const LCMSInfo *target_info,
537 const cmsHTRANSFORM *transform,Quantum *q)
539#define GetLCMSPixel(source_info,pixel,index) \
540 (source_info->scale[index]*(((double) QuantumScale*(double) pixel)+ \
541 source_info->translate[index]))
542#define SetLCMSPixel(target_info,pixel,index) ClampToQuantum( \
543 target_info->scale[index]*(((double) QuantumRange*(double) pixel)+ \
544 target_info->translate[index]))
552 p=(
double *) source_info->pixels[
id];
553 for (x=0; x < (ssize_t) image->columns; x++)
555 *p++=GetLCMSPixel(source_info,GetPixelRed(image,q),0);
556 if (source_info->channels > 1)
558 *p++=GetLCMSPixel(source_info,GetPixelGreen(image,q),1);
559 *p++=GetLCMSPixel(source_info,GetPixelBlue(image,q),2);
561 if (source_info->channels > 3)
562 *p++=GetLCMSPixel(source_info,GetPixelBlack(image,q),3);
563 q+=(ptrdiff_t) GetPixelChannels(image);
565 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
566 (
unsigned int) image->columns);
567 p=(
double *) target_info->pixels[
id];
568 q-=GetPixelChannels(image)*image->columns;
569 for (x=0; x < (ssize_t) image->columns; x++)
571 if (target_info->channels == 1)
572 SetPixelGray(image,SetLCMSPixel(target_info,*p,0),q);
574 SetPixelRed(image,SetLCMSPixel(target_info,*p,0),q);
576 if (target_info->channels > 1)
578 SetPixelGreen(image,SetLCMSPixel(target_info,*p,1),q);
580 SetPixelBlue(image,SetLCMSPixel(target_info,*p,2),q);
583 if (target_info->channels > 3)
585 SetPixelBlack(image,SetLCMSPixel(target_info,*p,3),q);
588 q+=(ptrdiff_t) GetPixelChannels(image);
592static void TransformQuantumPixels(
const int id,
const Image* image,
593 const LCMSInfo *source_info,
const LCMSInfo *target_info,
594 const cmsHTRANSFORM *transform,Quantum *q)
602 p=(Quantum *) source_info->pixels[
id];
603 for (x=0; x < (ssize_t) image->columns; x++)
605 *p++=GetPixelRed(image,q);
606 if (source_info->channels > 1)
608 *p++=GetPixelGreen(image,q);
609 *p++=GetPixelBlue(image,q);
611 if (source_info->channels > 3)
612 *p++=GetPixelBlack(image,q);
613 q+=(ptrdiff_t) GetPixelChannels(image);
615 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
616 (
unsigned int) image->columns);
617 p=(Quantum *) target_info->pixels[
id];
618 q-=GetPixelChannels(image)*image->columns;
619 for (x=0; x < (ssize_t) image->columns; x++)
621 if (target_info->channels == 1)
622 SetPixelGray(image,*p++,q);
624 SetPixelRed(image,*p++,q);
625 if (target_info->channels > 1)
627 SetPixelGreen(image,*p++,q);
628 SetPixelBlue(image,*p++,q);
630 if (target_info->channels > 3)
631 SetPixelBlack(image,*p++,q);
632 q+=(ptrdiff_t) GetPixelChannels(image);
636static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
638 info->translate[0]=translate;
639 info->translate[1]=translate;
640 info->translate[2]=translate;
641 info->translate[3]=translate;
644static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
646 info->scale[0]=scale;
647 info->scale[1]=scale;
648 info->scale[2]=scale;
649 info->scale[3]=scale;
653static void SetsRGBImageProfile(Image *image,ExceptionInfo *exception)
658 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
659 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
660 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
661 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
662 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
664 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
669 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
670 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
671 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
672 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
673 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
674 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
675 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
676 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
677 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
678 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
679 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
680 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
681 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
682 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
683 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
684 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
685 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
686 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
687 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
688 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
689 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
690 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
691 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
692 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
694 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
695 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
696 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
697 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
698 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
700 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
701 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
702 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
703 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
704 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
705 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
706 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
707 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
709 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
710 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
712 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
713 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
718 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
719 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
720 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
721 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
723 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
724 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
725 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
726 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
729 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
730 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
731 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
733 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
739 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
740 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
741 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
742 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
747 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
750 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
752 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
754 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
755 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
756 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
757 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
758 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
759 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
760 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
761 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
762 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
763 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
764 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
765 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
766 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
767 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
768 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
769 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
770 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
771 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
772 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
773 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
774 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
775 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
776 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
777 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
778 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
779 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
780 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
781 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
782 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
783 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
784 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
785 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
786 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
787 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
788 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
789 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
790 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
791 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
792 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
793 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
794 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
795 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
796 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
797 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
798 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
799 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
800 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
801 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
802 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
803 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
804 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
805 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
806 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
807 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
808 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
809 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
810 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
811 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
812 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
813 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
814 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
815 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
816 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
817 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
818 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
819 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
820 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
821 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
822 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
823 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
824 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
825 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
826 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
827 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
828 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
829 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
830 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
831 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
832 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
833 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
834 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
835 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
836 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
837 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
838 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
839 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
840 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
841 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
842 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
843 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
844 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
845 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
846 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
847 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
848 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
849 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
850 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
851 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
852 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
853 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
854 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
855 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
856 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
857 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
858 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
859 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
860 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
861 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
862 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
863 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
864 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
865 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
866 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
867 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
868 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
869 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
870 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
871 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
872 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
873 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
874 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
875 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
876 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
877 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
878 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
879 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
880 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
881 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
882 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
883 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
884 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
885 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
886 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
887 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
888 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
889 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
890 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
891 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
892 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
893 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
894 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
895 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
896 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
897 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
898 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
899 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
900 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
901 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
902 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
903 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
904 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
905 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
906 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
907 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
908 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
909 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
910 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
911 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
912 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
913 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
914 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
915 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
916 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
917 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
918 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
919 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
920 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
921 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
922 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
923 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
924 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
925 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
931 assert(image != (Image *) NULL);
932 assert(image->signature == MagickCoreSignature);
933 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
935 profile=BlobToProfileStringInfo(
"icc",sRGBProfile,
sizeof(sRGBProfile),
937 (void) SetImageProfilePrivate(image,profile,exception);
940MagickExport MagickBooleanType ProfileImage(Image *image,
const char *name,
941 const void *datum,
const size_t length,ExceptionInfo *exception)
943#define ProfileImageTag "Profile/Image"
945 #define TYPE_XYZ_8 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(1))
947#define ThrowProfileException(severity,tag,context) \
949 if (profile != (StringInfo *) NULL) \
950 profile=DestroyStringInfo(profile); \
951 if (cms_context != (cmsContext) NULL) \
952 cmsDeleteContext(cms_context); \
953 if (source_info.profile != (cmsHPROFILE) NULL) \
954 (void) cmsCloseProfile(source_info.profile); \
955 if (target_info.profile != (cmsHPROFILE) NULL) \
956 (void) cmsCloseProfile(target_info.profile); \
957 ThrowBinaryException(severity,tag,context); \
966 assert(image != (Image *) NULL);
967 assert(image->signature == MagickCoreSignature);
968 assert(name != (
const char *) NULL);
969 if (IsEventLogging() != MagickFalse)
970 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
971 if ((datum == (
const void *) NULL) || (length == 0))
979 ResetImageProfileIterator(image);
980 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
982 if (IsOptionMember(next,name) != MagickFalse)
984 (void) DeleteImageProfile(image,next);
985 ResetImageProfileIterator(image);
987 next=GetNextImageProfile(image);
995 profile=AcquireProfileStringInfo(name,(
size_t) length,exception);
996 if (profile == (StringInfo *) NULL)
998 SetStringInfoDatum(profile,(
unsigned char *) datum);
999 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
1000 status=SetImageProfilePrivate(image,profile,exception);
1006 icc_profile=GetImageProfile(image,
"icc");
1007 if ((icc_profile != (
const StringInfo *) NULL) &&
1008 (CompareStringInfo(icc_profile,profile) == 0))
1013 value=GetImageProperty(image,
"exif:ColorSpace",exception);
1015 if (LocaleCompare(value,
"1") != 0)
1016 SetsRGBImageProfile(image,exception);
1017 value=GetImageProperty(image,
"exif:InteroperabilityIndex",exception);
1018 if (LocaleCompare(value,
"R98.") != 0)
1019 SetsRGBImageProfile(image,exception);
1020 icc_profile=GetImageProfile(image,
"icc");
1022 if ((icc_profile != (
const StringInfo *) NULL) &&
1023 (CompareStringInfo(icc_profile,profile) == 0))
1025 profile=DestroyStringInfo(profile);
1028#if !defined(MAGICKCORE_LCMS_DELEGATE)
1029 (void) ThrowMagickException(exception,GetMagickModule(),
1030 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
1031 "'%s' (LCMS)",image->filename);
1047 cms_exception.image=image;
1048 cms_exception.exception=exception;
1049 cms_context=cmsCreateContext(NULL,&cms_exception);
1050 if (cms_context == (cmsContext) NULL)
1052 profile=DestroyStringInfo(profile);
1053 ThrowBinaryException(ResourceLimitError,
1054 "ColorspaceColorProfileMismatch",name);
1056 cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
1057 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1058 GetStringInfoDatum(profile),(cmsUInt32Number)
1059 GetStringInfoLength(profile));
1060 if (source_info.profile == (cmsHPROFILE) NULL)
1062 profile=DestroyStringInfo(profile);
1063 cmsDeleteContext(cms_context);
1064 ThrowBinaryException(ResourceLimitError,
1065 "ColorspaceColorProfileMismatch",name);
1067 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
1068 (icc_profile == (StringInfo *) NULL))
1069 status=SetImageProfilePrivate(image,profile,exception);
1075 cmsColorSpaceSignature
1079 *magick_restrict transform;
1093 target_info.profile=(cmsHPROFILE) NULL;
1094 if (icc_profile != (StringInfo *) NULL)
1096 target_info.profile=source_info.profile;
1097 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1098 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1099 GetStringInfoLength(icc_profile));
1100 if (source_info.profile == (cmsHPROFILE) NULL)
1101 ThrowProfileException(ResourceLimitError,
1102 "ColorspaceColorProfileMismatch",name);
1105#if !defined(MAGICKCORE_HDRI_SUPPORT) || (MAGICKCORE_QUANTUM_DEPTH > 16)
1110 artifact=GetImageArtifact(image,
"profile:highres-transform");
1111 if (IsStringFalse(artifact) != MagickFalse)
1112 highres=MagickFalse;
1115 SetLCMSInfoScale(&source_info,1.0);
1116 SetLCMSInfoTranslate(&source_info,0.0);
1117 source_info.colorspace=sRGBColorspace;
1118 source_info.channels=3;
1119 switch (cmsGetColorSpace(source_info.profile))
1121 case cmsSigCmykData:
1123 source_info.colorspace=CMYKColorspace;
1124 source_info.channels=4;
1125 if (highres != MagickFalse)
1127 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1128 SetLCMSInfoScale(&source_info,100.0);
1130#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1132 source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1133#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1135 source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1139 case cmsSigGrayData:
1141 source_info.colorspace=GRAYColorspace;
1142 source_info.channels=1;
1143 if (highres != MagickFalse)
1144 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1145#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1147 source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1148#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1150 source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1156 source_info.colorspace=LabColorspace;
1157 if (highres != MagickFalse)
1159 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1160 source_info.scale[0]=100.0;
1161 source_info.scale[1]=255.0;
1162 source_info.scale[2]=255.0;
1163#if !defined(MAGICKCORE_HDRI_SUPPORT)
1164 source_info.translate[1]=(-0.5);
1165 source_info.translate[2]=(-0.5);
1168#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1170 source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1171#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1173 source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1179 source_info.colorspace=sRGBColorspace;
1180 if (highres != MagickFalse)
1181 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1182#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1184 source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1185#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1187 source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1193 source_info.colorspace=XYZColorspace;
1194 if (highres != MagickFalse)
1195 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1196#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1198 source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1199#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1201 source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1206 ThrowProfileException(ImageError,
1207 "ColorspaceColorProfileMismatch",name);
1209 signature=cmsGetPCS(source_info.profile);
1210 if (target_info.profile != (cmsHPROFILE) NULL)
1211 signature=cmsGetColorSpace(target_info.profile);
1212 SetLCMSInfoScale(&target_info,1.0);
1213 SetLCMSInfoTranslate(&target_info,0.0);
1214 target_info.channels=3;
1217 case cmsSigCmykData:
1219 target_info.colorspace=CMYKColorspace;
1220 target_info.channels=4;
1221 if (highres != MagickFalse)
1223 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1224 SetLCMSInfoScale(&target_info,0.01);
1226#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1228 target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1229#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1231 target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1235 case cmsSigGrayData:
1237 target_info.colorspace=GRAYColorspace;
1238 target_info.channels=1;
1239 if (highres != MagickFalse)
1240 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1241#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1243 target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1244#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1246 target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1252 target_info.colorspace=LabColorspace;
1253 if (highres != MagickFalse)
1255 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1256 target_info.scale[0]=0.01;
1257 target_info.scale[1]=1/255.0;
1258 target_info.scale[2]=1/255.0;
1259#if !defined(MAGICKCORE_HDRI_SUPPORT)
1260 target_info.translate[1]=0.5;
1261 target_info.translate[2]=0.5;
1264#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1266 target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1267#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1269 target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1275 target_info.colorspace=sRGBColorspace;
1276 if (highres != MagickFalse)
1277 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1278#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1280 target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1281#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1283 target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1289 target_info.colorspace=XYZColorspace;
1290 if (highres != MagickFalse)
1291 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1292#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1294 target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1295#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1297 source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1302 ThrowProfileException(ImageError,
1303 "ColorspaceColorProfileMismatch",name);
1305 switch (image->rendering_intent)
1307 case AbsoluteIntent:
1309 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1312 case PerceptualIntent:
1314 target_info.intent=INTENT_PERCEPTUAL;
1317 case RelativeIntent:
1319 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1322 case SaturationIntent:
1324 target_info.intent=INTENT_SATURATION;
1329 target_info.intent=INTENT_PERCEPTUAL;
1333 flags=cmsFLAGS_HIGHRESPRECALC;
1334#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1335 if (image->black_point_compensation != MagickFalse)
1336 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1338 transform=AcquireTransformTLS(&source_info,&target_info,flags,
1340 if (transform == (cmsHTRANSFORM *) NULL)
1341 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1346 source_info.pixels=AcquirePixelTLS(image->columns,
1347 source_info.channels,highres);
1348 target_info.pixels=AcquirePixelTLS(image->columns,
1349 target_info.channels,highres);
1350 if ((source_info.pixels == (
void **) NULL) ||
1351 (target_info.pixels == (
void **) NULL))
1353 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1354 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1355 transform=DestroyTransformTLS(transform);
1356 ThrowProfileException(ResourceLimitError,
1357 "MemoryAllocationFailed",image->filename);
1359 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1361 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1362 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1363 transform=DestroyTransformTLS(transform);
1364 if (source_info.profile != (cmsHPROFILE) NULL)
1365 (void) cmsCloseProfile(source_info.profile);
1366 if (target_info.profile != (cmsHPROFILE) NULL)
1367 (void) cmsCloseProfile(target_info.profile);
1368 return(MagickFalse);
1370 if (target_info.colorspace == CMYKColorspace)
1371 (void) SetImageColorspace(image,target_info.colorspace,exception);
1373 image_view=AcquireAuthenticCacheView(image,exception);
1374#if defined(MAGICKCORE_OPENMP_SUPPORT)
1375 #pragma omp parallel for schedule(static) shared(status) \
1376 magick_number_threads(image,image,image->rows,1)
1378 for (y=0; y < (ssize_t) image->rows; y++)
1381 id = GetOpenMPThreadId();
1389 if (status == MagickFalse)
1391 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1393 if (q == (Quantum *) NULL)
1398 if (highres != MagickFalse)
1399 TransformDoublePixels(
id,image,&source_info,&target_info,
1402 TransformQuantumPixels(
id,image,&source_info,&target_info,
1404 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1405 if (sync == MagickFalse)
1407 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1412#if defined(MAGICKCORE_OPENMP_SUPPORT)
1416 proceed=SetImageProgress(image,ProfileImageTag,progress,
1418 if (proceed == MagickFalse)
1422 image_view=DestroyCacheView(image_view);
1423 (void) SetImageColorspace(image,target_info.colorspace,exception);
1428 image->type=image->alpha_trait == UndefinedPixelTrait ?
1429 TrueColorType : TrueColorAlphaType;
1432 case cmsSigCmykData:
1434 image->type=image->alpha_trait == UndefinedPixelTrait ?
1435 ColorSeparationType : ColorSeparationAlphaType;
1438 case cmsSigGrayData:
1440 image->type=image->alpha_trait == UndefinedPixelTrait ?
1441 GrayscaleType : GrayscaleAlphaType;
1447 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1448 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1449 transform=DestroyTransformTLS(transform);
1450 if ((status != MagickFalse) &&
1451 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1452 status=SetImageProfilePrivate(image,profile,exception);
1453 if (target_info.profile != (cmsHPROFILE) NULL)
1454 (void) cmsCloseProfile(target_info.profile);
1456 (void) cmsCloseProfile(source_info.profile);
1457 cmsDeleteContext(cms_context);
1489MagickExport StringInfo *RemoveImageProfile(Image *image,
const char *name)
1494 assert(image != (Image *) NULL);
1495 assert(image->signature == MagickCoreSignature);
1496 if (IsEventLogging() != MagickFalse)
1497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1498 if (image->profiles == (SplayTreeInfo *) NULL)
1499 return((StringInfo *) NULL);
1500 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1501 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1502 image->profiles,name);
1530MagickExport
void ResetImageProfileIterator(
const Image *image)
1532 assert(image != (Image *) NULL);
1533 assert(image->signature == MagickCoreSignature);
1534 if (IsEventLogging() != MagickFalse)
1535 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1536 if (image->profiles == (SplayTreeInfo *) NULL)
1538 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1572static void *DestroyProfile(
void *profile)
1574 return((
void *) DestroyStringInfo((StringInfo *) profile));
1577static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1578 unsigned char *quantum)
1584static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1585 unsigned int *quantum)
1587 *quantum=(
unsigned int) (*p++) << 24;
1588 *quantum|=(
unsigned int) (*p++) << 16;
1589 *quantum|=(
unsigned int) (*p++) << 8;
1590 *quantum|=(
unsigned int) (*p++);
1594static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1595 unsigned short *quantum)
1597 *quantum=(
unsigned short) (*p++) << 8;
1598 *quantum|=(
unsigned short) (*p++);
1602static inline void WriteResourceLong(
unsigned char *p,
1603 const unsigned int quantum)
1608 buffer[0]=(
unsigned char) (quantum >> 24);
1609 buffer[1]=(
unsigned char) (quantum >> 16);
1610 buffer[2]=(
unsigned char) (quantum >> 8);
1611 buffer[3]=(
unsigned char) quantum;
1612 (void) memcpy(p,buffer,4);
1615static void WriteTo8BimProfile(Image *image,
const char *name,
1616 const StringInfo *profile)
1644 if (LocaleCompare(name,
"icc") == 0)
1647 if (LocaleCompare(name,
"iptc") == 0)
1650 if (LocaleCompare(name,
"xmp") == 0)
1654 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1655 image->profiles,
"8bim");
1656 if (profile_8bim == (StringInfo *) NULL)
1658 datum=GetStringInfoDatum(profile_8bim);
1659 length=GetStringInfoLength(profile_8bim);
1660 for (p=datum; p < (datum+length-16); )
1663 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1666 p=ReadResourceShort(p,&
id);
1667 p=ReadResourceByte(p,&length_byte);
1668 p+=(ptrdiff_t) length_byte;
1669 if (((length_byte+1) & 0x01) != 0)
1671 if (p > (datum+length-4))
1673 p=ReadResourceLong(p,&value);
1674 count=(ssize_t) value;
1675 if ((count & 0x01) != 0)
1677 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1679 if (
id != profile_id)
1680 p+=(ptrdiff_t) count;
1694 extent=(size_t) ((datum+length)-(p+count));
1695 if (profile == (StringInfo *) NULL)
1697 offset=(size_t) (q-datum);
1698 extract_profile=AcquireStringInfo(offset+extent);
1699 (void) memcpy(extract_profile->datum,datum,offset);
1703 offset=(size_t) (p-datum);
1704 extract_extent=(ssize_t) profile->length;
1705 if ((extract_extent & 0x01) != 0)
1707 extract_profile=AcquireStringInfo(offset+(
size_t) extract_extent+
1709 (void) memcpy(extract_profile->datum,datum,offset-4);
1710 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1712 (void) memcpy(extract_profile->datum+offset,
1713 profile->datum,profile->length);
1715 (void) memcpy(extract_profile->datum+offset+extract_extent,
1717 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1718 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1719 extract_profile=DestroyStringInfo(extract_profile);
1725static void GetProfilesFromResourceBlock(Image *image,
1726 const StringInfo *resource_block,ExceptionInfo *exception)
1752 datum=GetStringInfoDatum(resource_block);
1753 length=GetStringInfoLength(resource_block);
1754 for (p=datum; p < (datum+length-16); )
1756 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1759 p=ReadResourceShort(p,&
id);
1760 p=ReadResourceByte(p,&length_byte);
1761 p+=(ptrdiff_t) length_byte;
1762 if (((length_byte+1) & 0x01) != 0)
1764 if (p > (datum+length-4))
1766 p=ReadResourceLong(p,&value);
1767 count=(ssize_t) value;
1768 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1786 p=ReadResourceLong(p,&resolution);
1787 image->resolution.x=((double) resolution)/65536.0;
1788 p=ReadResourceShort(p,&units)+2;
1789 p=ReadResourceLong(p,&resolution)+4;
1790 image->resolution.y=((double) resolution)/65536.0;
1794 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1795 image->units=PixelsPerInchResolution;
1798 image->units=PixelsPerCentimeterResolution;
1799 image->resolution.x/=2.54;
1800 image->resolution.y/=2.54;
1809 profile=BlobToProfileStringInfo(
"iptc",p,(
size_t) count,exception);
1810 if (profile != (StringInfo *) NULL)
1811 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1812 profile,MagickTrue,exception);
1813 p+=(ptrdiff_t) count;
1821 p+=(ptrdiff_t) count;
1829 profile=BlobToProfileStringInfo(
"icc",p,(
size_t) count,exception);
1830 if (profile != (StringInfo *) NULL)
1831 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1832 profile,MagickTrue,exception);
1833 p+=(ptrdiff_t) count;
1841 profile=BlobToProfileStringInfo(
"exif",p,(
size_t) count,exception);
1842 if (profile != (StringInfo *) NULL)
1843 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1844 profile,MagickTrue,exception);
1845 p+=(ptrdiff_t) count;
1853 profile=BlobToProfileStringInfo(
"xmp",p,(
size_t) count,exception);
1854 if (profile != (StringInfo *) NULL)
1855 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1856 profile,MagickTrue,exception);
1857 p+=(ptrdiff_t) count;
1862 p+=(ptrdiff_t) count;
1866 if ((count & 0x01) != 0)
1871static void PatchCorruptProfile(
const char *name,StringInfo *profile)
1882 if (LocaleCompare(name,
"xmp") == 0)
1887 p=GetStringInfoDatum(profile);
1888 p=(
unsigned char *) strstr((
const char *) p,
"<?xpacket end=\"w\"?>");
1889 if (p != (
unsigned char *) NULL)
1892 length=(size_t) (p-GetStringInfoDatum(profile));
1893 if (length != GetStringInfoLength(profile))
1896 SetStringInfoLength(profile,length);
1901 if (((LocaleCompare(name,
"exif") == 0) || (LocaleCompare(name,
"app1") == 0)) &&
1902 (GetStringInfoLength(profile) > 2))
1907 p=GetStringInfoDatum(profile);
1908 if ((LocaleNCompare((
const char *) p,
"MM",2) == 0) ||
1909 (LocaleNCompare((
const char *) p,
"II",2) == 0))
1912 profile_start[] =
"Exif\0\0";
1917 exif_profile=AcquireStringInfo(6);
1918 if (exif_profile != (StringInfo *) NULL)
1920 SetStringInfoDatum(exif_profile,profile_start);
1921 ConcatenateStringInfo(exif_profile,profile);
1922 SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
1923 SetStringInfo(profile,exif_profile);
1924 exif_profile=DestroyStringInfo(exif_profile);
1930static MagickBooleanType ValidateXMPProfile(Image *image,
1931 const StringInfo *profile,ExceptionInfo *exception)
1933#if defined(MAGICKCORE_XML_DELEGATE)
1940 const char *artifact=GetImageArtifact(image,
"xmp:validate");
1941 if (IsStringTrue(artifact) == MagickFalse)
1943 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1944 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1945 XML_PARSE_NOWARNING);
1946 if (document == (xmlDocPtr) NULL)
1948 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
1949 "CorruptImageProfile",
"`%s' (XMP)",image->filename);
1950 return(MagickFalse);
1952 xmlFreeDoc(document);
1956 (void) ThrowMagickException(exception,GetMagickModule(),
1957 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (XML)",
1959 return(MagickFalse);
1963static MagickBooleanType SetImageProfileInternal(Image *image,
const char *name,
1964 StringInfo *profile,
const MagickBooleanType recursive,
1965 ExceptionInfo *exception)
1968 key[MagickPathExtent];
1976 assert(image != (Image *) NULL);
1977 assert(image->signature == MagickCoreSignature);
1978 assert(profile != (StringInfo *) NULL);
1979 assert(name != (
const char *) NULL);
1980 if (IsEventLogging() != MagickFalse)
1981 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1982 length=GetStringInfoLength(profile);
1983 if ((length == 0) || (length > GetMaxProfileSize()))
1986 (void) ThrowMagickException(exception,GetMagickModule(),
1987 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
1988 (
unsigned long long) length);
1989 profile=DestroyStringInfo(profile);
1992 PatchCorruptProfile(name,profile);
1993 if ((LocaleCompare(name,
"xmp") == 0) &&
1994 (ValidateXMPProfile(image,profile,exception) == MagickFalse))
1996 profile=DestroyStringInfo(profile);
1999 if (image->profiles == (SplayTreeInfo *) NULL)
2000 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
2002 (void) CopyMagickString(key,name,MagickPathExtent);
2008 if ((length > 4) && (LocaleCompare(key,
"app1") == 0) &&
2009 (LocaleNCompare((
const char *) GetStringInfoDatum(profile),
"exif",4) == 0))
2010 (void) CopyMagickString(key,
"exif",MagickPathExtent);
2013 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
2014 ConstantString(key),profile);
2015 if (status == MagickFalse)
2016 profile=DestroyStringInfo(profile);
2019 if (LocaleCompare(key,
"8bim") == 0)
2020 GetProfilesFromResourceBlock(image,profile,exception);
2022 if (recursive == MagickFalse)
2023 WriteTo8BimProfile(image,key,profile);
2028MagickExport StringInfo *AcquireProfileStringInfo(
const char *name,
2029 const size_t length,ExceptionInfo *exception)
2032 *profile = (StringInfo *) NULL;
2034 if (length > GetMaxProfileSize())
2035 (void) ThrowMagickException(exception,GetMagickModule(),
2036 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
2037 (
unsigned long long) length);
2040 profile=AcquireStringInfo(length);
2041 SetStringInfoName(profile,name);
2046MagickExport StringInfo *BlobToProfileStringInfo(
const char *name,
2047 const void *blob,
const size_t length,ExceptionInfo *exception)
2052 profile=AcquireProfileStringInfo(name,length,exception);
2053 if (profile != (
const StringInfo *) NULL)
2054 (void) memcpy(profile->datum,blob,length);
2058MagickExport MagickBooleanType SetImageProfile(Image *image,
const char *name,
2059 const StringInfo *profile,ExceptionInfo *exception)
2064 if (profile == (
const StringInfo *) NULL)
2065 return(MagickFalse);
2066 clone_profile=CloneStringInfo(profile);
2067 return(SetImageProfileInternal(image,name,clone_profile,MagickFalse,
2071MagickExport MagickBooleanType SetImageProfilePrivate(Image *image,
2072 StringInfo *profile,ExceptionInfo *exception)
2074 if (profile == (
const StringInfo *) NULL)
2075 return(MagickFalse);
2076 return(SetImageProfileInternal(image,GetStringInfoName(profile),profile,
2077 MagickFalse,exception));
2103static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
2115static inline signed short ReadProfileShort(
const EndianType endian,
2116 unsigned char *buffer)
2130 if (endian == LSBEndian)
2132 value=(
unsigned short) buffer[1] << 8;
2133 value|=(
unsigned short) buffer[0];
2134 quantum.unsigned_value=value & 0xffff;
2135 return((
signed short) quantum.signed_value);
2137 value=(
unsigned short) buffer[0] << 8;
2138 value|=(
unsigned short) buffer[1];
2139 quantum.unsigned_value=value & 0xffff;
2140 return((
signed short) quantum.signed_value);
2143static inline signed int ReadProfileLong(
const EndianType endian,
2144 unsigned char *buffer)
2158 if (endian == LSBEndian)
2160 value=(
unsigned int) buffer[3] << 24;
2161 value|=(
unsigned int) buffer[2] << 16;
2162 value|=(
unsigned int) buffer[1] << 8;
2163 value|=(
unsigned int) buffer[0];
2164 quantum.unsigned_value=value & 0xffffffff;
2165 return(quantum.signed_value);
2167 value=(
unsigned int) buffer[0] << 24;
2168 value|=(
unsigned int) buffer[1] << 16;
2169 value|=(
unsigned int) buffer[2] << 8;
2170 value|=(
unsigned int) buffer[3];
2171 quantum.unsigned_value=value & 0xffffffff;
2172 return(quantum.signed_value);
2175static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
2182 value=ReadProfileLong(MSBEndian,*p);
2188static inline signed short ReadProfileMSBShort(
unsigned char **p,
2196 value=ReadProfileShort(MSBEndian,*p);
2202static inline void WriteProfileLong(
const EndianType endian,
2203 const size_t value,
unsigned char *p)
2208 if (endian == LSBEndian)
2210 buffer[0]=(
unsigned char) value;
2211 buffer[1]=(
unsigned char) (value >> 8);
2212 buffer[2]=(
unsigned char) (value >> 16);
2213 buffer[3]=(
unsigned char) (value >> 24);
2214 (void) memcpy(p,buffer,4);
2217 buffer[0]=(
unsigned char) (value >> 24);
2218 buffer[1]=(
unsigned char) (value >> 16);
2219 buffer[2]=(
unsigned char) (value >> 8);
2220 buffer[3]=(
unsigned char) value;
2221 (void) memcpy(p,buffer,4);
2224static void WriteProfileShort(
const EndianType endian,
2225 const unsigned short value,
unsigned char *p)
2230 if (endian == LSBEndian)
2232 buffer[0]=(
unsigned char) value;
2233 buffer[1]=(
unsigned char) (value >> 8);
2234 (void) memcpy(p,buffer,2);
2237 buffer[0]=(
unsigned char) (value >> 8);
2238 buffer[1]=(
unsigned char) value;
2239 (void) memcpy(p,buffer,2);
2242static void SyncExifProfile(
const Image *image,
unsigned char *exif,
2245#define MaxDirectoryStack 16
2246#define EXIF_DELIMITER "\n"
2247#define EXIF_NUM_FORMATS 12
2248#define TAG_EXIF_OFFSET 0x8769
2249#define TAG_INTEROP_OFFSET 0xa005
2251 typedef struct _DirectoryInfo
2261 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
2279 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2286 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2287 if ((
id != 0x4949) && (
id != 0x4D4D))
2291 if (ReadProfileByte(&exif,&length) != 0x45)
2293 if (ReadProfileByte(&exif,&length) != 0x78)
2295 if (ReadProfileByte(&exif,&length) != 0x69)
2297 if (ReadProfileByte(&exif,&length) != 0x66)
2299 if (ReadProfileByte(&exif,&length) != 0x00)
2301 if (ReadProfileByte(&exif,&length) != 0x00)
2307 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2317 if (ReadProfileShort(endian,exif+2) != 0x002a)
2322 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2323 if ((offset < 0) || ((
size_t) offset >= length))
2325 directory=exif+offset;
2328 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2329 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2335 directory=directory_stack[level].directory;
2336 entry=directory_stack[level].entry;
2338 if ((directory < exif) || (directory > (exif+length-2)))
2343 number_entries=(size_t) ReadProfileShort(endian,directory);
2344 for ( ; entry < number_entries; entry++)
2360 q=(
unsigned char *) (directory+2+(12*entry));
2361 if (q > (exif+length-12))
2363 if (GetValueFromSplayTree(exif_resources,q) == q)
2365 (void) AddValueToSplayTree(exif_resources,q,q);
2366 tag_value=(ssize_t) ReadProfileShort(endian,q);
2367 format=(ssize_t) ReadProfileShort(endian,q+2);
2368 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2370 components=(int) ReadProfileLong(endian,q+4);
2373 number_bytes=(size_t) components*(
size_t) format_bytes[format];
2374 if ((ssize_t) number_bytes < components)
2376 if (number_bytes <= 4)
2383 offset=(ssize_t) ReadProfileLong(endian,q+8);
2385 ((
size_t) (offset+(ssize_t) number_bytes) > length))
2387 if (~length < number_bytes)
2389 p=(
unsigned char *) (exif+offset);
2395 (void) WriteProfileLong(endian,(
size_t) (image->resolution.x+0.5),p);
2396 if (number_bytes == 8)
2397 (void) WriteProfileLong(endian,1UL,p+4);
2402 (void) WriteProfileLong(endian,(
size_t) (image->resolution.y+0.5),p);
2403 if (number_bytes == 8)
2404 (void) WriteProfileLong(endian,1UL,p+4);
2409 if (number_bytes == 4)
2411 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2414 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2420 if (number_bytes == 4)
2422 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2425 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2431 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2433 offset=(ssize_t) ReadProfileLong(endian,p);
2434 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2436 directory_stack[level].directory=directory;
2438 directory_stack[level].entry=entry;
2440 directory_stack[level].directory=exif+offset;
2441 directory_stack[level].entry=0;
2443 if ((directory+2+(12*number_entries)) > (exif+length))
2445 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2447 if ((offset != 0) && ((
size_t) offset < length) &&
2448 (level < (MaxDirectoryStack-2)))
2450 directory_stack[level].directory=exif+offset;
2451 directory_stack[level].entry=0;
2458 }
while (level > 0);
2459 exif_resources=DestroySplayTree(exif_resources);
2463static void Sync8BimProfile(
const Image *image,
const StringInfo *profile)
2477 length=GetStringInfoLength(profile);
2478 p=GetStringInfoDatum(profile);
2481 if (ReadProfileByte(&p,&length) != 0x38)
2483 if (ReadProfileByte(&p,&length) != 0x42)
2485 if (ReadProfileByte(&p,&length) != 0x49)
2487 if (ReadProfileByte(&p,&length) != 0x4D)
2491 id=(
unsigned short) ReadProfileMSBShort(&p,&length);
2492 count=(ssize_t) ReadProfileByte(&p,&length);
2493 if ((count >= (ssize_t) length) || (count < 0))
2495 p+=(ptrdiff_t) count;
2496 length-=(size_t) count;
2497 if ((*p & 0x01) == 0)
2498 (void) ReadProfileByte(&p,&length);
2499 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2500 if ((count > (ssize_t) length) || (count < 0))
2502 if ((
id == 0x3ED) && (count == 16))
2504 if (image->units == PixelsPerCentimeterResolution)
2505 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2506 image->resolution.x*2.54*65536.0),p);
2508 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2509 image->resolution.x*65536.0),p);
2510 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2511 if (image->units == PixelsPerCentimeterResolution)
2512 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2513 image->resolution.y*2.54*65536.0),p+8);
2515 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2516 image->resolution.y*65536.0),p+8);
2517 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2520 SyncExifProfile(image,p,(
size_t) count);
2521 p+=(ptrdiff_t) count;
2522 length-=(size_t) count;
2527static void ReplaceXmpValue(StringInfo *profile,
size_t start,
size_t end,
2538 length=GetStringInfoLength(profile);
2539 value_length=strlen(value);
2540 new_length=length-(end-start)+value_length;
2541 if (new_length > length)
2542 SetStringInfoLength(profile,new_length);
2543 datum=(
char *) GetStringInfoDatum(profile);
2544 (void) memmove(datum+start+value_length,datum+end,length-end);
2545 (void) memcpy(datum+start,value,value_length);
2546 if (new_length < length)
2548 SetStringInfoLength(profile,new_length);
2549 datum=(
char *) GetStringInfoDatum(profile);
2550 *(datum+new_length)=
'\0';
2554static MagickBooleanType GetXmpOffsets(
const StringInfo *profile,
2555 const char *tag,
size_t *start,
size_t *end)
2565 datum=(
char *) GetStringInfoDatum(profile);
2566 length=GetStringInfoLength(profile);
2567 pos=strstr(datum,tag);
2568 tag_length=strlen(tag);
2569 if ((pos == (
char *) NULL) || ((pos-datum) < 1) || (*(pos-1) !=
'<') ||
2570 (((
size_t) (pos-datum)+tag_length) > length) ||
2571 (*(pos+tag_length) !=
'>'))
2572 return(MagickFalse);
2573 *start=(size_t) (pos-datum)+tag_length+1;
2574 pos=strstr(datum+*start,
"<");
2575 if (pos == (
char *) NULL)
2576 return(MagickFalse);
2577 *end=(size_t) (pos-datum);
2581static void GetXmpNumeratorAndDenominator(
double value,
2582 unsigned long *numerator,
unsigned long *denominator)
2589 if (value <= MagickEpsilon)
2591 if (value > (
double) MAGICK_ULONG_MAX)
2593 *numerator = MAGICK_ULONG_MAX;
2597 if (floor(value) == value)
2599 *numerator = (
unsigned long) value;
2605 while(fabs(df - value) > MagickEpsilon)
2612 *numerator=(
unsigned long) (value*(*denominator));
2614 df=*numerator/(double)*denominator;
2618static void SyncXmpProfile(
const Image *image,StringInfo *profile)
2621 value[MagickPathExtent];
2632 if (GetXmpOffsets(profile,
"tiff:XResolution",&start,&end) != MagickFalse)
2634 GetXmpNumeratorAndDenominator(image->resolution.x,&numerator,
2636 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",numerator,
2638 ReplaceXmpValue(profile,start,end,value);
2640 if (GetXmpOffsets(profile,
"tiff:YResolution",&start,&end) != MagickFalse)
2642 if ((fabs(image->resolution.x-image->resolution.y) > MagickEpsilon) ||
2645 GetXmpNumeratorAndDenominator(image->resolution.y,&numerator,
2647 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",
2648 numerator,denominator);
2650 ReplaceXmpValue(profile,start,end,value);
2652 if (GetXmpOffsets(profile,
"tiff:ResolutionUnit",&start,&end) != MagickFalse)
2654 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2655 ((
int) image->units)+1);
2656 ReplaceXmpValue(profile,start,end,value);
2658 if (GetXmpOffsets(profile,
"tiff:Orientation",&start,&end) != MagickFalse)
2660 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2661 (
int) image->orientation);
2662 ReplaceXmpValue(profile,start,end,value);
2666MagickPrivate
void SyncImageProfiles(Image *image)
2671 profile=(StringInfo *) GetImageProfile(image,
"8BIM");
2672 if (profile != (StringInfo *) NULL)
2673 Sync8BimProfile(image,profile);
2674 profile=(StringInfo *) GetImageProfile(image,
"EXIF");
2675 if (profile != (StringInfo *) NULL)
2676 SyncExifProfile(image,GetStringInfoDatum(profile),GetStringInfoLength(
2678 profile=(StringInfo *) GetImageProfile(image,
"XMP");
2679 if (profile != (StringInfo *) NULL)
2680 SyncXmpProfile(image,profile);
2683static void UpdateClipPath(
unsigned char *blob,
size_t length,
2684 const size_t old_columns,
const size_t old_rows,
2685 const RectangleInfo *new_geometry)
2695 selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2701 if (knot_count != 0)
2704 length-=(size_t) MagickMin(length,24U);
2710 knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2712 length-=(size_t) MagickMin(length,22);
2720 if (knot_count == 0)
2726 length-=(size_t) MagickMin(length,24);
2732 for (i=0; i < 3; i++)
2742 y=(double) ReadProfileMSBLong(&blob,&length);
2743 y=y*old_rows/4096.0/4096.0;
2745 yy=(
signed int) ((y*4096*4096)/new_geometry->height);
2746 WriteProfileLong(MSBEndian,(
size_t) yy,blob-4);
2747 x=(double) ReadProfileMSBLong(&blob,&length);
2748 x=x*old_columns/4096.0/4096.0;
2750 xx=(
signed int) ((x*4096*4096)/new_geometry->width);
2751 WriteProfileLong(MSBEndian,(
size_t) xx,blob-4);
2762 length-=(size_t) MagickMin(length,24);
2769MagickPrivate
void Update8BIMClipPath(
const Image *image,
2770 const size_t old_columns,
const size_t old_rows,
2771 const RectangleInfo *new_geometry)
2786 assert(image != (Image *) NULL);
2787 assert(new_geometry != (RectangleInfo *) NULL);
2788 profile=GetImageProfile(image,
"8bim");
2789 if (profile == (StringInfo *) NULL)
2791 length=GetStringInfoLength(profile);
2792 info=GetStringInfoDatum(profile);
2795 if (ReadProfileByte(&info,&length) != (
unsigned char)
'8')
2797 if (ReadProfileByte(&info,&length) != (
unsigned char)
'B')
2799 if (ReadProfileByte(&info,&length) != (
unsigned char)
'I')
2801 if (ReadProfileByte(&info,&length) != (
unsigned char)
'M')
2803 id=(ssize_t) ReadProfileMSBShort(&info,&length);
2804 count=(ssize_t) ReadProfileByte(&info,&length);
2805 if ((count != 0) && ((
size_t) count <= length))
2808 length-=(size_t) count;
2810 if ((count & 0x01) == 0)
2811 (void) ReadProfileByte(&info,&length);
2812 count=(ssize_t) ReadProfileMSBLong(&info,&length);
2813 if ((count < 0) || ((
size_t) count > length))
2818 if ((
id > 1999) && (
id < 2999))
2819 UpdateClipPath(info,(
size_t) count,old_columns,old_rows,new_geometry);
2821 length-=(size_t) MagickMin(length,(
size_t) count);