MagickCore  7.1.0
Convert, Edit, Or Compose Bitmap Images
profile.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % PPPP RRRR OOO FFFFF IIIII L EEEEE %
7 % P P R R O O F I L E %
8 % PPPP RRRR O O FFF I L EEE %
9 % P R R O O F I L E %
10 % P R R OOO F IIIII LLLLL EEEEE %
11 % %
12 % %
13 % MagickCore Image Profile Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  Include declarations.
41 */
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"
48 #include "MagickCore/configure.h"
49 #include "MagickCore/exception.h"
51 #include "MagickCore/image.h"
52 #include "MagickCore/linked-list.h"
53 #include "MagickCore/memory_.h"
54 #include "MagickCore/monitor.h"
56 #include "MagickCore/option.h"
59 #include "MagickCore/profile.h"
61 #include "MagickCore/property.h"
62 #include "MagickCore/quantum.h"
64 #include "MagickCore/resource_.h"
65 #include "MagickCore/splay-tree.h"
66 #include "MagickCore/string_.h"
69 #include "MagickCore/token.h"
70 #include "MagickCore/utility.h"
71 #if defined(MAGICKCORE_LCMS_DELEGATE)
72 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
73 #include <wchar.h>
74 #include <lcms/lcms2.h>
75 #else
76 #include <wchar.h>
77 #include "lcms2.h"
78 #endif
79 #endif
80 #if defined(MAGICKCORE_XML_DELEGATE)
81 # if defined(MAGICKCORE_WINDOWS_SUPPORT)
82 # if !defined(__MINGW32__)
83 # include <win32config.h>
84 # endif
85 # endif
86 # include <libxml/parser.h>
87 # include <libxml/tree.h>
88 #endif
89 
90 /*
91  Forward declarations
92 */
93 static MagickBooleanType
94  SetImageProfileInternal(Image *,const char *,const StringInfo *,
96 
97 static void
98  WriteTo8BimProfile(Image *,const char*,const StringInfo *);
99 
100 /*
101  Typedef declarations
102 */
104 {
105  char
107 
108  size_t
110 
111  unsigned char
113 
114  size_t
116 };
117 
118 typedef struct _CMSExceptionInfo
119 {
120  Image
122 
126 
127 /*
128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129 % %
130 % %
131 % %
132 % C l o n e I m a g e P r o f i l e s %
133 % %
134 % %
135 % %
136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 %
138 % CloneImageProfiles() clones one or more image profiles.
139 %
140 % The format of the CloneImageProfiles method is:
141 %
142 % MagickBooleanType CloneImageProfiles(Image *image,
143 % const Image *clone_image)
144 %
145 % A description of each parameter follows:
146 %
147 % o image: the image.
148 %
149 % o clone_image: the clone image.
150 %
151 */
153  const Image *clone_image)
154 {
155  assert(image != (Image *) NULL);
156  assert(image->signature == MagickCoreSignature);
157  assert(clone_image != (const Image *) NULL);
158  assert(clone_image->signature == MagickCoreSignature);
159  if (IsEventLogging() != MagickFalse)
160  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
161  if (clone_image->profiles != (void *) NULL)
162  {
163  if (image->profiles != (void *) NULL)
164  DestroyImageProfiles(image);
165  image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
166  (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
167  }
168  return(MagickTrue);
169 }
170 
171 /*
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 % %
174 % %
175 % %
176 % D e l e t e I m a g e P r o f i l e %
177 % %
178 % %
179 % %
180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 %
182 % DeleteImageProfile() deletes a profile from the image by its name.
183 %
184 % The format of the DeleteImageProfile method is:
185 %
186 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
187 %
188 % A description of each parameter follows:
189 %
190 % o image: the image.
191 %
192 % o name: the profile name.
193 %
194 */
196 {
197  assert(image != (Image *) NULL);
198  assert(image->signature == MagickCoreSignature);
199  if (IsEventLogging() != MagickFalse)
200  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
201  if (image->profiles == (SplayTreeInfo *) NULL)
202  return(MagickFalse);
203  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
204  return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
205 }
206 
207 /*
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209 % %
210 % %
211 % %
212 % D e s t r o y I m a g e P r o f i l e s %
213 % %
214 % %
215 % %
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217 %
218 % DestroyImageProfiles() releases memory associated with an image profile map.
219 %
220 % The format of the DestroyProfiles method is:
221 %
222 % void DestroyImageProfiles(Image *image)
223 %
224 % A description of each parameter follows:
225 %
226 % o image: the image.
227 %
228 */
230 {
231  if (image->profiles != (SplayTreeInfo *) NULL)
232  image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
233 }
234 
235 /*
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 % %
238 % %
239 % %
240 % G e t I m a g e P r o f i l e %
241 % %
242 % %
243 % %
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 %
246 % GetImageProfile() gets a profile associated with an image by name.
247 %
248 % The format of the GetImageProfile method is:
249 %
250 % const StringInfo *GetImageProfile(const Image *image,const char *name)
251 %
252 % A description of each parameter follows:
253 %
254 % o image: the image.
255 %
256 % o name: the profile name.
257 %
258 */
260  const char *name)
261 {
262  const StringInfo
263  *profile;
264 
265  assert(image != (Image *) NULL);
266  assert(image->signature == MagickCoreSignature);
267  if (IsEventLogging() != MagickFalse)
268  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
269  if (image->profiles == (SplayTreeInfo *) NULL)
270  return((StringInfo *) NULL);
271  profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
272  image->profiles,name);
273  return(profile);
274 }
275 
276 /*
277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 % %
279 % %
280 % %
281 % G e t N e x t I m a g e P r o f i l e %
282 % %
283 % %
284 % %
285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286 %
287 % GetNextImageProfile() gets the next profile name for an image.
288 %
289 % The format of the GetNextImageProfile method is:
290 %
291 % char *GetNextImageProfile(const Image *image)
292 %
293 % A description of each parameter follows:
294 %
295 % o hash_info: the hash info.
296 %
297 */
299 {
300  assert(image != (Image *) NULL);
301  assert(image->signature == MagickCoreSignature);
302  if (IsEventLogging() != MagickFalse)
303  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
304  if (image->profiles == (SplayTreeInfo *) NULL)
305  return((char *) NULL);
306  return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
307 }
308 
309 /*
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 % %
312 % %
313 % %
314 % P r o f i l e I m a g e %
315 % %
316 % %
317 % %
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 %
320 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
321 % profile with / to / from an image. If the profile is NULL, it is removed
322 % from the image otherwise added or applied. Use a name of '*' and a profile
323 % of NULL to remove all profiles from the image.
324 %
325 % ICC and ICM profiles are handled as follows: If the image does not have
326 % an associated color profile, the one you provide is associated with the
327 % image and the image pixels are not transformed. Otherwise, the colorspace
328 % transform defined by the existing and new profile are applied to the image
329 % pixels and the new profile is associated with the image.
330 %
331 % The format of the ProfileImage method is:
332 %
333 % MagickBooleanType ProfileImage(Image *image,const char *name,
334 % const void *datum,const size_t length,const MagickBooleanType clone)
335 %
336 % A description of each parameter follows:
337 %
338 % o image: the image.
339 %
340 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
341 %
342 % o datum: the profile data.
343 %
344 % o length: the length of the profile.
345 %
346 % o clone: should be MagickFalse.
347 %
348 */
349 
350 #if defined(MAGICKCORE_LCMS_DELEGATE)
351 
352 typedef struct _LCMSInfo
353 {
355  colorspace;
356 
357  cmsUInt32Number
358  type;
359 
360  size_t
361  channels;
362 
363  cmsHPROFILE
364  profile;
365 
366  int
367  intent;
368 
369  double
370  scale[4],
371  translate[4];
372 
373  void
374  **magick_restrict pixels;
375 } LCMSInfo;
376 
377 #if LCMS_VERSION < 2060
378 static void* cmsGetContextUserData(cmsContext ContextID)
379 {
380  return(ContextID);
381 }
382 
383 static cmsContext cmsCreateContext(void *magick_unused(Plugin),void *UserData)
384 {
385  magick_unreferenced(Plugin);
386  return((cmsContext) UserData);
387 }
388 
389 static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
390  cmsLogErrorHandlerFunction Fn)
391 {
392  magick_unreferenced(ContextID);
393  cmsSetLogErrorHandler(Fn);
394 }
395 
396 static void cmsDeleteContext(cmsContext magick_unused(ContextID))
397 {
398  magick_unreferenced(ContextID);
399 }
400 #endif
401 
402 static void **DestroyPixelTLS(void **pixels)
403 {
404  ssize_t
405  i;
406 
407  if (pixels == (void **) NULL)
408  return((void **) NULL);
409  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
410  if (pixels[i] != (void *) NULL)
411  pixels[i]=RelinquishMagickMemory(pixels[i]);
412  pixels=(void **) RelinquishMagickMemory(pixels);
413  return(pixels);
414 }
415 
416 static void **AcquirePixelTLS(const size_t columns,const size_t channels,
417  MagickBooleanType highres)
418 {
419  ssize_t
420  i;
421 
422  size_t
423  number_threads;
424 
425  size_t
426  size;
427 
428  void
429  **pixels;
430 
431  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
432  pixels=(void **) AcquireQuantumMemory(number_threads,sizeof(*pixels));
433  if (pixels == (void **) NULL)
434  return((void **) NULL);
435  (void) memset(pixels,0,number_threads*sizeof(*pixels));
436  size=sizeof(double);
437  if (highres == MagickFalse)
438  size=sizeof(Quantum);
439  for (i=0; i < (ssize_t) number_threads; i++)
440  {
441  pixels[i]=AcquireQuantumMemory(columns,channels*size);
442  if (pixels[i] == (void *) NULL)
443  return(DestroyPixelTLS(pixels));
444  }
445  return(pixels);
446 }
447 
448 static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
449 {
450  ssize_t
451  i;
452 
453  assert(transform != (cmsHTRANSFORM *) NULL);
454  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
455  if (transform[i] != (cmsHTRANSFORM) NULL)
456  cmsDeleteTransform(transform[i]);
457  transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
458  return(transform);
459 }
460 
461 static cmsHTRANSFORM *AcquireTransformTLS(const LCMSInfo *source_info,
462  const LCMSInfo *target_info,const cmsUInt32Number flags,
463  cmsContext cms_context)
464 {
465  cmsHTRANSFORM
466  *transform;
467 
468  size_t
469  number_threads;
470 
471  ssize_t
472  i;
473 
474  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
475  transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
476  sizeof(*transform));
477  if (transform == (cmsHTRANSFORM *) NULL)
478  return((cmsHTRANSFORM *) NULL);
479  (void) memset(transform,0,number_threads*sizeof(*transform));
480  for (i=0; i < (ssize_t) number_threads; i++)
481  {
482  transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
483  source_info->type,target_info->profile,target_info->type,
484  target_info->intent,flags);
485  if (transform[i] == (cmsHTRANSFORM) NULL)
486  return(DestroyTransformTLS(transform));
487  }
488  return(transform);
489 }
490 
491 static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
492  const char *message)
493 {
495  *cms_exception;
496 
498  *exception;
499 
500  Image
501  *image;
502 
503  cms_exception=(CMSExceptionInfo *) cmsGetContextUserData(context);
504  if (cms_exception == (CMSExceptionInfo *) NULL)
505  return;
506  exception=cms_exception->exception;
507  if (exception == (ExceptionInfo *) NULL)
508  return;
509  image=cms_exception->image;
510  if (image == (Image *) NULL)
511  {
513  "UnableToTransformColorspace","`%s'","unknown context");
514  return;
515  }
516  if (image->debug != MagickFalse)
517  (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
518  severity,message != (char *) NULL ? message : "no message");
520  "UnableToTransformColorspace","`%s', %s (#%u)",image->filename,
521  message != (char *) NULL ? message : "no message",severity);
522 }
523 
524 static void TransformDoublePixels(const int id,const Image* image,
525  const LCMSInfo *source_info,const LCMSInfo *target_info,
526  const cmsHTRANSFORM *transform,Quantum *q)
527 {
528 #define GetLCMSPixel(source_info,pixel,index) \
529  (source_info->scale[index]*((QuantumScale*pixel)+source_info->translate[index]))
530 #define SetLCMSPixel(target_info,pixel,index) \
531  ClampToQuantum(target_info->scale[index]*((QuantumRange*pixel)+target_info->translate[index]))
532 
533  double
534  *p;
535 
536  ssize_t
537  x;
538 
539  p=(double *) source_info->pixels[id];
540  for (x=0; x < (ssize_t) image->columns; x++)
541  {
542  *p++=GetLCMSPixel(source_info,GetPixelRed(image,q),0);
543  if (source_info->channels > 1)
544  {
545  *p++=GetLCMSPixel(source_info,GetPixelGreen(image,q),1);
546  *p++=GetLCMSPixel(source_info,GetPixelBlue(image,q),2);
547  }
548  if (source_info->channels > 3)
549  *p++=GetLCMSPixel(source_info,GetPixelBlack(image,q),3);
550  q+=GetPixelChannels(image);
551  }
552  cmsDoTransform(transform[id],source_info->pixels[id],target_info->pixels[id],
553  (unsigned int) image->columns);
554  p=(double *) target_info->pixels[id];
555  q-=GetPixelChannels(image)*image->columns;
556  for (x=0; x < (ssize_t) image->columns; x++)
557  {
558  if (target_info->channels == 1)
559  SetPixelGray(image,SetLCMSPixel(target_info,*p,0),q);
560  else
561  SetPixelRed(image,SetLCMSPixel(target_info,*p,0),q);
562  p++;
563  if (target_info->channels > 1)
564  {
565  SetPixelGreen(image,SetLCMSPixel(target_info,*p,1),q);
566  p++;
567  SetPixelBlue(image,SetLCMSPixel(target_info,*p,2),q);
568  p++;
569  }
570  if (target_info->channels > 3)
571  {
572  SetPixelBlack(image,SetLCMSPixel(target_info,*p,3),q);
573  p++;
574  }
575  q+=GetPixelChannels(image);
576  }
577 }
578 
579 static void TransformQuantumPixels(const int id,const Image* image,
580  const LCMSInfo *source_info,const LCMSInfo *target_info,
581  const cmsHTRANSFORM *transform,Quantum *q)
582 {
583  Quantum
584  *p;
585 
586  ssize_t
587  x;
588 
589  p=(Quantum *) source_info->pixels[id];
590  for (x=0; x < (ssize_t) image->columns; x++)
591  {
592  *p++=GetPixelRed(image,q);
593  if (source_info->channels > 1)
594  {
595  *p++=GetPixelGreen(image,q);
596  *p++=GetPixelBlue(image,q);
597  }
598  if (source_info->channels > 3)
599  *p++=GetPixelBlack(image,q);
600  q+=GetPixelChannels(image);
601  }
602  cmsDoTransform(transform[id],source_info->pixels[id],target_info->pixels[id],
603  (unsigned int) image->columns);
604  p=(Quantum *) target_info->pixels[id];
605  q-=GetPixelChannels(image)*image->columns;
606  for (x=0; x < (ssize_t) image->columns; x++)
607  {
608  if (target_info->channels == 1)
609  SetPixelGray(image,*p++,q);
610  else
611  SetPixelRed(image,*p++,q);
612  if (target_info->channels > 1)
613  {
614  SetPixelGreen(image,*p++,q);
615  SetPixelBlue(image,*p++,q);
616  }
617  if (target_info->channels > 3)
618  SetPixelBlack(image,*p++,q);
619  q+=GetPixelChannels(image);
620  }
621 }
622 
623 static inline void SetLCMSInfoTranslate(LCMSInfo *info,const double translate)
624 {
625  info->translate[0]=translate;
626  info->translate[1]=translate;
627  info->translate[2]=translate;
628  info->translate[3]=translate;
629 }
630 
631 static inline void SetLCMSInfoScale(LCMSInfo *info,const double scale)
632 {
633  info->scale[0]=scale;
634  info->scale[1]=scale;
635  info->scale[2]=scale;
636  info->scale[3]=scale;
637 }
638 #endif
639 
641  ExceptionInfo *exception)
642 {
643  static unsigned char
644  sRGBProfile[] =
645  {
646  0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
647  0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
648  0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
649  0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
650  0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
651  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
652  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
653  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
657  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
658  0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
659  0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
660  0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
661  0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
662  0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
663  0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
664  0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
665  0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
666  0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
667  0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
668  0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
669  0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
670  0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
671  0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
672  0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
673  0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
674  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
675  0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
676  0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
677  0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
678  0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
679  0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
680  0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681  0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
682  0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
683  0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
684  0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
685  0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
686  0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687  0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
688  0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
689  0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
690  0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
691  0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
692  0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
693  0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
694  0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
695  0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
696  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
697  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
698  0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699  0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
700  0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
701  0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
706  0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
707  0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
708  0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
709  0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
710  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
711  0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
712  0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
713  0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
714  0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716  0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
717  0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
718  0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
719  0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720  0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
721  0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726  0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
727  0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
728  0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
729  0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
730  0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
731  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
732  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733  0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
734  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
735  0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
736  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737  0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
738  0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
739  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
740  0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
741  0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
742  0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
743  0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
744  0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
745  0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
746  0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
747  0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
748  0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
749  0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
750  0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
751  0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
752  0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
753  0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
754  0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
755  0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
756  0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
757  0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
758  0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
759  0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
760  0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
761  0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
762  0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
763  0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
764  0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
765  0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
766  0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
767  0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
768  0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
769  0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
770  0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
771  0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
772  0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
773  0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
774  0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
775  0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
776  0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
777  0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
778  0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
779  0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
780  0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
781  0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
782  0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
783  0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
784  0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
785  0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
786  0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
787  0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
788  0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
789  0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
790  0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
791  0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
792  0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
793  0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
794  0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
795  0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
796  0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
797  0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
798  0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
799  0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
800  0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
801  0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
802  0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
803  0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
804  0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
805  0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
806  0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
807  0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
808  0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
809  0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
810  0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
811  0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
812  0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
813  0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
814  0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
815  0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
816  0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
817  0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
818  0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
819  0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
820  0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
821  0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
822  0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
823  0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
824  0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
825  0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
826  0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
827  0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
828  0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
829  0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
830  0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
831  0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
832  0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
833  0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
834  0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
835  0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
836  0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
837  0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
838  0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
839  0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
840  0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
841  0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
842  0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
843  0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
844  0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
845  0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
846  0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
847  0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
848  0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
849  0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
850  0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
851  0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
852  0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
853  0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
854  0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
855  0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
856  0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
857  0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
858  0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
859  0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
860  0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
861  0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
862  0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
863  0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
864  0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
865  0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
866  0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
867  0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
868  0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
869  0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
870  0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
871  0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
872  0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
873  0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
874  0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
875  0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
876  0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
877  0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
878  0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
879  0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
880  0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
881  0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
882  0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
883  0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
884  0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
885  0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
886  0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
887  0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
888  0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
889  0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
890  0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
891  0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
892  0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
893  0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
894  0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
895  0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
896  0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
897  0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
898  0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
899  0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
900  0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
901  0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
902  0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
903  0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
904  0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
905  0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
906  0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
907  0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
908  0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
909  0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
910  0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
911  0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
912  0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
913  0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
914  };
915 
916  StringInfo
917  *profile;
918 
920  status;
921 
922  assert(image != (Image *) NULL);
923  assert(image->signature == MagickCoreSignature);
924  if (GetImageProfile(image,"icc") != (const StringInfo *) NULL)
925  return(MagickFalse);
926  profile=AcquireStringInfo(sizeof(sRGBProfile));
927  SetStringInfoDatum(profile,sRGBProfile);
928  status=SetImageProfile(image,"icc",profile,exception);
929  profile=DestroyStringInfo(profile);
930  return(status);
931 }
932 
934  const void *datum,const size_t length,ExceptionInfo *exception)
935 {
936 #define ProfileImageTag "Profile/Image"
937 #ifndef TYPE_XYZ_8
938  #define TYPE_XYZ_8 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(1))
939 #endif
940 #define ThrowProfileException(severity,tag,context) \
941 { \
942  if (profile != (StringInfo *) NULL) \
943  profile=DestroyStringInfo(profile); \
944  if (cms_context != (cmsContext) NULL) \
945  cmsDeleteContext(cms_context); \
946  if (source_info.profile != (cmsHPROFILE) NULL) \
947  (void) cmsCloseProfile(source_info.profile); \
948  if (target_info.profile != (cmsHPROFILE) NULL) \
949  (void) cmsCloseProfile(target_info.profile); \
950  ThrowBinaryException(severity,tag,context); \
951 }
952 
954  status;
955 
956  StringInfo
957  *profile;
958 
959  assert(image != (Image *) NULL);
960  assert(image->signature == MagickCoreSignature);
961  assert(name != (const char *) NULL);
962  if (IsEventLogging() != MagickFalse)
963  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
964  if ((datum == (const void *) NULL) || (length == 0))
965  {
966  char
967  *next;
968 
969  /*
970  Delete image profile(s).
971  */
973  for (next=GetNextImageProfile(image); next != (const char *) NULL; )
974  {
975  if (IsOptionMember(next,name) != MagickFalse)
976  {
977  (void) DeleteImageProfile(image,next);
979  }
980  next=GetNextImageProfile(image);
981  }
982  return(MagickTrue);
983  }
984  /*
985  Add a ICC, IPTC, or generic profile to the image.
986  */
987  status=MagickTrue;
988  profile=AcquireStringInfo((size_t) length);
989  SetStringInfoDatum(profile,(unsigned char *) datum);
990  if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
991  status=SetImageProfile(image,name,profile,exception);
992  else
993  {
994  const StringInfo
995  *icc_profile;
996 
997  icc_profile=GetImageProfile(image,"icc");
998  if ((icc_profile != (const StringInfo *) NULL) &&
999  (CompareStringInfo(icc_profile,profile) == 0))
1000  {
1001  const char
1002  *value;
1003 
1004  value=GetImageProperty(image,"exif:ColorSpace",exception);
1005  (void) value;
1006  if (LocaleCompare(value,"1") != 0)
1007  (void) SetsRGBImageProfile(image,exception);
1008  value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
1009  if (LocaleCompare(value,"R98.") != 0)
1010  (void) SetsRGBImageProfile(image,exception);
1011  icc_profile=GetImageProfile(image,"icc");
1012  }
1013  if ((icc_profile != (const StringInfo *) NULL) &&
1014  (CompareStringInfo(icc_profile,profile) == 0))
1015  {
1016  profile=DestroyStringInfo(profile);
1017  return(MagickTrue);
1018  }
1019 #if !defined(MAGICKCORE_LCMS_DELEGATE)
1020  (void) ThrowMagickException(exception,GetMagickModule(),
1021  MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
1022  "'%s' (LCMS)",image->filename);
1023 #else
1024  {
1025  cmsContext
1026  cms_context;
1027 
1029  cms_exception;
1030 
1031  LCMSInfo
1032  source_info,
1033  target_info;
1034 
1035  /*
1036  Transform pixel colors as defined by the color profiles.
1037  */
1038  cms_exception.image=image;
1039  cms_exception.exception=exception;
1040  cms_context=cmsCreateContext(NULL,&cms_exception);
1041  if (cms_context == (cmsContext) NULL)
1042  {
1043  profile=DestroyStringInfo(profile);
1045  "ColorspaceColorProfileMismatch",name);
1046  }
1047  cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
1048  source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1049  GetStringInfoDatum(profile),(cmsUInt32Number)
1050  GetStringInfoLength(profile));
1051  if (source_info.profile == (cmsHPROFILE) NULL)
1052  {
1053  profile=DestroyStringInfo(profile);
1054  cmsDeleteContext(cms_context);
1056  "ColorspaceColorProfileMismatch",name);
1057  }
1058  if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
1059  (icc_profile == (StringInfo *) NULL))
1060  status=SetImageProfile(image,name,profile,exception);
1061  else
1062  {
1063  CacheView
1064  *image_view;
1065 
1066  cmsColorSpaceSignature
1067  signature;
1068 
1069  cmsHTRANSFORM
1070  *magick_restrict transform;
1071 
1072  cmsUInt32Number
1073  flags;
1074 
1076  highres;
1077 
1079  progress;
1080 
1081  ssize_t
1082  y;
1083 
1084  target_info.profile=(cmsHPROFILE) NULL;
1085  if (icc_profile != (StringInfo *) NULL)
1086  {
1087  target_info.profile=source_info.profile;
1088  source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1089  GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1090  GetStringInfoLength(icc_profile));
1091  if (source_info.profile == (cmsHPROFILE) NULL)
1093  "ColorspaceColorProfileMismatch",name);
1094  }
1095  highres=MagickTrue;
1096 #if !defined(MAGICKCORE_HDRI_SUPPORT) || (MAGICKCORE_QUANTUM_DEPTH > 16)
1097  {
1098  const char
1099  *artifact;
1100 
1101  artifact=GetImageArtifact(image,"profile:highres-transform");
1102  if (IsStringFalse(artifact) != MagickFalse)
1103  highres=MagickFalse;
1104  }
1105 #endif
1106  SetLCMSInfoScale(&source_info,1.0);
1107  SetLCMSInfoTranslate(&source_info,0.0);
1108  source_info.colorspace=sRGBColorspace;
1109  source_info.channels=3;
1110  switch (cmsGetColorSpace(source_info.profile))
1111  {
1112  case cmsSigCmykData:
1113  {
1114  source_info.colorspace=CMYKColorspace;
1115  source_info.channels=4;
1116  if (highres != MagickFalse)
1117  {
1118  source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1119  SetLCMSInfoScale(&source_info,100.0);
1120  }
1121 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1122  else
1123  source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1124 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1125  else
1126  source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1127 #endif
1128  break;
1129  }
1130  case cmsSigGrayData:
1131  {
1132  source_info.colorspace=GRAYColorspace;
1133  source_info.channels=1;
1134  if (highres != MagickFalse)
1135  source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1136 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1137  else
1138  source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1139 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1140  else
1141  source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1142 #endif
1143  break;
1144  }
1145  case cmsSigLabData:
1146  {
1147  source_info.colorspace=LabColorspace;
1148  if (highres != MagickFalse)
1149  {
1150  source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1151  source_info.scale[0]=100.0;
1152  source_info.scale[1]=255.0;
1153  source_info.scale[2]=255.0;
1154  source_info.translate[1]=(-0.5);
1155  source_info.translate[2]=(-0.5);
1156  }
1157 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1158  else
1159  source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1160 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1161  else
1162  source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1163 #endif
1164  break;
1165  }
1166  case cmsSigRgbData:
1167  {
1168  source_info.colorspace=sRGBColorspace;
1169  if (highres != MagickFalse)
1170  source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1171 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1172  else
1173  source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1174 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1175  else
1176  source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1177 #endif
1178  break;
1179  }
1180  case cmsSigXYZData:
1181  {
1182  source_info.colorspace=XYZColorspace;
1183  if (highres != MagickFalse)
1184  source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1185 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1186  else
1187  source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1188 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1189  else
1190  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1191 #endif
1192  break;
1193  }
1194  default:
1196  "ColorspaceColorProfileMismatch",name);
1197  }
1198  signature=cmsGetPCS(source_info.profile);
1199  if (target_info.profile != (cmsHPROFILE) NULL)
1200  signature=cmsGetColorSpace(target_info.profile);
1201  SetLCMSInfoScale(&target_info,1.0);
1202  SetLCMSInfoTranslate(&target_info,0.0);
1203  target_info.channels=3;
1204  switch (signature)
1205  {
1206  case cmsSigCmykData:
1207  {
1208  target_info.colorspace=CMYKColorspace;
1209  target_info.channels=4;
1210  if (highres != MagickFalse)
1211  {
1212  target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1213  SetLCMSInfoScale(&target_info,0.01);
1214  }
1215 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1216  else
1217  target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1218 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1219  else
1220  target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1221 #endif
1222  break;
1223  }
1224  case cmsSigGrayData:
1225  {
1226  target_info.colorspace=GRAYColorspace;
1227  target_info.channels=1;
1228  if (highres != MagickFalse)
1229  target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1230 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1231  else
1232  target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1233 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1234  else
1235  target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1236 #endif
1237  break;
1238  }
1239  case cmsSigLabData:
1240  {
1241  target_info.colorspace=LabColorspace;
1242  if (highres != MagickFalse)
1243  {
1244  target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1245  target_info.scale[0]=0.01;
1246  target_info.scale[1]=1/255.0;
1247  target_info.scale[2]=1/255.0;
1248  target_info.translate[1]=0.5;
1249  target_info.translate[2]=0.5;
1250  }
1251 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1252  else
1253  target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1254 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1255  else
1256  target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1257 #endif
1258  break;
1259  }
1260  case cmsSigRgbData:
1261  {
1262  target_info.colorspace=sRGBColorspace;
1263  if (highres != MagickFalse)
1264  target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1265 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1266  else
1267  target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1268 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1269  else
1270  target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1271 #endif
1272  break;
1273  }
1274  case cmsSigXYZData:
1275  {
1276  target_info.colorspace=XYZColorspace;
1277  if (highres != MagickFalse)
1278  target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1279 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1280  else
1281  target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1282 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1283  else
1284  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1285 #endif
1286  break;
1287  }
1288  default:
1290  "ColorspaceColorProfileMismatch",name);
1291  }
1292  switch (image->rendering_intent)
1293  {
1294  case AbsoluteIntent:
1295  {
1296  target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1297  break;
1298  }
1299  case PerceptualIntent:
1300  {
1301  target_info.intent=INTENT_PERCEPTUAL;
1302  break;
1303  }
1304  case RelativeIntent:
1305  {
1306  target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1307  break;
1308  }
1309  case SaturationIntent:
1310  {
1311  target_info.intent=INTENT_SATURATION;
1312  break;
1313  }
1314  default:
1315  {
1316  target_info.intent=INTENT_PERCEPTUAL;
1317  break;
1318  }
1319  }
1320  flags=cmsFLAGS_HIGHRESPRECALC;
1321 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1322  if (image->black_point_compensation != MagickFalse)
1323  flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1324 #endif
1325  transform=AcquireTransformTLS(&source_info,&target_info,flags,
1326  cms_context);
1327  if (transform == (cmsHTRANSFORM *) NULL)
1328  ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1329  name);
1330  /*
1331  Transform image as dictated by the source & target image profiles.
1332  */
1333  source_info.pixels=AcquirePixelTLS(image->columns,
1334  source_info.channels,highres);
1335  target_info.pixels=AcquirePixelTLS(image->columns,
1336  target_info.channels,highres);
1337  if ((source_info.pixels == (void **) NULL) ||
1338  (target_info.pixels == (void **) NULL))
1339  {
1340  target_info.pixels=DestroyPixelTLS(target_info.pixels);
1341  source_info.pixels=DestroyPixelTLS(source_info.pixels);
1342  transform=DestroyTransformTLS(transform);
1344  "MemoryAllocationFailed",image->filename);
1345  }
1346  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1347  {
1348  target_info.pixels=DestroyPixelTLS(target_info.pixels);
1349  source_info.pixels=DestroyPixelTLS(source_info.pixels);
1350  transform=DestroyTransformTLS(transform);
1351  if (source_info.profile != (cmsHPROFILE) NULL)
1352  (void) cmsCloseProfile(source_info.profile);
1353  if (target_info.profile != (cmsHPROFILE) NULL)
1354  (void) cmsCloseProfile(target_info.profile);
1355  return(MagickFalse);
1356  }
1357  if (target_info.colorspace == CMYKColorspace)
1358  (void) SetImageColorspace(image,target_info.colorspace,exception);
1359  progress=0;
1360  image_view=AcquireAuthenticCacheView(image,exception);
1361 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1362  #pragma omp parallel for schedule(static) shared(status) \
1363  magick_number_threads(image,image,image->rows,1)
1364 #endif
1365  for (y=0; y < (ssize_t) image->rows; y++)
1366  {
1367  const int
1368  id = GetOpenMPThreadId();
1369 
1371  sync;
1372 
1373  Quantum
1374  *magick_restrict q;
1375 
1376  if (status == MagickFalse)
1377  continue;
1378  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1379  exception);
1380  if (q == (Quantum *) NULL)
1381  {
1382  status=MagickFalse;
1383  continue;
1384  }
1385  if (highres != MagickFalse)
1386  TransformDoublePixels(id,image,&source_info,&target_info,
1387  transform,q);
1388  else
1389  TransformQuantumPixels(id,image,&source_info,&target_info,
1390  transform,q);
1391  sync=SyncCacheViewAuthenticPixels(image_view,exception);
1392  if (sync == MagickFalse)
1393  status=MagickFalse;
1394  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1395  {
1397  proceed;
1398 
1399 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1400  #pragma omp atomic
1401 #endif
1402  progress++;
1403  proceed=SetImageProgress(image,ProfileImageTag,progress,
1404  image->rows);
1405  if (proceed == MagickFalse)
1406  status=MagickFalse;
1407  }
1408  }
1409  image_view=DestroyCacheView(image_view);
1410  (void) SetImageColorspace(image,target_info.colorspace,exception);
1411  switch (signature)
1412  {
1413  case cmsSigRgbData:
1414  {
1415  image->type=image->alpha_trait == UndefinedPixelTrait ?
1417  break;
1418  }
1419  case cmsSigCmykData:
1420  {
1421  image->type=image->alpha_trait == UndefinedPixelTrait ?
1423  break;
1424  }
1425  case cmsSigGrayData:
1426  {
1427  image->type=image->alpha_trait == UndefinedPixelTrait ?
1429  break;
1430  }
1431  default:
1432  break;
1433  }
1434  target_info.pixels=DestroyPixelTLS(target_info.pixels);
1435  source_info.pixels=DestroyPixelTLS(source_info.pixels);
1436  transform=DestroyTransformTLS(transform);
1437  if ((status != MagickFalse) &&
1438  (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1439  status=SetImageProfile(image,name,profile,exception);
1440  if (target_info.profile != (cmsHPROFILE) NULL)
1441  (void) cmsCloseProfile(target_info.profile);
1442  }
1443  (void) cmsCloseProfile(source_info.profile);
1444  cmsDeleteContext(cms_context);
1445  }
1446 #endif
1447  }
1448  profile=DestroyStringInfo(profile);
1449  return(status);
1450 }
1451 
1452 /*
1453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1454 % %
1455 % %
1456 % %
1457 % R e m o v e I m a g e P r o f i l e %
1458 % %
1459 % %
1460 % %
1461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1462 %
1463 % RemoveImageProfile() removes a named profile from the image and returns its
1464 % value.
1465 %
1466 % The format of the RemoveImageProfile method is:
1467 %
1468 % void *RemoveImageProfile(Image *image,const char *name)
1469 %
1470 % A description of each parameter follows:
1471 %
1472 % o image: the image.
1473 %
1474 % o name: the profile name.
1475 %
1476 */
1478 {
1479  StringInfo
1480  *profile;
1481 
1482  assert(image != (Image *) NULL);
1483  assert(image->signature == MagickCoreSignature);
1484  if (IsEventLogging() != MagickFalse)
1485  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1486  if (image->profiles == (SplayTreeInfo *) NULL)
1487  return((StringInfo *) NULL);
1488  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1490  image->profiles,name);
1491  return(profile);
1492 }
1493 
1494 /*
1495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1496 % %
1497 % %
1498 % %
1499 % R e s e t P r o f i l e I t e r a t o r %
1500 % %
1501 % %
1502 % %
1503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1504 %
1505 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1506 % conjunction with GetNextImageProfile() to iterate over all the profiles
1507 % associated with an image.
1508 %
1509 % The format of the ResetImageProfileIterator method is:
1510 %
1511 % ResetImageProfileIterator(Image *image)
1512 %
1513 % A description of each parameter follows:
1514 %
1515 % o image: the image.
1516 %
1517 */
1519 {
1520  assert(image != (Image *) NULL);
1521  assert(image->signature == MagickCoreSignature);
1522  if (IsEventLogging() != MagickFalse)
1523  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1524  if (image->profiles == (SplayTreeInfo *) NULL)
1525  return;
1527 }
1528 
1529 /*
1530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1531 % %
1532 % %
1533 % %
1534 % S e t I m a g e P r o f i l e %
1535 % %
1536 % %
1537 % %
1538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1539 %
1540 % SetImageProfile() adds a named profile to the image. If a profile with the
1541 % same name already exists, it is replaced. This method differs from the
1542 % ProfileImage() method in that it does not apply CMS color profiles.
1543 %
1544 % The format of the SetImageProfile method is:
1545 %
1546 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1547 % const StringInfo *profile)
1548 %
1549 % A description of each parameter follows:
1550 %
1551 % o image: the image.
1552 %
1553 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1554 % Photoshop wrapper for iptc profiles).
1555 %
1556 % o profile: A StringInfo structure that contains the named profile.
1557 %
1558 */
1559 
1560 static void *DestroyProfile(void *profile)
1561 {
1562  return((void *) DestroyStringInfo((StringInfo *) profile));
1563 }
1564 
1565 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1566  unsigned char *quantum)
1567 {
1568  *quantum=(*p++);
1569  return(p);
1570 }
1571 
1572 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1573  unsigned int *quantum)
1574 {
1575  *quantum=(unsigned int) (*p++) << 24;
1576  *quantum|=(unsigned int) (*p++) << 16;
1577  *quantum|=(unsigned int) (*p++) << 8;
1578  *quantum|=(unsigned int) (*p++);
1579  return(p);
1580 }
1581 
1582 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1583  unsigned short *quantum)
1584 {
1585  *quantum=(unsigned short) (*p++) << 8;
1586  *quantum|=(unsigned short) (*p++);
1587  return(p);
1588 }
1589 
1590 static inline void WriteResourceLong(unsigned char *p,
1591  const unsigned int quantum)
1592 {
1593  unsigned char
1594  buffer[4];
1595 
1596  buffer[0]=(unsigned char) (quantum >> 24);
1597  buffer[1]=(unsigned char) (quantum >> 16);
1598  buffer[2]=(unsigned char) (quantum >> 8);
1599  buffer[3]=(unsigned char) quantum;
1600  (void) memcpy(p,buffer,4);
1601 }
1602 
1603 static void WriteTo8BimProfile(Image *image,const char *name,
1604  const StringInfo *profile)
1605 {
1606  const unsigned char
1607  *datum,
1608  *q;
1609 
1610  const unsigned char
1611  *p;
1612 
1613  size_t
1614  length;
1615 
1616  StringInfo
1617  *profile_8bim;
1618 
1619  ssize_t
1620  count;
1621 
1622  unsigned char
1623  length_byte;
1624 
1625  unsigned int
1626  value;
1627 
1628  unsigned short
1629  id,
1630  profile_id;
1631 
1632  if (LocaleCompare(name,"icc") == 0)
1633  profile_id=0x040f;
1634  else
1635  if (LocaleCompare(name,"iptc") == 0)
1636  profile_id=0x0404;
1637  else
1638  if (LocaleCompare(name,"xmp") == 0)
1639  profile_id=0x0424;
1640  else
1641  return;
1642  profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1643  image->profiles,"8bim");
1644  if (profile_8bim == (StringInfo *) NULL)
1645  return;
1646  datum=GetStringInfoDatum(profile_8bim);
1647  length=GetStringInfoLength(profile_8bim);
1648  for (p=datum; p < (datum+length-16); )
1649  {
1650  q=p;
1651  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1652  break;
1653  p+=4;
1654  p=ReadResourceShort(p,&id);
1655  p=ReadResourceByte(p,&length_byte);
1656  p+=length_byte;
1657  if (((length_byte+1) & 0x01) != 0)
1658  p++;
1659  if (p > (datum+length-4))
1660  break;
1661  p=ReadResourceLong(p,&value);
1662  count=(ssize_t) value;
1663  if ((count & 0x01) != 0)
1664  count++;
1665  if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1666  break;
1667  if (id != profile_id)
1668  p+=count;
1669  else
1670  {
1671  size_t
1672  extent,
1673  offset;
1674 
1675  ssize_t
1676  extract_extent;
1677 
1678  StringInfo
1679  *extract_profile;
1680 
1681  extract_extent=0;
1682  extent=(datum+length)-(p+count);
1683  if (profile == (StringInfo *) NULL)
1684  {
1685  offset=(q-datum);
1686  extract_profile=AcquireStringInfo(offset+extent);
1687  (void) memcpy(extract_profile->datum,datum,offset);
1688  }
1689  else
1690  {
1691  offset=(p-datum);
1692  extract_extent=profile->length;
1693  if ((extract_extent & 0x01) != 0)
1694  extract_extent++;
1695  extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1696  (void) memcpy(extract_profile->datum,datum,offset-4);
1697  WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
1698  profile->length);
1699  (void) memcpy(extract_profile->datum+offset,
1700  profile->datum,profile->length);
1701  }
1702  (void) memcpy(extract_profile->datum+offset+extract_extent,
1703  p+count,extent);
1704  (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1705  ConstantString("8bim"),CloneStringInfo(extract_profile));
1706  extract_profile=DestroyStringInfo(extract_profile);
1707  break;
1708  }
1709  }
1710 }
1711 
1713  const StringInfo *resource_block,ExceptionInfo *exception)
1714 {
1715  const unsigned char
1716  *datum;
1717 
1718  const unsigned char
1719  *p;
1720 
1721  size_t
1722  length;
1723 
1724  ssize_t
1725  count;
1726 
1727  StringInfo
1728  *profile;
1729 
1730  unsigned char
1731  length_byte;
1732 
1733  unsigned int
1734  value;
1735 
1736  unsigned short
1737  id;
1738 
1739  datum=GetStringInfoDatum(resource_block);
1740  length=GetStringInfoLength(resource_block);
1741  for (p=datum; p < (datum+length-16); )
1742  {
1743  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1744  break;
1745  p+=4;
1746  p=ReadResourceShort(p,&id);
1747  p=ReadResourceByte(p,&length_byte);
1748  p+=length_byte;
1749  if (((length_byte+1) & 0x01) != 0)
1750  p++;
1751  if (p > (datum+length-4))
1752  break;
1753  p=ReadResourceLong(p,&value);
1754  count=(ssize_t) value;
1755  if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1756  break;
1757  switch (id)
1758  {
1759  case 0x03ed:
1760  {
1761  unsigned int
1762  resolution;
1763 
1764  unsigned short
1765  units;
1766 
1767  /*
1768  Resolution.
1769  */
1770  if (count < 10)
1771  break;
1772  p=ReadResourceLong(p,&resolution);
1773  image->resolution.x=((double) resolution)/65536.0;
1774  p=ReadResourceShort(p,&units)+2;
1775  p=ReadResourceLong(p,&resolution)+4;
1776  image->resolution.y=((double) resolution)/65536.0;
1777  /*
1778  Values are always stored as pixels per inch.
1779  */
1782  else
1783  {
1785  image->resolution.x/=2.54;
1786  image->resolution.y/=2.54;
1787  }
1788  break;
1789  }
1790  case 0x0404:
1791  {
1792  /*
1793  IPTC Profile
1794  */
1795  profile=AcquireStringInfo(count);
1796  SetStringInfoDatum(profile,p);
1797  (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1798  exception);
1799  profile=DestroyStringInfo(profile);
1800  p+=count;
1801  break;
1802  }
1803  case 0x040c:
1804  {
1805  /*
1806  Thumbnail.
1807  */
1808  p+=count;
1809  break;
1810  }
1811  case 0x040f:
1812  {
1813  /*
1814  ICC Profile.
1815  */
1816  profile=AcquireStringInfo(count);
1817  SetStringInfoDatum(profile,p);
1818  (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1819  exception);
1820  profile=DestroyStringInfo(profile);
1821  p+=count;
1822  break;
1823  }
1824  case 0x0422:
1825  {
1826  /*
1827  EXIF Profile.
1828  */
1829  profile=AcquireStringInfo(count);
1830  SetStringInfoDatum(profile,p);
1831  (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1832  exception);
1833  profile=DestroyStringInfo(profile);
1834  p+=count;
1835  break;
1836  }
1837  case 0x0424:
1838  {
1839  /*
1840  XMP Profile.
1841  */
1842  profile=AcquireStringInfo(count);
1843  SetStringInfoDatum(profile,p);
1844  (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1845  exception);
1846  profile=DestroyStringInfo(profile);
1847  p+=count;
1848  break;
1849  }
1850  default:
1851  {
1852  p+=count;
1853  break;
1854  }
1855  }
1856  if ((count & 0x01) != 0)
1857  p++;
1858  }
1859 }
1860 
1861 static void PatchCorruptProfile(const char *name,StringInfo *profile)
1862 {
1863  unsigned char
1864  *p;
1865 
1866  size_t
1867  length;
1868 
1869  /*
1870  Detect corrupt profiles and if discovered, repair.
1871  */
1872  if (LocaleCompare(name,"xmp") == 0)
1873  {
1874  /*
1875  Remove garbage after xpacket end.
1876  */
1877  p=GetStringInfoDatum(profile);
1878  p=(unsigned char *) strstr((const char *) p,"<?xpacket end=\"w\"?>");
1879  if (p != (unsigned char *) NULL)
1880  {
1881  p+=19;
1882  length=p-GetStringInfoDatum(profile);
1883  if (length != GetStringInfoLength(profile))
1884  {
1885  *p='\0';
1886  SetStringInfoLength(profile,length);
1887  }
1888  }
1889  return;
1890  }
1891  if (LocaleCompare(name,"exif") == 0)
1892  {
1893  /*
1894  Check if profile starts with byte order marker instead of Exif.
1895  */
1896  p=GetStringInfoDatum(profile);
1897  if ((LocaleNCompare((const char *) p,"MM",2) == 0) ||
1898  (LocaleNCompare((const char *) p,"II",2) == 0))
1899  {
1900  const unsigned char
1901  profile_start[] = "Exif\0\0";
1902 
1903  StringInfo
1904  *exif_profile;
1905 
1906  exif_profile=AcquireStringInfo(6);
1907  if (exif_profile != (StringInfo *) NULL)
1908  {
1909  SetStringInfoDatum(exif_profile,profile_start);
1910  ConcatenateStringInfo(exif_profile,profile);
1911  SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
1912  SetStringInfo(profile,exif_profile);
1913  exif_profile=DestroyStringInfo(exif_profile);
1914  }
1915  }
1916  }
1917 }
1918 
1919 #if defined(MAGICKCORE_XML_DELEGATE)
1921  const StringInfo *profile,ExceptionInfo *exception)
1922 {
1923  xmlDocPtr
1924  document;
1925 
1926  /*
1927  Parse XML profile.
1928  */
1929  document=xmlReadMemory((const char *) GetStringInfoDatum(profile),(int)
1930  GetStringInfoLength(profile),"xmp.xml",NULL,XML_PARSE_NOERROR |
1931  XML_PARSE_NOWARNING);
1932  if (document == (xmlDocPtr) NULL)
1933  {
1935  "CorruptImageProfile","`%s' (XMP)",image->filename);
1936  return(MagickFalse);
1937  }
1938  xmlFreeDoc(document);
1939  return(MagickTrue);
1940 }
1941 #else
1943  const StringInfo *profile,ExceptionInfo *exception)
1944 {
1946  "DelegateLibrarySupportNotBuiltIn","'%s' (XML)",image->filename);
1947  return(MagickFalse);
1948 }
1949 #endif
1950 
1951 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1952  const StringInfo *profile,const MagickBooleanType recursive,
1953  ExceptionInfo *exception)
1954 {
1955  char
1956  key[MagickPathExtent];
1957 
1959  status;
1960 
1961  StringInfo
1962  *clone_profile;
1963 
1964  assert(image != (Image *) NULL);
1965  assert(image->signature == MagickCoreSignature);
1966  if (IsEventLogging() != MagickFalse)
1967  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1968  clone_profile=CloneStringInfo(profile);
1969  PatchCorruptProfile(name,clone_profile);
1970  if ((LocaleCompare(name,"xmp") == 0) &&
1971  (ValidateXMPProfile(image,clone_profile,exception) == MagickFalse))
1972  {
1973  clone_profile=DestroyStringInfo(clone_profile);
1974  return(MagickTrue);
1975  }
1976  if (image->profiles == (SplayTreeInfo *) NULL)
1978  DestroyProfile);
1979  (void) CopyMagickString(key,name,MagickPathExtent);
1980  LocaleLower(key);
1981  status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1982  ConstantString(key),clone_profile);
1983  if (status != MagickFalse)
1984  {
1985  if (LocaleCompare(name,"8bim") == 0)
1986  GetProfilesFromResourceBlock(image,clone_profile,exception);
1987  else
1988  if (recursive == MagickFalse)
1989  WriteTo8BimProfile(image,name,clone_profile);
1990  }
1991  return(status);
1992 }
1993 
1995  const StringInfo *profile,ExceptionInfo *exception)
1996 {
1997  return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1998 }
1999 
2000 /*
2001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2002 % %
2003 % %
2004 % %
2005 % S y n c I m a g e P r o f i l e s %
2006 % %
2007 % %
2008 % %
2009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2010 %
2011 % SyncImageProfiles() synchronizes image properties with the image profiles.
2012 % Currently we only support updating the EXIF resolution and orientation.
2013 %
2014 % The format of the SyncImageProfiles method is:
2015 %
2016 % MagickBooleanType SyncImageProfiles(Image *image)
2017 %
2018 % A description of each parameter follows:
2019 %
2020 % o image: the image.
2021 %
2022 */
2023 
2024 static inline int ReadProfileByte(unsigned char **p,size_t *length)
2025 {
2026  int
2027  c;
2028 
2029  if (*length < 1)
2030  return(EOF);
2031  c=(int) (*(*p)++);
2032  (*length)--;
2033  return(c);
2034 }
2035 
2036 static inline signed short ReadProfileShort(const EndianType endian,
2037  unsigned char *buffer)
2038 {
2039  union
2040  {
2041  unsigned int
2042  unsigned_value;
2043 
2044  signed int
2045  signed_value;
2046  } quantum;
2047 
2048  unsigned short
2049  value;
2050 
2051  if (endian == LSBEndian)
2052  {
2053  value=(unsigned short) buffer[1] << 8;
2054  value|=(unsigned short) buffer[0];
2055  quantum.unsigned_value=value & 0xffff;
2056  return(quantum.signed_value);
2057  }
2058  value=(unsigned short) buffer[0] << 8;
2059  value|=(unsigned short) buffer[1];
2060  quantum.unsigned_value=value & 0xffff;
2061  return(quantum.signed_value);
2062 }
2063 
2064 static inline signed int ReadProfileLong(const EndianType endian,
2065  unsigned char *buffer)
2066 {
2067  union
2068  {
2069  unsigned int
2070  unsigned_value;
2071 
2072  signed int
2073  signed_value;
2074  } quantum;
2075 
2076  unsigned int
2077  value;
2078 
2079  if (endian == LSBEndian)
2080  {
2081  value=(unsigned int) buffer[3] << 24;
2082  value|=(unsigned int) buffer[2] << 16;
2083  value|=(unsigned int) buffer[1] << 8;
2084  value|=(unsigned int) buffer[0];
2085  quantum.unsigned_value=value & 0xffffffff;
2086  return(quantum.signed_value);
2087  }
2088  value=(unsigned int) buffer[0] << 24;
2089  value|=(unsigned int) buffer[1] << 16;
2090  value|=(unsigned int) buffer[2] << 8;
2091  value|=(unsigned int) buffer[3];
2092  quantum.unsigned_value=value & 0xffffffff;
2093  return(quantum.signed_value);
2094 }
2095 
2096 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
2097 {
2098  signed int
2099  value;
2100 
2101  if (*length < 4)
2102  return(0);
2103  value=ReadProfileLong(MSBEndian,*p);
2104  (*length)-=4;
2105  *p+=4;
2106  return(value);
2107 }
2108 
2109 static inline signed short ReadProfileMSBShort(unsigned char **p,
2110  size_t *length)
2111 {
2112  signed short
2113  value;
2114 
2115  if (*length < 2)
2116  return(0);
2117  value=ReadProfileShort(MSBEndian,*p);
2118  (*length)-=2;
2119  *p+=2;
2120  return(value);
2121 }
2122 
2123 static inline void WriteProfileLong(const EndianType endian,
2124  const size_t value,unsigned char *p)
2125 {
2126  unsigned char
2127  buffer[4];
2128 
2129  if (endian == LSBEndian)
2130  {
2131  buffer[0]=(unsigned char) value;
2132  buffer[1]=(unsigned char) (value >> 8);
2133  buffer[2]=(unsigned char) (value >> 16);
2134  buffer[3]=(unsigned char) (value >> 24);
2135  (void) memcpy(p,buffer,4);
2136  return;
2137  }
2138  buffer[0]=(unsigned char) (value >> 24);
2139  buffer[1]=(unsigned char) (value >> 16);
2140  buffer[2]=(unsigned char) (value >> 8);
2141  buffer[3]=(unsigned char) value;
2142  (void) memcpy(p,buffer,4);
2143 }
2144 
2145 static void WriteProfileShort(const EndianType endian,
2146  const unsigned short value,unsigned char *p)
2147 {
2148  unsigned char
2149  buffer[2];
2150 
2151  if (endian == LSBEndian)
2152  {
2153  buffer[0]=(unsigned char) value;
2154  buffer[1]=(unsigned char) (value >> 8);
2155  (void) memcpy(p,buffer,2);
2156  return;
2157  }
2158  buffer[0]=(unsigned char) (value >> 8);
2159  buffer[1]=(unsigned char) value;
2160  (void) memcpy(p,buffer,2);
2161 }
2162 
2163 static MagickBooleanType SyncExifProfile(const Image *image,unsigned char *exif,
2164  size_t length)
2165 {
2166 #define MaxDirectoryStack 16
2167 #define EXIF_DELIMITER "\n"
2168 #define EXIF_NUM_FORMATS 12
2169 #define TAG_EXIF_OFFSET 0x8769
2170 #define TAG_INTEROP_OFFSET 0xa005
2171 
2172  typedef struct _DirectoryInfo
2173  {
2174  unsigned char
2175  *directory;
2176 
2177  size_t
2178  entry;
2179  } DirectoryInfo;
2180 
2181  DirectoryInfo
2182  directory_stack[MaxDirectoryStack];
2183 
2184  EndianType
2185  endian;
2186 
2187  size_t
2188  entry,
2189  number_entries;
2190 
2192  *exif_resources;
2193 
2194  ssize_t
2195  id,
2196  level,
2197  offset;
2198 
2199  static int
2200  format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2201 
2202  unsigned char
2203  *directory;
2204 
2205  if (length < 16)
2206  return(MagickFalse);
2207  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2208  if ((id != 0x4949) && (id != 0x4D4D))
2209  {
2210  while (length != 0)
2211  {
2212  if (ReadProfileByte(&exif,&length) != 0x45)
2213  continue;
2214  if (ReadProfileByte(&exif,&length) != 0x78)
2215  continue;
2216  if (ReadProfileByte(&exif,&length) != 0x69)
2217  continue;
2218  if (ReadProfileByte(&exif,&length) != 0x66)
2219  continue;
2220  if (ReadProfileByte(&exif,&length) != 0x00)
2221  continue;
2222  if (ReadProfileByte(&exif,&length) != 0x00)
2223  continue;
2224  break;
2225  }
2226  if (length < 16)
2227  return(MagickFalse);
2228  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2229  }
2230  endian=LSBEndian;
2231  if (id == 0x4949)
2232  endian=LSBEndian;
2233  else
2234  if (id == 0x4D4D)
2235  endian=MSBEndian;
2236  else
2237  return(MagickFalse);
2238  if (ReadProfileShort(endian,exif+2) != 0x002a)
2239  return(MagickFalse);
2240  /*
2241  This the offset to the first IFD.
2242  */
2243  offset=(ssize_t) ReadProfileLong(endian,exif+4);
2244  if ((offset < 0) || ((size_t) offset >= length))
2245  return(MagickFalse);
2246  directory=exif+offset;
2247  level=0;
2248  entry=0;
2249  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2250  (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2251  do
2252  {
2253  if (level > 0)
2254  {
2255  level--;
2256  directory=directory_stack[level].directory;
2257  entry=directory_stack[level].entry;
2258  }
2259  if ((directory < exif) || (directory > (exif+length-2)))
2260  break;
2261  /*
2262  Determine how many entries there are in the current IFD.
2263  */
2264  number_entries=ReadProfileShort(endian,directory);
2265  for ( ; entry < number_entries; entry++)
2266  {
2267  int
2268  components;
2269 
2270  unsigned char
2271  *p,
2272  *q;
2273 
2274  size_t
2275  number_bytes;
2276 
2277  ssize_t
2278  format,
2279  tag_value;
2280 
2281  q=(unsigned char *) (directory+2+(12*entry));
2282  if (q > (exif+length-12))
2283  break; /* corrupt EXIF */
2284  if (GetValueFromSplayTree(exif_resources,q) == q)
2285  break;
2286  (void) AddValueToSplayTree(exif_resources,q,q);
2287  tag_value=(ssize_t) ReadProfileShort(endian,q);
2288  format=(ssize_t) ReadProfileShort(endian,q+2);
2289  if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2290  break;
2291  components=(int) ReadProfileLong(endian,q+4);
2292  if (components < 0)
2293  break; /* corrupt EXIF */
2294  number_bytes=(size_t) components*format_bytes[format];
2295  if ((ssize_t) number_bytes < components)
2296  break; /* prevent overflow */
2297  if (number_bytes <= 4)
2298  p=q+8;
2299  else
2300  {
2301  /*
2302  The directory entry contains an offset.
2303  */
2304  offset=(ssize_t) ReadProfileLong(endian,q+8);
2305  if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2306  continue;
2307  if (~length < number_bytes)
2308  continue; /* prevent overflow */
2309  p=(unsigned char *) (exif+offset);
2310  }
2311  switch (tag_value)
2312  {
2313  case 0x011a:
2314  {
2315  (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2316  if (number_bytes == 8)
2317  (void) WriteProfileLong(endian,1UL,p+4);
2318  break;
2319  }
2320  case 0x011b:
2321  {
2322  (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2323  if (number_bytes == 8)
2324  (void) WriteProfileLong(endian,1UL,p+4);
2325  break;
2326  }
2327  case 0x0112:
2328  {
2329  if (number_bytes == 4)
2330  {
2331  (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2332  break;
2333  }
2334  (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2335  p);
2336  break;
2337  }
2338  case 0x0128:
2339  {
2340  if (number_bytes == 4)
2341  {
2342  (void) WriteProfileLong(endian,((size_t) image->units)+1,p);
2343  break;
2344  }
2345  (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2346  break;
2347  }
2348  default:
2349  break;
2350  }
2351  if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2352  {
2353  offset=(ssize_t) ReadProfileLong(endian,p);
2354  if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2355  {
2356  directory_stack[level].directory=directory;
2357  entry++;
2358  directory_stack[level].entry=entry;
2359  level++;
2360  directory_stack[level].directory=exif+offset;
2361  directory_stack[level].entry=0;
2362  level++;
2363  if ((directory+2+(12*number_entries)) > (exif+length))
2364  break;
2365  offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2366  number_entries));
2367  if ((offset != 0) && ((size_t) offset < length) &&
2368  (level < (MaxDirectoryStack-2)))
2369  {
2370  directory_stack[level].directory=exif+offset;
2371  directory_stack[level].entry=0;
2372  level++;
2373  }
2374  }
2375  break;
2376  }
2377  }
2378  } while (level > 0);
2379  exif_resources=DestroySplayTree(exif_resources);
2380  return(MagickTrue);
2381 }
2382 
2384  const StringInfo *profile)
2385 {
2386  size_t
2387  length;
2388 
2389  ssize_t
2390  count;
2391 
2392  unsigned char
2393  *p;
2394 
2395  unsigned short
2396  id;
2397 
2398  length=GetStringInfoLength(profile);
2399  p=GetStringInfoDatum(profile);
2400  while (length != 0)
2401  {
2402  if (ReadProfileByte(&p,&length) != 0x38)
2403  continue;
2404  if (ReadProfileByte(&p,&length) != 0x42)
2405  continue;
2406  if (ReadProfileByte(&p,&length) != 0x49)
2407  continue;
2408  if (ReadProfileByte(&p,&length) != 0x4D)
2409  continue;
2410  if (length < 7)
2411  return(MagickFalse);
2412  id=ReadProfileMSBShort(&p,&length);
2413  count=(ssize_t) ReadProfileByte(&p,&length);
2414  if ((count >= (ssize_t) length) || (count < 0))
2415  return(MagickFalse);
2416  p+=count;
2417  length-=count;
2418  if ((*p & 0x01) == 0)
2419  (void) ReadProfileByte(&p,&length);
2420  count=(ssize_t) ReadProfileMSBLong(&p,&length);
2421  if ((count > (ssize_t) length) || (count < 0))
2422  return(MagickFalse);
2423  if ((id == 0x3ED) && (count == 16))
2424  {
2425  if (image->units == PixelsPerCentimeterResolution)
2427  image->resolution.x*2.54*65536.0),p);
2428  else
2430  image->resolution.x*65536.0),p);
2431  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2432  if (image->units == PixelsPerCentimeterResolution)
2434  image->resolution.y*2.54*65536.0),p+8);
2435  else
2437  image->resolution.y*65536.0),p+8);
2438  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2439  }
2440  if (id == 0x0422)
2441  (void) SyncExifProfile(image,p,count);
2442  p+=count;
2443  length-=count;
2444  }
2445  return(MagickTrue);
2446 }
2447 
2449 {
2451  status;
2452 
2453  StringInfo
2454  *profile;
2455 
2456  status=MagickTrue;
2457  profile=(StringInfo *) GetImageProfile(image,"8BIM");
2458  if (profile != (StringInfo *) NULL)
2459  if (Sync8BimProfile(image,profile) == MagickFalse)
2460  status=MagickFalse;
2461  profile=(StringInfo *) GetImageProfile(image,"EXIF");
2462  if (profile != (StringInfo *) NULL)
2463  if (SyncExifProfile(image,GetStringInfoDatum(profile),
2464  GetStringInfoLength(profile)) == MagickFalse)
2465  status=MagickFalse;
2466  return(status);
2467 }
2468 
2469 static void UpdateClipPath(unsigned char *blob,size_t length,
2470  const size_t old_columns,const size_t old_rows,
2471  const RectangleInfo *new_geometry)
2472 {
2473  ssize_t
2474  i;
2475 
2476  ssize_t
2477  knot_count,
2478  selector;
2479 
2480  knot_count=0;
2481  while (length != 0)
2482  {
2483  selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2484  switch (selector)
2485  {
2486  case 0:
2487  case 3:
2488  {
2489  if (knot_count != 0)
2490  {
2491  blob+=24;
2492  length-=MagickMin(24,(ssize_t) length);
2493  break;
2494  }
2495  /*
2496  Expected subpath length record.
2497  */
2498  knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2499  blob+=22;
2500  length-=MagickMin(22,(ssize_t) length);
2501  break;
2502  }
2503  case 1:
2504  case 2:
2505  case 4:
2506  case 5:
2507  {
2508  if (knot_count == 0)
2509  {
2510  /*
2511  Unexpected subpath knot.
2512  */
2513  blob+=24;
2514  length-=MagickMin(24,(ssize_t) length);
2515  break;
2516  }
2517  /*
2518  Add sub-path knot
2519  */
2520  for (i=0; i < 3; i++)
2521  {
2522  double
2523  x,
2524  y;
2525 
2526  signed int
2527  xx,
2528  yy;
2529 
2530  y=(double) ReadProfileMSBLong(&blob,&length);
2531  y=y*old_rows/4096.0/4096.0;
2532  y-=new_geometry->y;
2533  yy=(signed int) ((y*4096*4096)/new_geometry->height);
2534  WriteProfileLong(MSBEndian,(size_t) yy,blob-4);
2535  x=(double) ReadProfileMSBLong(&blob,&length);
2536  x=x*old_columns/4096.0/4096.0;
2537  x-=new_geometry->x;
2538  xx=(signed int) ((x*4096*4096)/new_geometry->width);
2539  WriteProfileLong(MSBEndian,(size_t) xx,blob-4);
2540  }
2541  knot_count--;
2542  break;
2543  }
2544  case 6:
2545  case 7:
2546  case 8:
2547  default:
2548  {
2549  blob+=24;
2550  length-=MagickMin(24,(ssize_t) length);
2551  break;
2552  }
2553  }
2554  }
2555 }
2556 
2558  const size_t old_columns,const size_t old_rows,
2559  const RectangleInfo *new_geometry)
2560 {
2561  const StringInfo
2562  *profile;
2563 
2564  size_t
2565  length;
2566 
2567  ssize_t
2568  count,
2569  id;
2570 
2571  unsigned char
2572  *info;
2573 
2574  assert(image != (Image *) NULL);
2575  assert(new_geometry != (RectangleInfo *) NULL);
2576  profile=GetImageProfile(image,"8bim");
2577  if (profile == (StringInfo *) NULL)
2578  return;
2579  length=GetStringInfoLength(profile);
2580  info=GetStringInfoDatum(profile);
2581  while (length > 0)
2582  {
2583  if (ReadProfileByte(&info,&length) != (unsigned char) '8')
2584  continue;
2585  if (ReadProfileByte(&info,&length) != (unsigned char) 'B')
2586  continue;
2587  if (ReadProfileByte(&info,&length) != (unsigned char) 'I')
2588  continue;
2589  if (ReadProfileByte(&info,&length) != (unsigned char) 'M')
2590  continue;
2591  id=(ssize_t) ReadProfileMSBShort(&info,&length);
2592  count=(ssize_t) ReadProfileByte(&info,&length);
2593  if ((count != 0) && ((size_t) count <= length))
2594  {
2595  info+=count;
2596  length-=count;
2597  }
2598  if ((count & 0x01) == 0)
2599  (void) ReadProfileByte(&info,&length);
2600  count=(ssize_t) ReadProfileMSBLong(&info,&length);
2601  if ((count < 0) || ((size_t) count > length))
2602  {
2603  length=0;
2604  continue;
2605  }
2606  if ((id > 1999) && (id < 2999))
2607  UpdateClipPath(info,(size_t) count,old_columns,old_rows,new_geometry);
2608  info+=count;
2609  length-=MagickMin(count,(ssize_t) length);
2610  }
2611 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:253
MagickExport MagickBooleanType IsStringFalse(const char *value)
Definition: string.c:1429
MagickExport int CompareStringInfo(const StringInfo *target, const StringInfo *source)
Definition: string.c:344
MagickExport MagickBooleanType IsOptionMember(const char *option, const char *options)
Definition: option.c:2832
static MagickBooleanType Sync8BimProfile(const Image *image, const StringInfo *profile)
Definition: profile.c:2383
MagickExport MagickBooleanType AddValueToSplayTree(SplayTreeInfo *splay_tree, const void *key, const void *value)
Definition: splay-tree.c:154
MagickProgressMonitor progress_monitor
Definition: image.h:303
ImageType type
Definition: image.h:264
static signed int ReadProfileLong(const EndianType endian, unsigned char *buffer)
Definition: profile.c:2064
static Quantum GetPixelRed(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static MagickBooleanType SetImageProfileInternal(Image *, const char *, const StringInfo *, const MagickBooleanType, ExceptionInfo *)
Definition: profile.c:1951
MagickExport MagickBooleanType DeleteImageProfile(Image *image, const char *name)
Definition: profile.c:195
static const unsigned char * ReadResourceByte(const unsigned char *p, unsigned char *quantum)
Definition: profile.c:1565
static DoublePixelPacket ** AcquirePixelTLS(const size_t count)
Definition: quantize.c:1440
unsigned char * datum
Definition: string_.h:33
static void SetPixelGray(const Image *magick_restrict image, const Quantum gray, Quantum *magick_restrict pixel)
#define ProfileImageTag
#define ThrowProfileException(severity, tag, context)
Image * image
Definition: profile.c:121
MagickExport const char * GetImageArtifact(const Image *image, const char *artifact)
Definition: artifact.c:274
static void * DestroyProfile(void *profile)
Definition: profile.c:1560
struct _CMSExceptionInfo CMSExceptionInfo
MagickExport void DestroyImageProfiles(Image *image)
Definition: profile.c:229
MagickExport void ConcatenateStringInfo(StringInfo *string_info, const StringInfo *source)
Definition: string.c:518
MagickExport size_t CopyMagickString(char *magick_restrict destination, const char *magick_restrict source, const size_t length)
Definition: string.c:731
ResolutionType units
Definition: image.h:198
static void WriteProfileShort(const EndianType endian, const unsigned short value, unsigned char *p)
Definition: profile.c:2145
unsigned char * info
Definition: profile.c:112
size_t width
Definition: geometry.h:132
static MagickBooleanType SyncExifProfile(const Image *image, unsigned char *exif, size_t length)
Definition: profile.c:2163
#define ThrowBinaryException(severity, tag, context)
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:133
EndianType
Definition: quantum.h:29
Definition: image.h:151
double x
Definition: geometry.h:125
#define MagickCoreSignature
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:300
void * profiles
Definition: image.h:195
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1178
static MagickBooleanType ValidateXMPProfile(Image *image, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1942
#define MaxDirectoryStack
MagickBooleanType
Definition: magick-type.h:161
MagickExport void LocaleLower(char *string)
Definition: locale.c:1450
static void WriteProfileLong(const EndianType endian, const size_t value, unsigned char *p)
Definition: profile.c:2123
MagickBooleanType black_point_compensation
Definition: image.h:258
static ssize_t CastDoubleToLong(const double x)
Definition: image-private.h:55
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:815
static void GetProfilesFromResourceBlock(Image *image, const StringInfo *resource_block, ExceptionInfo *exception)
Definition: profile.c:1712
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:665
MagickExport MagickBooleanType CloneImageProfiles(Image *image, const Image *clone_image)
Definition: profile.c:152
MagickExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition: locale.c:1524
double y
Definition: geometry.h:125
static int GetOpenMPThreadId(void)
static signed short ReadProfileShort(const EndianType endian, unsigned char *buffer)
Definition: profile.c:2036
MagickExport const StringInfo * GetImageProfile(const Image *image, const char *name)
Definition: profile.c:259
#define magick_unused(x)
static MagickBooleanType SetsRGBImageProfile(Image *image, ExceptionInfo *exception)
Definition: profile.c:640
size_t signature
Definition: profile.c:115
static void UpdateClipPath(unsigned char *blob, size_t length, const size_t old_columns, const size_t old_rows, const RectangleInfo *new_geometry)
Definition: profile.c:2469
MagickExport SplayTreeInfo * DestroySplayTree(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:682
#define MagickPathExtent
static Quantum GetPixelGreen(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static void WriteTo8BimProfile(Image *, const char *, const StringInfo *)
Definition: profile.c:1603
MagickExport MagickBooleanType IsEventLogging(void)
Definition: log.c:763
PixelTrait alpha_trait
Definition: image.h:280
MagickExport SplayTreeInfo * NewSplayTree(int(*compare)(const void *, const void *), void *(*relinquish_key)(void *), void *(*relinquish_value)(void *))
Definition: splay-tree.c:1141
static Quantum GetPixelBlack(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
MagickPrivate void Update8BIMClipPath(const Image *image, const size_t old_columns, const size_t old_rows, const RectangleInfo *new_geometry)
Definition: profile.c:2557
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1145
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1699
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
Definition: resource.c:795
static const unsigned char * ReadResourceShort(const unsigned char *p, unsigned short *quantum)
Definition: profile.c:1582
ssize_t x
Definition: geometry.h:136
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
size_t height
Definition: geometry.h:132
static void SetPixelBlue(const Image *magick_restrict image, const Quantum blue, Quantum *magick_restrict pixel)
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2620
MagickExport StringInfo * RemoveImageProfile(Image *image, const char *name)
Definition: profile.c:1477
MagickExport const void * GetValueFromSplayTree(SplayTreeInfo *splay_tree, const void *key)
Definition: splay-tree.c:921
MagickExport char * GetNextImageProfile(const Image *image)
Definition: profile.c:298
MagickExport StringInfo * AcquireStringInfo(const size_t length)
Definition: string.c:151
MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
Definition: profile.c:2448
MagickExport MagickBooleanType SetImageProfile(Image *image, const char *name, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1994
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1406
char filename[MagickPathExtent]
Definition: image.h:319
MagickExport SplayTreeInfo * CloneSplayTree(SplayTreeInfo *splay_tree, void *(*clone_key)(void *), void *(*clone_value)(void *))
Definition: splay-tree.c:346
#define GetMagickModule()
Definition: log.h:28
MagickExport int CompareSplayTreeString(const void *target, const void *source)
Definition: splay-tree.c:412
RenderingIntent rendering_intent
Definition: image.h:192
MagickExport const void * GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:769
#define EXIF_NUM_FORMATS
unsigned short Quantum
Definition: magick-type.h:86
MagickExport void SetStringInfoLength(StringInfo *string_info, const size_t length)
Definition: string.c:1708
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1418
MagickExport const char * GetImageProperty(const Image *image, const char *property, ExceptionInfo *exception)
Definition: property.c:2245
static signed int ReadProfileMSBLong(unsigned char **p, size_t *length)
Definition: profile.c:2096
static DoublePixelPacket ** DestroyPixelTLS(DoublePixelPacket **pixels)
Definition: quantize.c:1427
#define TYPE_XYZ_8
MagickExport void * RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree, const void *key)
Definition: splay-tree.c:1299
MagickExport MagickBooleanType DeleteNodeFromSplayTree(SplayTreeInfo *splay_tree, const void *key)
Definition: splay-tree.c:603
static void WriteResourceLong(unsigned char *p, const unsigned int quantum)
Definition: profile.c:1590
size_t length
Definition: profile.c:109
#define MagickMin(x, y)
Definition: image-private.h:39
ColorspaceType
Definition: colorspace.h:25
MagickExport void ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:1472
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1162
PointInfo resolution
Definition: image.h:209
#define magick_unreferenced(x)
#define TAG_EXIF_OFFSET
static int ReadProfileByte(unsigned char **p, size_t *length)
Definition: profile.c:2024
static void SetPixelRed(const Image *magick_restrict image, const Quantum red, Quantum *magick_restrict pixel)
char * name
Definition: profile.c:106
ResolutionType
Definition: image.h:89
#define MagickPrivate
MagickExport void ResetImageProfileIterator(const Image *image)
Definition: profile.c:1518
size_t length
Definition: string_.h:36
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1101
OrientationType orientation
Definition: image.h:166
ssize_t y
Definition: geometry.h:136
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
MagickExport MagickBooleanType ProfileImage(Image *image, const char *name, const void *datum, const size_t length, ExceptionInfo *exception)
Definition: profile.c:933
static void SetPixelBlack(const Image *magick_restrict image, const Quantum black, Quantum *magick_restrict pixel)
static Quantum GetPixelBlue(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
#define TAG_INTEROP_OFFSET
MagickExport size_t GetStringInfoLength(const StringInfo *string_info)
Definition: string.c:1207
static signed short ReadProfileMSBShort(unsigned char **p, size_t *length)
Definition: profile.c:2109
MagickExport char * ConstantString(const char *source)
Definition: string.c:678
static const unsigned char * ReadResourceLong(const unsigned char *p, unsigned int *quantum)
Definition: profile.c:1572
ColorspaceType colorspace
Definition: image.h:157
MagickExport StringInfo * CloneStringInfo(const StringInfo *string_info)
Definition: string.c:302
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
static void PatchCorruptProfile(const char *name, StringInfo *profile)
Definition: profile.c:1861
MagickExport void SetStringInfoDatum(StringInfo *string_info, const unsigned char *source)
Definition: string.c:1675
MagickBooleanType debug
Definition: image.h:334
ExceptionInfo * exception
Definition: profile.c:124
static void SetPixelGreen(const Image *magick_restrict image, const Quantum green, Quantum *magick_restrict pixel)
MagickExport void SetStringInfo(StringInfo *string_info, const StringInfo *source)
Definition: string.c:1635