MagickCore  7.1.0
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-2021 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  if (image->debug != MagickFalse)
158  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
159  assert(clone_image != (const Image *) NULL);
160  assert(clone_image->signature == MagickCoreSignature);
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 (image->debug != 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 (image->debug != 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 (image->debug != 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 **DestroyPixelThreadSet(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 **AcquirePixelThreadSet(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(DestroyPixelThreadSet(pixels));
444  }
445  return(pixels);
446 }
447 
448 static cmsHTRANSFORM *DestroyTransformThreadSet(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 *AcquireTransformThreadSet(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(DestroyTransformThreadSet(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  if (image->debug != MagickFalse)
962  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
963  assert(name != (const char *) NULL);
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=AcquireTransformThreadSet(&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=AcquirePixelThreadSet(image->columns,
1334  source_info.channels,highres);
1335  target_info.pixels=AcquirePixelThreadSet(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=DestroyPixelThreadSet(target_info.pixels);
1341  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1342  transform=DestroyTransformThreadSet(transform);
1344  "MemoryAllocationFailed",image->filename);
1345  }
1346  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1347  {
1348  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1349  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1350  transform=DestroyTransformThreadSet(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=DestroyPixelThreadSet(target_info.pixels);
1435  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1436  transform=DestroyTransformThreadSet(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 (image->debug != 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 (image->debug != 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 (image->debug != 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 
2164 {
2165  size_t
2166  length;
2167 
2168  ssize_t
2169  count;
2170 
2171  unsigned char
2172  *p;
2173 
2174  unsigned short
2175  id;
2176 
2177  length=GetStringInfoLength(profile);
2178  p=GetStringInfoDatum(profile);
2179  while (length != 0)
2180  {
2181  if (ReadProfileByte(&p,&length) != 0x38)
2182  continue;
2183  if (ReadProfileByte(&p,&length) != 0x42)
2184  continue;
2185  if (ReadProfileByte(&p,&length) != 0x49)
2186  continue;
2187  if (ReadProfileByte(&p,&length) != 0x4D)
2188  continue;
2189  if (length < 7)
2190  return(MagickFalse);
2191  id=ReadProfileMSBShort(&p,&length);
2192  count=(ssize_t) ReadProfileByte(&p,&length);
2193  if ((count >= (ssize_t) length) || (count < 0))
2194  return(MagickFalse);
2195  p+=count;
2196  length-=count;
2197  if ((*p & 0x01) == 0)
2198  (void) ReadProfileByte(&p,&length);
2199  count=(ssize_t) ReadProfileMSBLong(&p,&length);
2200  if ((count > (ssize_t) length) || (count < 0))
2201  return(MagickFalse);
2202  if ((id == 0x3ED) && (count == 16))
2203  {
2204  if (image->units == PixelsPerCentimeterResolution)
2206  image->resolution.x*2.54*65536.0),p);
2207  else
2209  image->resolution.x*65536.0),p);
2210  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2211  if (image->units == PixelsPerCentimeterResolution)
2213  image->resolution.y*2.54*65536.0),p+8);
2214  else
2216  image->resolution.y*65536.0),p+8);
2217  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2218  }
2219  p+=count;
2220  length-=count;
2221  }
2222  return(MagickTrue);
2223 }
2224 
2226 {
2227 #define MaxDirectoryStack 16
2228 #define EXIF_DELIMITER "\n"
2229 #define EXIF_NUM_FORMATS 12
2230 #define TAG_EXIF_OFFSET 0x8769
2231 #define TAG_INTEROP_OFFSET 0xa005
2232 
2233  typedef struct _DirectoryInfo
2234  {
2235  unsigned char
2236  *directory;
2237 
2238  size_t
2239  entry;
2240  } DirectoryInfo;
2241 
2242  DirectoryInfo
2243  directory_stack[MaxDirectoryStack];
2244 
2245  EndianType
2246  endian;
2247 
2248  size_t
2249  entry,
2250  length,
2251  number_entries;
2252 
2254  *exif_resources;
2255 
2256  ssize_t
2257  id,
2258  level,
2259  offset;
2260 
2261  static int
2262  format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2263 
2264  unsigned char
2265  *directory,
2266  *exif;
2267 
2268  /*
2269  Set EXIF resolution tag.
2270  */
2271  length=GetStringInfoLength(profile);
2272  exif=GetStringInfoDatum(profile);
2273  if (length < 16)
2274  return(MagickFalse);
2275  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2276  if ((id != 0x4949) && (id != 0x4D4D))
2277  {
2278  while (length != 0)
2279  {
2280  if (ReadProfileByte(&exif,&length) != 0x45)
2281  continue;
2282  if (ReadProfileByte(&exif,&length) != 0x78)
2283  continue;
2284  if (ReadProfileByte(&exif,&length) != 0x69)
2285  continue;
2286  if (ReadProfileByte(&exif,&length) != 0x66)
2287  continue;
2288  if (ReadProfileByte(&exif,&length) != 0x00)
2289  continue;
2290  if (ReadProfileByte(&exif,&length) != 0x00)
2291  continue;
2292  break;
2293  }
2294  if (length < 16)
2295  return(MagickFalse);
2296  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2297  }
2298  endian=LSBEndian;
2299  if (id == 0x4949)
2300  endian=LSBEndian;
2301  else
2302  if (id == 0x4D4D)
2303  endian=MSBEndian;
2304  else
2305  return(MagickFalse);
2306  if (ReadProfileShort(endian,exif+2) != 0x002a)
2307  return(MagickFalse);
2308  /*
2309  This the offset to the first IFD.
2310  */
2311  offset=(ssize_t) ReadProfileLong(endian,exif+4);
2312  if ((offset < 0) || ((size_t) offset >= length))
2313  return(MagickFalse);
2314  directory=exif+offset;
2315  level=0;
2316  entry=0;
2317  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2318  (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2319  do
2320  {
2321  if (level > 0)
2322  {
2323  level--;
2324  directory=directory_stack[level].directory;
2325  entry=directory_stack[level].entry;
2326  }
2327  if ((directory < exif) || (directory > (exif+length-2)))
2328  break;
2329  /*
2330  Determine how many entries there are in the current IFD.
2331  */
2332  number_entries=ReadProfileShort(endian,directory);
2333  for ( ; entry < number_entries; entry++)
2334  {
2335  int
2336  components;
2337 
2338  unsigned char
2339  *p,
2340  *q;
2341 
2342  size_t
2343  number_bytes;
2344 
2345  ssize_t
2346  format,
2347  tag_value;
2348 
2349  q=(unsigned char *) (directory+2+(12*entry));
2350  if (q > (exif+length-12))
2351  break; /* corrupt EXIF */
2352  if (GetValueFromSplayTree(exif_resources,q) == q)
2353  break;
2354  (void) AddValueToSplayTree(exif_resources,q,q);
2355  tag_value=(ssize_t) ReadProfileShort(endian,q);
2356  format=(ssize_t) ReadProfileShort(endian,q+2);
2357  if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2358  break;
2359  components=(int) ReadProfileLong(endian,q+4);
2360  if (components < 0)
2361  break; /* corrupt EXIF */
2362  number_bytes=(size_t) components*format_bytes[format];
2363  if ((ssize_t) number_bytes < components)
2364  break; /* prevent overflow */
2365  if (number_bytes <= 4)
2366  p=q+8;
2367  else
2368  {
2369  /*
2370  The directory entry contains an offset.
2371  */
2372  offset=(ssize_t) ReadProfileLong(endian,q+8);
2373  if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2374  continue;
2375  if (~length < number_bytes)
2376  continue; /* prevent overflow */
2377  p=(unsigned char *) (exif+offset);
2378  }
2379  switch (tag_value)
2380  {
2381  case 0x011a:
2382  {
2383  (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2384  if (number_bytes == 8)
2385  (void) WriteProfileLong(endian,1UL,p+4);
2386  break;
2387  }
2388  case 0x011b:
2389  {
2390  (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2391  if (number_bytes == 8)
2392  (void) WriteProfileLong(endian,1UL,p+4);
2393  break;
2394  }
2395  case 0x0112:
2396  {
2397  if (number_bytes == 4)
2398  {
2399  (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2400  break;
2401  }
2402  (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2403  p);
2404  break;
2405  }
2406  case 0x0128:
2407  {
2408  if (number_bytes == 4)
2409  {
2410  (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2411  break;
2412  }
2413  (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2414  break;
2415  }
2416  default:
2417  break;
2418  }
2419  if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2420  {
2421  offset=(ssize_t) ReadProfileLong(endian,p);
2422  if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2423  {
2424  directory_stack[level].directory=directory;
2425  entry++;
2426  directory_stack[level].entry=entry;
2427  level++;
2428  directory_stack[level].directory=exif+offset;
2429  directory_stack[level].entry=0;
2430  level++;
2431  if ((directory+2+(12*number_entries)) > (exif+length))
2432  break;
2433  offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2434  number_entries));
2435  if ((offset != 0) && ((size_t) offset < length) &&
2436  (level < (MaxDirectoryStack-2)))
2437  {
2438  directory_stack[level].directory=exif+offset;
2439  directory_stack[level].entry=0;
2440  level++;
2441  }
2442  }
2443  break;
2444  }
2445  }
2446  } while (level > 0);
2447  exif_resources=DestroySplayTree(exif_resources);
2448  return(MagickTrue);
2449 }
2450 
2452 {
2454  status;
2455 
2456  StringInfo
2457  *profile;
2458 
2459  status=MagickTrue;
2460  profile=(StringInfo *) GetImageProfile(image,"8BIM");
2461  if (profile != (StringInfo *) NULL)
2462  if (Sync8BimProfile(image,profile) == MagickFalse)
2463  status=MagickFalse;
2464  profile=(StringInfo *) GetImageProfile(image,"EXIF");
2465  if (profile != (StringInfo *) NULL)
2466  if (SyncExifProfile(image,profile) == MagickFalse)
2467  status=MagickFalse;
2468  return(status);
2469 }
2470 
2471 static void UpdateClipPath(unsigned char *blob,size_t length,
2472  const size_t old_columns,const size_t old_rows,
2473  const RectangleInfo *new_geometry)
2474 {
2475  ssize_t
2476  i;
2477 
2478  ssize_t
2479  knot_count,
2480  selector;
2481 
2482  knot_count=0;
2483  while (length != 0)
2484  {
2485  selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2486  switch (selector)
2487  {
2488  case 0:
2489  case 3:
2490  {
2491  if (knot_count != 0)
2492  {
2493  blob+=24;
2494  length-=MagickMin(24,(ssize_t) length);
2495  break;
2496  }
2497  /*
2498  Expected subpath length record.
2499  */
2500  knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2501  blob+=22;
2502  length-=MagickMin(22,(ssize_t) length);
2503  break;
2504  }
2505  case 1:
2506  case 2:
2507  case 4:
2508  case 5:
2509  {
2510  if (knot_count == 0)
2511  {
2512  /*
2513  Unexpected subpath knot.
2514  */
2515  blob+=24;
2516  length-=MagickMin(24,(ssize_t) length);
2517  break;
2518  }
2519  /*
2520  Add sub-path knot
2521  */
2522  for (i=0; i < 3; i++)
2523  {
2524  double
2525  x,
2526  y;
2527 
2528  signed int
2529  xx,
2530  yy;
2531 
2532  y=(double) ReadProfileMSBLong(&blob,&length);
2533  y=y*old_rows/4096.0/4096.0;
2534  y-=new_geometry->y;
2535  yy=(signed int) ((y*4096*4096)/new_geometry->height);
2536  WriteProfileLong(MSBEndian,(size_t) yy,blob-4);
2537  x=(double) ReadProfileMSBLong(&blob,&length);
2538  x=x*old_columns/4096.0/4096.0;
2539  x-=new_geometry->x;
2540  xx=(signed int) ((x*4096*4096)/new_geometry->width);
2541  WriteProfileLong(MSBEndian,(size_t) xx,blob-4);
2542  }
2543  knot_count--;
2544  break;
2545  }
2546  case 6:
2547  case 7:
2548  case 8:
2549  default:
2550  {
2551  blob+=24;
2552  length-=MagickMin(24,(ssize_t) length);
2553  break;
2554  }
2555  }
2556  }
2557 }
2558 
2560  const size_t old_columns,const size_t old_rows,
2561  const RectangleInfo *new_geometry)
2562 {
2563  const StringInfo
2564  *profile;
2565 
2566  size_t
2567  length;
2568 
2569  ssize_t
2570  count,
2571  id;
2572 
2573  unsigned char
2574  *info;
2575 
2576  assert(image != (Image *) NULL);
2577  assert(new_geometry != (RectangleInfo *) NULL);
2578  profile=GetImageProfile(image,"8bim");
2579  if (profile == (StringInfo *) NULL)
2580  return;
2581  length=GetStringInfoLength(profile);
2582  info=GetStringInfoDatum(profile);
2583  while (length > 0)
2584  {
2585  if (ReadProfileByte(&info,&length) != (unsigned char) '8')
2586  continue;
2587  if (ReadProfileByte(&info,&length) != (unsigned char) 'B')
2588  continue;
2589  if (ReadProfileByte(&info,&length) != (unsigned char) 'I')
2590  continue;
2591  if (ReadProfileByte(&info,&length) != (unsigned char) 'M')
2592  continue;
2593  id=(ssize_t) ReadProfileMSBShort(&info,&length);
2594  count=(ssize_t) ReadProfileByte(&info,&length);
2595  if ((count != 0) && ((size_t) count <= length))
2596  {
2597  info+=count;
2598  length-=count;
2599  }
2600  if ((count & 0x01) == 0)
2601  (void) ReadProfileByte(&info,&length);
2602  count=(ssize_t) ReadProfileMSBLong(&info,&length);
2603  if ((count < 0) || ((size_t) count > length))
2604  {
2605  length=0;
2606  continue;
2607  }
2608  if ((id > 1999) && (id < 2999))
2609  UpdateClipPath(info,(size_t) count,old_columns,old_rows,new_geometry);
2610  info+=count;
2611  length-=MagickMin(count,(ssize_t) length);
2612  }
2613 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
MagickExport MagickBooleanType IsStringFalse(const char *value)
Definition: string.c:1427
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:2810
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
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:273
static void * DestroyProfile(void *profile)
Definition: profile.c:1560
struct _CMSExceptionInfo CMSExceptionInfo
MagickBooleanType SyncExifProfile(Image *image, StringInfo *profile)
Definition: profile.c:2225
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:131
#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:124
#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:299
void * profiles
Definition: image.h:195
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1176
static MagickBooleanType ValidateXMPProfile(Image *image, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1942
#define MaxDirectoryStack
MagickBooleanType
Definition: magick-type.h:165
MagickExport void LocaleLower(char *string)
Definition: locale.c:1443
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
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:1523
double y
Definition: geometry.h:124
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:2471
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
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:2559
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:1660
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
Definition: resource.c:793
static DoublePixelPacket ** DestroyPixelThreadSet(DoublePixelPacket **pixels)
Definition: quantize.c:1427
static const unsigned char * ReadResourceShort(const unsigned char *p, unsigned short *quantum)
Definition: profile.c:1582
ssize_t x
Definition: geometry.h:135
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
static DoublePixelPacket ** AcquirePixelThreadSet(const size_t count)
Definition: quantize.c:1440
size_t height
Definition: geometry.h:131
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:2614
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:2451
MagickExport MagickBooleanType SetImageProfile(Image *image, const char *name, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1994
static MagickBooleanType Sync8BimProfile(Image *image, StringInfo *profile)
Definition: profile.c:2163
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1399
static ssize_t CastDoubleToLong(const double value)
Definition: image-private.h:53
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:1706
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1420
MagickExport const char * GetImageProperty(const Image *image, const char *property, ExceptionInfo *exception)
Definition: property.c:2216
static signed int ReadProfileMSBLong(unsigned char **p, size_t *length)
Definition: profile.c:2096
#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:37
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:1100
OrientationType orientation
Definition: image.h:166
ssize_t y
Definition: geometry.h:135
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:1205
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:1673
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:1633