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);
1454 profile=DestroyStringInfo(profile);
1455 if (target_info.profile != (cmsHPROFILE) NULL)
1456 (void) cmsCloseProfile(target_info.profile);
1458 (void) cmsCloseProfile(source_info.profile);
1459 cmsDeleteContext(cms_context);
1491MagickExport StringInfo *RemoveImageProfile(Image *image,
const char *name)
1496 assert(image != (Image *) NULL);
1497 assert(image->signature == MagickCoreSignature);
1498 if (IsEventLogging() != MagickFalse)
1499 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1500 if (image->profiles == (SplayTreeInfo *) NULL)
1501 return((StringInfo *) NULL);
1502 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1503 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1504 image->profiles,name);
1532MagickExport
void ResetImageProfileIterator(
const Image *image)
1534 assert(image != (Image *) NULL);
1535 assert(image->signature == MagickCoreSignature);
1536 if (IsEventLogging() != MagickFalse)
1537 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1538 if (image->profiles == (SplayTreeInfo *) NULL)
1540 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1574static void *DestroyProfile(
void *profile)
1576 return((
void *) DestroyStringInfo((StringInfo *) profile));
1579static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1580 unsigned char *quantum)
1586static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1587 unsigned int *quantum)
1589 *quantum=(
unsigned int) (*p++) << 24;
1590 *quantum|=(
unsigned int) (*p++) << 16;
1591 *quantum|=(
unsigned int) (*p++) << 8;
1592 *quantum|=(
unsigned int) (*p++);
1596static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1597 unsigned short *quantum)
1599 *quantum=(
unsigned short) (*p++) << 8;
1600 *quantum|=(
unsigned short) (*p++);
1604static inline void WriteResourceLong(
unsigned char *p,
1605 const unsigned int quantum)
1610 buffer[0]=(
unsigned char) (quantum >> 24);
1611 buffer[1]=(
unsigned char) (quantum >> 16);
1612 buffer[2]=(
unsigned char) (quantum >> 8);
1613 buffer[3]=(
unsigned char) quantum;
1614 (void) memcpy(p,buffer,4);
1617static void WriteTo8BimProfile(Image *image,
const char *name,
1618 const StringInfo *profile)
1646 if (LocaleCompare(name,
"icc") == 0)
1649 if (LocaleCompare(name,
"iptc") == 0)
1652 if (LocaleCompare(name,
"xmp") == 0)
1656 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1657 image->profiles,
"8bim");
1658 if (profile_8bim == (StringInfo *) NULL)
1660 datum=GetStringInfoDatum(profile_8bim);
1661 length=GetStringInfoLength(profile_8bim);
1662 for (p=datum; p < (datum+length-16); )
1665 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1668 p=ReadResourceShort(p,&
id);
1669 p=ReadResourceByte(p,&length_byte);
1670 p+=(ptrdiff_t) length_byte;
1671 if (((length_byte+1) & 0x01) != 0)
1673 if (p > (datum+length-4))
1675 p=ReadResourceLong(p,&value);
1676 count=(ssize_t) value;
1677 if ((count & 0x01) != 0)
1679 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1681 if (
id != profile_id)
1682 p+=(ptrdiff_t) count;
1696 extent=(size_t) ((datum+length)-(p+count));
1697 if (profile == (StringInfo *) NULL)
1699 offset=(size_t) (q-datum);
1700 extract_profile=AcquireStringInfo(offset+extent);
1701 (void) memcpy(extract_profile->datum,datum,offset);
1705 offset=(size_t) (p-datum);
1706 extract_extent=(ssize_t) profile->length;
1707 if ((extract_extent & 0x01) != 0)
1709 extract_profile=AcquireStringInfo(offset+(
size_t) extract_extent+
1711 (void) memcpy(extract_profile->datum,datum,offset-4);
1712 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1714 (void) memcpy(extract_profile->datum+offset,
1715 profile->datum,profile->length);
1717 (void) memcpy(extract_profile->datum+offset+extract_extent,
1719 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1720 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1721 extract_profile=DestroyStringInfo(extract_profile);
1727static void GetProfilesFromResourceBlock(Image *image,
1728 const StringInfo *resource_block,ExceptionInfo *exception)
1754 datum=GetStringInfoDatum(resource_block);
1755 length=GetStringInfoLength(resource_block);
1756 for (p=datum; p < (datum+length-16); )
1758 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1761 p=ReadResourceShort(p,&
id);
1762 p=ReadResourceByte(p,&length_byte);
1763 p+=(ptrdiff_t) length_byte;
1764 if (((length_byte+1) & 0x01) != 0)
1766 if (p > (datum+length-4))
1768 p=ReadResourceLong(p,&value);
1769 count=(ssize_t) value;
1770 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1788 p=ReadResourceLong(p,&resolution);
1789 image->resolution.x=((double) resolution)/65536.0;
1790 p=ReadResourceShort(p,&units)+2;
1791 p=ReadResourceLong(p,&resolution)+4;
1792 image->resolution.y=((double) resolution)/65536.0;
1796 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1797 image->units=PixelsPerInchResolution;
1800 image->units=PixelsPerCentimeterResolution;
1801 image->resolution.x/=2.54;
1802 image->resolution.y/=2.54;
1811 profile=BlobToProfileStringInfo(
"iptc",p,(
size_t) count,exception);
1812 if (profile != (StringInfo *) NULL)
1813 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1814 profile,MagickTrue,exception);
1815 p+=(ptrdiff_t) count;
1823 p+=(ptrdiff_t) count;
1831 profile=BlobToProfileStringInfo(
"icc",p,(
size_t) count,exception);
1832 if (profile != (StringInfo *) NULL)
1833 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1834 profile,MagickTrue,exception);
1835 p+=(ptrdiff_t) count;
1843 profile=BlobToProfileStringInfo(
"exif",p,(
size_t) count,exception);
1844 if (profile != (StringInfo *) NULL)
1845 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1846 profile,MagickTrue,exception);
1847 p+=(ptrdiff_t) count;
1855 profile=BlobToProfileStringInfo(
"xmp",p,(
size_t) count,exception);
1856 if (profile != (StringInfo *) NULL)
1857 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1858 profile,MagickTrue,exception);
1859 p+=(ptrdiff_t) count;
1864 p+=(ptrdiff_t) count;
1868 if ((count & 0x01) != 0)
1873static void PatchCorruptProfile(
const char *name,StringInfo *profile)
1884 if (LocaleCompare(name,
"xmp") == 0)
1889 p=GetStringInfoDatum(profile);
1890 p=(
unsigned char *) strstr((
const char *) p,
"<?xpacket end=\"w\"?>");
1891 if (p != (
unsigned char *) NULL)
1894 length=(size_t) (p-GetStringInfoDatum(profile));
1895 if (length != GetStringInfoLength(profile))
1898 SetStringInfoLength(profile,length);
1903 if (((LocaleCompare(name,
"exif") == 0) || (LocaleCompare(name,
"app1") == 0)) &&
1904 (GetStringInfoLength(profile) > 2))
1909 p=GetStringInfoDatum(profile);
1910 if ((LocaleNCompare((
const char *) p,
"MM",2) == 0) ||
1911 (LocaleNCompare((
const char *) p,
"II",2) == 0))
1914 profile_start[] =
"Exif\0\0";
1919 exif_profile=AcquireStringInfo(6);
1920 if (exif_profile != (StringInfo *) NULL)
1922 SetStringInfoDatum(exif_profile,profile_start);
1923 ConcatenateStringInfo(exif_profile,profile);
1924 SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
1925 SetStringInfo(profile,exif_profile);
1926 exif_profile=DestroyStringInfo(exif_profile);
1932static MagickBooleanType ValidateXMPProfile(Image *image,
1933 const StringInfo *profile,ExceptionInfo *exception)
1935#if defined(MAGICKCORE_XML_DELEGATE)
1942 const char *artifact=GetImageArtifact(image,
"xmp:validate");
1943 if (IsStringTrue(artifact) == MagickFalse)
1945 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1946 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1947 XML_PARSE_NOWARNING);
1948 if (document == (xmlDocPtr) NULL)
1950 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
1951 "CorruptImageProfile",
"`%s' (XMP)",image->filename);
1952 return(MagickFalse);
1954 xmlFreeDoc(document);
1958 (void) ThrowMagickException(exception,GetMagickModule(),
1959 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (XML)",
1961 return(MagickFalse);
1965static MagickBooleanType SetImageProfileInternal(Image *image,
const char *name,
1966 StringInfo *profile,
const MagickBooleanType recursive,
1967 ExceptionInfo *exception)
1970 key[MagickPathExtent];
1978 assert(image != (Image *) NULL);
1979 assert(image->signature == MagickCoreSignature);
1980 assert(profile != (StringInfo *) NULL);
1981 assert(name != (
const char *) NULL);
1982 if (IsEventLogging() != MagickFalse)
1983 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1984 length=GetStringInfoLength(profile);
1985 if ((length == 0) || (length > GetMaxProfileSize()))
1988 (void) ThrowMagickException(exception,GetMagickModule(),
1989 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
1990 (
unsigned long long) length);
1991 profile=DestroyStringInfo(profile);
1994 PatchCorruptProfile(name,profile);
1995 if ((LocaleCompare(name,
"xmp") == 0) &&
1996 (ValidateXMPProfile(image,profile,exception) == MagickFalse))
1998 profile=DestroyStringInfo(profile);
2001 if (image->profiles == (SplayTreeInfo *) NULL)
2002 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
2004 (void) CopyMagickString(key,name,MagickPathExtent);
2010 if ((length > 4) && (LocaleCompare(key,
"app1") == 0) &&
2011 (LocaleNCompare((
const char *) GetStringInfoDatum(profile),
"exif",4) == 0))
2012 (void) CopyMagickString(key,
"exif",MagickPathExtent);
2015 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
2016 ConstantString(key),profile);
2017 if (status == MagickFalse)
2018 profile=DestroyStringInfo(profile);
2021 if (LocaleCompare(key,
"8bim") == 0)
2022 GetProfilesFromResourceBlock(image,profile,exception);
2024 if (recursive == MagickFalse)
2025 WriteTo8BimProfile(image,key,profile);
2030MagickExport StringInfo *AcquireProfileStringInfo(
const char *name,
2031 const size_t length,ExceptionInfo *exception)
2034 *profile = (StringInfo *) NULL;
2036 if (length > GetMaxProfileSize())
2037 (void) ThrowMagickException(exception,GetMagickModule(),
2038 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
2039 (
unsigned long long) length);
2042 profile=AcquireStringInfo(length);
2043 SetStringInfoName(profile,name);
2048MagickExport StringInfo *BlobToProfileStringInfo(
const char *name,
2049 const void *blob,
const size_t length,ExceptionInfo *exception)
2054 profile=AcquireProfileStringInfo(name,length,exception);
2055 if (profile != (
const StringInfo *) NULL)
2056 (void) memcpy(profile->datum,blob,length);
2060MagickExport MagickBooleanType SetImageProfile(Image *image,
const char *name,
2061 const StringInfo *profile,ExceptionInfo *exception)
2066 if (profile == (
const StringInfo *) NULL)
2067 return(MagickFalse);
2068 clone_profile=CloneStringInfo(profile);
2069 return(SetImageProfileInternal(image,name,clone_profile,MagickFalse,
2073MagickExport MagickBooleanType SetImageProfilePrivate(Image *image,
2074 StringInfo *profile,ExceptionInfo *exception)
2076 if (profile == (
const StringInfo *) NULL)
2077 return(MagickFalse);
2078 return(SetImageProfileInternal(image,GetStringInfoName(profile),profile,
2079 MagickFalse,exception));
2105static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
2117static inline signed short ReadProfileShort(
const EndianType endian,
2118 unsigned char *buffer)
2132 if (endian == LSBEndian)
2134 value=(
unsigned short) buffer[1] << 8;
2135 value|=(
unsigned short) buffer[0];
2136 quantum.unsigned_value=value & 0xffff;
2137 return((
signed short) quantum.signed_value);
2139 value=(
unsigned short) buffer[0] << 8;
2140 value|=(
unsigned short) buffer[1];
2141 quantum.unsigned_value=value & 0xffff;
2142 return((
signed short) quantum.signed_value);
2145static inline signed int ReadProfileLong(
const EndianType endian,
2146 unsigned char *buffer)
2160 if (endian == LSBEndian)
2162 value=(
unsigned int) buffer[3] << 24;
2163 value|=(
unsigned int) buffer[2] << 16;
2164 value|=(
unsigned int) buffer[1] << 8;
2165 value|=(
unsigned int) buffer[0];
2166 quantum.unsigned_value=value & 0xffffffff;
2167 return(quantum.signed_value);
2169 value=(
unsigned int) buffer[0] << 24;
2170 value|=(
unsigned int) buffer[1] << 16;
2171 value|=(
unsigned int) buffer[2] << 8;
2172 value|=(
unsigned int) buffer[3];
2173 quantum.unsigned_value=value & 0xffffffff;
2174 return(quantum.signed_value);
2177static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
2184 value=ReadProfileLong(MSBEndian,*p);
2190static inline signed short ReadProfileMSBShort(
unsigned char **p,
2198 value=ReadProfileShort(MSBEndian,*p);
2204static inline void WriteProfileLong(
const EndianType endian,
2205 const size_t value,
unsigned char *p)
2210 if (endian == LSBEndian)
2212 buffer[0]=(
unsigned char) value;
2213 buffer[1]=(
unsigned char) (value >> 8);
2214 buffer[2]=(
unsigned char) (value >> 16);
2215 buffer[3]=(
unsigned char) (value >> 24);
2216 (void) memcpy(p,buffer,4);
2219 buffer[0]=(
unsigned char) (value >> 24);
2220 buffer[1]=(
unsigned char) (value >> 16);
2221 buffer[2]=(
unsigned char) (value >> 8);
2222 buffer[3]=(
unsigned char) value;
2223 (void) memcpy(p,buffer,4);
2226static void WriteProfileShort(
const EndianType endian,
2227 const unsigned short value,
unsigned char *p)
2232 if (endian == LSBEndian)
2234 buffer[0]=(
unsigned char) value;
2235 buffer[1]=(
unsigned char) (value >> 8);
2236 (void) memcpy(p,buffer,2);
2239 buffer[0]=(
unsigned char) (value >> 8);
2240 buffer[1]=(
unsigned char) value;
2241 (void) memcpy(p,buffer,2);
2244static void SyncExifProfile(
const Image *image,
unsigned char *exif,
2247#define MaxDirectoryStack 16
2248#define EXIF_DELIMITER "\n"
2249#define EXIF_NUM_FORMATS 12
2250#define TAG_EXIF_OFFSET 0x8769
2251#define TAG_INTEROP_OFFSET 0xa005
2253 typedef struct _DirectoryInfo
2263 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
2281 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2288 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2289 if ((
id != 0x4949) && (
id != 0x4D4D))
2293 if (ReadProfileByte(&exif,&length) != 0x45)
2295 if (ReadProfileByte(&exif,&length) != 0x78)
2297 if (ReadProfileByte(&exif,&length) != 0x69)
2299 if (ReadProfileByte(&exif,&length) != 0x66)
2301 if (ReadProfileByte(&exif,&length) != 0x00)
2303 if (ReadProfileByte(&exif,&length) != 0x00)
2309 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2319 if (ReadProfileShort(endian,exif+2) != 0x002a)
2324 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2325 if ((offset < 0) || ((
size_t) offset >= length))
2327 directory=exif+offset;
2330 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2331 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2337 directory=directory_stack[level].directory;
2338 entry=directory_stack[level].entry;
2340 if ((directory < exif) || (directory > (exif+length-2)))
2345 number_entries=(size_t) ReadProfileShort(endian,directory);
2346 for ( ; entry < number_entries; entry++)
2362 q=(
unsigned char *) (directory+2+(12*entry));
2363 if (q > (exif+length-12))
2365 if (GetValueFromSplayTree(exif_resources,q) == q)
2367 (void) AddValueToSplayTree(exif_resources,q,q);
2368 tag_value=(ssize_t) ReadProfileShort(endian,q);
2369 format=(ssize_t) ReadProfileShort(endian,q+2);
2370 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2372 components=(int) ReadProfileLong(endian,q+4);
2375 number_bytes=(size_t) components*(
size_t) format_bytes[format];
2376 if ((ssize_t) number_bytes < components)
2378 if (number_bytes <= 4)
2385 offset=(ssize_t) ReadProfileLong(endian,q+8);
2387 ((
size_t) (offset+(ssize_t) number_bytes) > length))
2389 if (~length < number_bytes)
2391 p=(
unsigned char *) (exif+offset);
2397 (void) WriteProfileLong(endian,(
size_t) (image->resolution.x+0.5),p);
2398 if (number_bytes == 8)
2399 (void) WriteProfileLong(endian,1UL,p+4);
2404 (void) WriteProfileLong(endian,(
size_t) (image->resolution.y+0.5),p);
2405 if (number_bytes == 8)
2406 (void) WriteProfileLong(endian,1UL,p+4);
2411 if (number_bytes == 4)
2413 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2416 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2422 if (number_bytes == 4)
2424 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2427 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2433 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2435 offset=(ssize_t) ReadProfileLong(endian,p);
2436 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2438 directory_stack[level].directory=directory;
2440 directory_stack[level].entry=entry;
2442 directory_stack[level].directory=exif+offset;
2443 directory_stack[level].entry=0;
2445 if ((directory+2+(12*number_entries)) > (exif+length))
2447 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2449 if ((offset != 0) && ((
size_t) offset < length) &&
2450 (level < (MaxDirectoryStack-2)))
2452 directory_stack[level].directory=exif+offset;
2453 directory_stack[level].entry=0;
2460 }
while (level > 0);
2461 exif_resources=DestroySplayTree(exif_resources);
2465static void Sync8BimProfile(
const Image *image,
const StringInfo *profile)
2479 length=GetStringInfoLength(profile);
2480 p=GetStringInfoDatum(profile);
2483 if (ReadProfileByte(&p,&length) != 0x38)
2485 if (ReadProfileByte(&p,&length) != 0x42)
2487 if (ReadProfileByte(&p,&length) != 0x49)
2489 if (ReadProfileByte(&p,&length) != 0x4D)
2493 id=(
unsigned short) ReadProfileMSBShort(&p,&length);
2494 count=(ssize_t) ReadProfileByte(&p,&length);
2495 if ((count >= (ssize_t) length) || (count < 0))
2497 p+=(ptrdiff_t) count;
2498 length-=(size_t) count;
2499 if ((*p & 0x01) == 0)
2500 (void) ReadProfileByte(&p,&length);
2501 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2502 if ((count > (ssize_t) length) || (count < 0))
2504 if ((
id == 0x3ED) && (count == 16))
2506 if (image->units == PixelsPerCentimeterResolution)
2507 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2508 image->resolution.x*2.54*65536.0),p);
2510 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2511 image->resolution.x*65536.0),p);
2512 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2513 if (image->units == PixelsPerCentimeterResolution)
2514 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2515 image->resolution.y*2.54*65536.0),p+8);
2517 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2518 image->resolution.y*65536.0),p+8);
2519 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2522 SyncExifProfile(image,p,(
size_t) count);
2523 p+=(ptrdiff_t) count;
2524 length-=(size_t) count;
2529static void ReplaceXmpValue(StringInfo *profile,
size_t start,
size_t end,
2540 length=GetStringInfoLength(profile);
2541 value_length=strlen(value);
2542 new_length=length-(end-start)+value_length;
2543 if (new_length > length)
2544 SetStringInfoLength(profile,new_length);
2545 datum=(
char *) GetStringInfoDatum(profile);
2546 (void) memmove(datum+start+value_length,datum+end,length-end);
2547 (void) memcpy(datum+start,value,value_length);
2548 if (new_length < length)
2550 SetStringInfoLength(profile,new_length);
2551 datum=(
char *) GetStringInfoDatum(profile);
2552 *(datum+new_length)=
'\0';
2556static MagickBooleanType GetXmpOffsets(
const StringInfo *profile,
2557 const char *tag,
size_t *start,
size_t *end)
2567 datum=(
char *) GetStringInfoDatum(profile);
2568 length=GetStringInfoLength(profile);
2569 pos=strstr(datum,tag);
2570 tag_length=strlen(tag);
2571 if ((pos == (
char *) NULL) || ((pos-datum) < 1) || (*(pos-1) !=
'<') ||
2572 (((
size_t) (pos-datum)+tag_length) > length) ||
2573 (*(pos+tag_length) !=
'>'))
2574 return(MagickFalse);
2575 *start=(size_t) (pos-datum)+tag_length+1;
2576 pos=strstr(datum+*start,
"<");
2577 if (pos == (
char *) NULL)
2578 return(MagickFalse);
2579 *end=(size_t) (pos-datum);
2583static void GetXmpNumeratorAndDenominator(
double value,
2584 unsigned long *numerator,
unsigned long *denominator)
2591 if (value <= MagickEpsilon)
2593 if (value > (
double) MAGICK_ULONG_MAX)
2595 *numerator = MAGICK_ULONG_MAX;
2599 if (floor(value) == value)
2601 *numerator = (
unsigned long) value;
2607 while(fabs(df - value) > MagickEpsilon)
2614 *numerator=(
unsigned long) (value*(*denominator));
2616 df=*numerator/(double)*denominator;
2620static void SyncXmpProfile(
const Image *image,StringInfo *profile)
2623 value[MagickPathExtent];
2634 if (GetXmpOffsets(profile,
"tiff:XResolution",&start,&end) != MagickFalse)
2636 GetXmpNumeratorAndDenominator(image->resolution.x,&numerator,
2638 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",numerator,
2640 ReplaceXmpValue(profile,start,end,value);
2642 if (GetXmpOffsets(profile,
"tiff:YResolution",&start,&end) != MagickFalse)
2644 if ((fabs(image->resolution.x-image->resolution.y) > MagickEpsilon) ||
2647 GetXmpNumeratorAndDenominator(image->resolution.y,&numerator,
2649 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",
2650 numerator,denominator);
2652 ReplaceXmpValue(profile,start,end,value);
2654 if (GetXmpOffsets(profile,
"tiff:ResolutionUnit",&start,&end) != MagickFalse)
2656 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2657 ((
int) image->units)+1);
2658 ReplaceXmpValue(profile,start,end,value);
2660 if (GetXmpOffsets(profile,
"tiff:Orientation",&start,&end) != MagickFalse)
2662 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2663 (
int) image->orientation);
2664 ReplaceXmpValue(profile,start,end,value);
2668MagickPrivate
void SyncImageProfiles(Image *image)
2673 profile=(StringInfo *) GetImageProfile(image,
"8BIM");
2674 if (profile != (StringInfo *) NULL)
2675 Sync8BimProfile(image,profile);
2676 profile=(StringInfo *) GetImageProfile(image,
"EXIF");
2677 if (profile != (StringInfo *) NULL)
2678 SyncExifProfile(image,GetStringInfoDatum(profile),GetStringInfoLength(
2680 profile=(StringInfo *) GetImageProfile(image,
"XMP");
2681 if (profile != (StringInfo *) NULL)
2682 SyncXmpProfile(image,profile);
2685static void UpdateClipPath(
unsigned char *blob,
size_t length,
2686 const size_t old_columns,
const size_t old_rows,
2687 const RectangleInfo *new_geometry)
2697 selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2703 if (knot_count != 0)
2706 length-=(size_t) MagickMin(length,24U);
2712 knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2714 length-=(size_t) MagickMin(length,22);
2722 if (knot_count == 0)
2728 length-=(size_t) MagickMin(length,24);
2734 for (i=0; i < 3; i++)
2744 y=(double) ReadProfileMSBLong(&blob,&length);
2745 y=y*old_rows/4096.0/4096.0;
2747 yy=(
signed int) ((y*4096*4096)/new_geometry->height);
2748 WriteProfileLong(MSBEndian,(
size_t) yy,blob-4);
2749 x=(double) ReadProfileMSBLong(&blob,&length);
2750 x=x*old_columns/4096.0/4096.0;
2752 xx=(
signed int) ((x*4096*4096)/new_geometry->width);
2753 WriteProfileLong(MSBEndian,(
size_t) xx,blob-4);
2764 length-=(size_t) MagickMin(length,24);
2771MagickPrivate
void Update8BIMClipPath(
const Image *image,
2772 const size_t old_columns,
const size_t old_rows,
2773 const RectangleInfo *new_geometry)
2788 assert(image != (Image *) NULL);
2789 assert(new_geometry != (RectangleInfo *) NULL);
2790 profile=GetImageProfile(image,
"8bim");
2791 if (profile == (StringInfo *) NULL)
2793 length=GetStringInfoLength(profile);
2794 info=GetStringInfoDatum(profile);
2797 if (ReadProfileByte(&info,&length) != (
unsigned char)
'8')
2799 if (ReadProfileByte(&info,&length) != (
unsigned char)
'B')
2801 if (ReadProfileByte(&info,&length) != (
unsigned char)
'I')
2803 if (ReadProfileByte(&info,&length) != (
unsigned char)
'M')
2805 id=(ssize_t) ReadProfileMSBShort(&info,&length);
2806 count=(ssize_t) ReadProfileByte(&info,&length);
2807 if ((count != 0) && ((
size_t) count <= length))
2810 length-=(size_t) count;
2812 if ((count & 0x01) == 0)
2813 (void) ReadProfileByte(&info,&length);
2814 count=(ssize_t) ReadProfileMSBLong(&info,&length);
2815 if ((count < 0) || ((
size_t) count > length))
2820 if ((
id > 1999) && (
id < 2999))
2821 UpdateClipPath(info,(
size_t) count,old_columns,old_rows,new_geometry);
2823 length-=(size_t) MagickMin(length,(
size_t) count);