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,
371  translate;
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,
417  const size_t channels,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  ssize_t
469  i;
470 
471  size_t
472  number_threads;
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) \
529  (source_info->scale*QuantumScale*(pixel)+source_info->translate)
530 #define SetLCMSPixel(target_info,pixel) \
531  ClampToQuantum(target_info->scale*QuantumRange*(pixel)+target_info->translate)
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));
543  if (source_info->channels > 1)
544  {
545  *p++=GetLCMSPixel(source_info,GetPixelGreen(image,q));
546  *p++=GetLCMSPixel(source_info,GetPixelBlue(image,q));
547  }
548  if (source_info->channels > 3)
549  *p++=GetLCMSPixel(source_info,GetPixelBlack(image,q));
550  q+=GetPixelChannels(image);
551  }
552  cmsDoTransform(transform[id],source_info->pixels[id],
553  target_info->pixels[id],(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),q);
560  else
561  SetPixelRed(image,SetLCMSPixel(target_info,*p),q);
562  p++;
563  if (target_info->channels > 1)
564  {
565  SetPixelGreen(image,SetLCMSPixel(target_info,*p),q);
566  p++;
567  SetPixelBlue(image,SetLCMSPixel(target_info,*p),q);
568  p++;
569  }
570  if (target_info->channels > 3)
571  {
572  SetPixelBlack(image,SetLCMSPixel(target_info,*p),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],
603  target_info->pixels[id],(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 #endif
623 
625  ExceptionInfo *exception)
626 {
627  static unsigned char
628  sRGBProfile[] =
629  {
630  0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
631  0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
632  0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
633  0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
634  0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
635  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
636  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
637  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
641  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
642  0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
643  0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
644  0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
645  0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
646  0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
647  0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
648  0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
649  0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
650  0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
651  0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
652  0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
653  0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
654  0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
655  0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
656  0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
657  0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
658  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
659  0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
660  0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
661  0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
662  0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
663  0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
664  0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665  0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
666  0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
667  0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
668  0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
669  0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
670  0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671  0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
672  0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
673  0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
674  0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
675  0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
676  0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
677  0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
678  0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
679  0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
680  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
681  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
682  0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683  0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
684  0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
685  0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
690  0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
691  0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
692  0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
693  0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
694  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
695  0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
696  0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
697  0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
698  0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700  0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
701  0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
702  0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
703  0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704  0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
705  0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710  0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
711  0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
712  0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
713  0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
714  0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
715  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
716  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717  0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
718  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
719  0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
720  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721  0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
722  0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
723  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
724  0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
725  0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
726  0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
727  0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
728  0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
729  0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
730  0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
731  0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
732  0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
733  0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
734  0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
735  0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
736  0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
737  0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
738  0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
739  0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
740  0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
741  0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
742  0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
743  0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
744  0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
745  0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
746  0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
747  0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
748  0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
749  0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
750  0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
751  0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
752  0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
753  0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
754  0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
755  0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
756  0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
757  0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
758  0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
759  0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
760  0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
761  0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
762  0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
763  0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
764  0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
765  0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
766  0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
767  0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
768  0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
769  0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
770  0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
771  0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
772  0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
773  0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
774  0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
775  0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
776  0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
777  0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
778  0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
779  0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
780  0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
781  0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
782  0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
783  0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
784  0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
785  0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
786  0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
787  0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
788  0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
789  0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
790  0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
791  0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
792  0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
793  0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
794  0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
795  0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
796  0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
797  0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
798  0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
799  0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
800  0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
801  0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
802  0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
803  0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
804  0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
805  0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
806  0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
807  0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
808  0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
809  0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
810  0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
811  0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
812  0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
813  0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
814  0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
815  0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
816  0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
817  0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
818  0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
819  0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
820  0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
821  0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
822  0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
823  0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
824  0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
825  0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
826  0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
827  0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
828  0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
829  0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
830  0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
831  0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
832  0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
833  0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
834  0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
835  0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
836  0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
837  0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
838  0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
839  0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
840  0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
841  0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
842  0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
843  0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
844  0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
845  0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
846  0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
847  0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
848  0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
849  0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
850  0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
851  0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
852  0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
853  0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
854  0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
855  0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
856  0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
857  0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
858  0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
859  0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
860  0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
861  0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
862  0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
863  0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
864  0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
865  0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
866  0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
867  0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
868  0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
869  0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
870  0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
871  0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
872  0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
873  0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
874  0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
875  0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
876  0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
877  0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
878  0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
879  0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
880  0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
881  0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
882  0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
883  0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
884  0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
885  0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
886  0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
887  0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
888  0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
889  0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
890  0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
891  0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
892  0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
893  0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
894  0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
895  0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
896  0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
897  0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
898  };
899 
900  StringInfo
901  *profile;
902 
904  status;
905 
906  assert(image != (Image *) NULL);
907  assert(image->signature == MagickCoreSignature);
908  if (GetImageProfile(image,"icc") != (const StringInfo *) NULL)
909  return(MagickFalse);
910  profile=AcquireStringInfo(sizeof(sRGBProfile));
911  SetStringInfoDatum(profile,sRGBProfile);
912  status=SetImageProfile(image,"icc",profile,exception);
913  profile=DestroyStringInfo(profile);
914  return(status);
915 }
916 
918  const void *datum,const size_t length,ExceptionInfo *exception)
919 {
920 #define ProfileImageTag "Profile/Image"
921 #ifndef TYPE_XYZ_8
922  #define TYPE_XYZ_8 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(1))
923 #endif
924 #define ThrowProfileException(severity,tag,context) \
925 { \
926  if (profile != (StringInfo *) NULL) \
927  profile=DestroyStringInfo(profile); \
928  if (cms_context != (cmsContext) NULL) \
929  cmsDeleteContext(cms_context); \
930  if (source_info.profile != (cmsHPROFILE) NULL) \
931  (void) cmsCloseProfile(source_info.profile); \
932  if (target_info.profile != (cmsHPROFILE) NULL) \
933  (void) cmsCloseProfile(target_info.profile); \
934  ThrowBinaryException(severity,tag,context); \
935 }
936 
938  status;
939 
940  StringInfo
941  *profile;
942 
943  assert(image != (Image *) NULL);
944  assert(image->signature == MagickCoreSignature);
945  if (image->debug != MagickFalse)
946  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
947  assert(name != (const char *) NULL);
948  if ((datum == (const void *) NULL) || (length == 0))
949  {
950  char
951  *next;
952 
953  /*
954  Delete image profile(s).
955  */
957  for (next=GetNextImageProfile(image); next != (const char *) NULL; )
958  {
959  if (IsOptionMember(next,name) != MagickFalse)
960  {
961  (void) DeleteImageProfile(image,next);
963  }
964  next=GetNextImageProfile(image);
965  }
966  return(MagickTrue);
967  }
968  /*
969  Add a ICC, IPTC, or generic profile to the image.
970  */
971  status=MagickTrue;
972  profile=AcquireStringInfo((size_t) length);
973  SetStringInfoDatum(profile,(unsigned char *) datum);
974  if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
975  status=SetImageProfile(image,name,profile,exception);
976  else
977  {
978  const StringInfo
979  *icc_profile;
980 
981  icc_profile=GetImageProfile(image,"icc");
982  if ((icc_profile != (const StringInfo *) NULL) &&
983  (CompareStringInfo(icc_profile,profile) == 0))
984  {
985  const char
986  *value;
987 
988  value=GetImageProperty(image,"exif:ColorSpace",exception);
989  (void) value;
990  if (LocaleCompare(value,"1") != 0)
991  (void) SetsRGBImageProfile(image,exception);
992  value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
993  if (LocaleCompare(value,"R98.") != 0)
994  (void) SetsRGBImageProfile(image,exception);
995  icc_profile=GetImageProfile(image,"icc");
996  }
997  if ((icc_profile != (const StringInfo *) NULL) &&
998  (CompareStringInfo(icc_profile,profile) == 0))
999  {
1000  profile=DestroyStringInfo(profile);
1001  return(MagickTrue);
1002  }
1003 #if !defined(MAGICKCORE_LCMS_DELEGATE)
1004  (void) ThrowMagickException(exception,GetMagickModule(),
1005  MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
1006  "'%s' (LCMS)",image->filename);
1007 #else
1008  {
1009  cmsContext
1010  cms_context;
1011 
1013  cms_exception;
1014 
1015  LCMSInfo
1016  source_info,
1017  target_info;
1018 
1019  /*
1020  Transform pixel colors as defined by the color profiles.
1021  */
1022  cms_exception.image=image;
1023  cms_exception.exception=exception;
1024  cms_context=cmsCreateContext(NULL,&cms_exception);
1025  if (cms_context == (cmsContext) NULL)
1026  {
1027  profile=DestroyStringInfo(profile);
1029  "ColorspaceColorProfileMismatch",name);
1030  }
1031  cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
1032  source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1033  GetStringInfoDatum(profile),(cmsUInt32Number)
1034  GetStringInfoLength(profile));
1035  if (source_info.profile == (cmsHPROFILE) NULL)
1036  {
1037  profile=DestroyStringInfo(profile);
1038  cmsDeleteContext(cms_context);
1040  "ColorspaceColorProfileMismatch",name);
1041  }
1042  if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
1043  (icc_profile == (StringInfo *) NULL))
1044  status=SetImageProfile(image,name,profile,exception);
1045  else
1046  {
1047  CacheView
1048  *image_view;
1049 
1050  cmsColorSpaceSignature
1051  signature;
1052 
1053  cmsHTRANSFORM
1054  *magick_restrict transform;
1055 
1056  cmsUInt32Number
1057  flags;
1058 
1059 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1060  const char
1061  *artifact;
1062 #endif
1063 
1065  highres;
1066 
1068  progress;
1069 
1070  ssize_t
1071  y;
1072 
1073  target_info.profile=(cmsHPROFILE) NULL;
1074  if (icc_profile != (StringInfo *) NULL)
1075  {
1076  target_info.profile=source_info.profile;
1077  source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1078  GetStringInfoDatum(icc_profile),
1079  (cmsUInt32Number) GetStringInfoLength(icc_profile));
1080  if (source_info.profile == (cmsHPROFILE) NULL)
1082  "ColorspaceColorProfileMismatch",name);
1083  }
1084  highres=MagickTrue;
1085 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1086  artifact=GetImageArtifact(image,"profile:highres-transform");
1087  if (IsStringFalse(artifact) != MagickFalse)
1088  highres=MagickFalse;
1089 #endif
1090  source_info.scale=1.0;
1091  source_info.translate=0.0;
1092  source_info.colorspace=sRGBColorspace;
1093  source_info.channels=3;
1094  switch (cmsGetColorSpace(source_info.profile))
1095  {
1096  case cmsSigCmykData:
1097  {
1098  source_info.colorspace=CMYKColorspace;
1099  source_info.channels=4;
1100 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1101  if (highres == MagickFalse)
1102  source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1103  else
1104 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1105  if (highres == MagickFalse)
1106  source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1107  else
1108 #endif
1109  {
1110  source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1111  source_info.scale=100.0;
1112  }
1113  break;
1114  }
1115  case cmsSigGrayData:
1116  {
1117  source_info.colorspace=GRAYColorspace;
1118  source_info.channels=1;
1119 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1120  if (highres == MagickFalse)
1121  source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1122  else
1123 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1124  if (highres == MagickFalse)
1125  source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1126  else
1127 #endif
1128  source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1129  break;
1130  }
1131  case cmsSigLabData:
1132  {
1133  source_info.colorspace=LabColorspace;
1134 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1135  if (highres == MagickFalse)
1136  source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1137  else
1138 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1139  if (highres == MagickFalse)
1140  source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1141  else
1142 #endif
1143  {
1144  source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1145  source_info.scale=100.0;
1146  source_info.translate=(-0.5);
1147  }
1148  break;
1149  }
1150  case cmsSigRgbData:
1151  {
1152  source_info.colorspace=sRGBColorspace;
1153 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1154  if (highres == MagickFalse)
1155  source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1156  else
1157 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1158  if (highres == MagickFalse)
1159  source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1160  else
1161 #endif
1162  source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1163  break;
1164  }
1165  case cmsSigXYZData:
1166  {
1167  source_info.colorspace=XYZColorspace;
1168 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1169  if (highres == MagickFalse)
1170  source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1171  else
1172 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1173  if (highres == MagickFalse)
1174  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1175  else
1176 #endif
1177  source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1178  break;
1179  }
1180  default:
1182  "ColorspaceColorProfileMismatch",name);
1183  }
1184  signature=cmsGetPCS(source_info.profile);
1185  if (target_info.profile != (cmsHPROFILE) NULL)
1186  signature=cmsGetColorSpace(target_info.profile);
1187  target_info.scale=1.0;
1188  target_info.translate=0.0;
1189  target_info.channels=3;
1190  switch (signature)
1191  {
1192  case cmsSigCmykData:
1193  {
1194  target_info.colorspace=CMYKColorspace;
1195  target_info.channels=4;
1196 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1197  if (highres == MagickFalse)
1198  target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1199  else
1200 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1201  if (highres == MagickFalse)
1202  target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1203  else
1204 #endif
1205  {
1206  target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1207  target_info.scale=0.01;
1208  }
1209  break;
1210  }
1211  case cmsSigGrayData:
1212  {
1213  target_info.colorspace=GRAYColorspace;
1214  target_info.channels=1;
1215 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1216  if (highres == MagickFalse)
1217  target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1218  else
1219 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1220  if (highres == MagickFalse)
1221  target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1222  else
1223 #endif
1224  target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1225  break;
1226  }
1227  case cmsSigLabData:
1228  {
1229  target_info.colorspace=LabColorspace;
1230 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1231  if (highres == MagickFalse)
1232  target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1233  else
1234 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1235  if (highres == MagickFalse)
1236  target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1237  else
1238 #endif
1239  {
1240  target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1241  target_info.scale=0.01;
1242  target_info.translate=0.5;
1243  }
1244  break;
1245  }
1246  case cmsSigRgbData:
1247  {
1248  target_info.colorspace=sRGBColorspace;
1249 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1250  if (highres == MagickFalse)
1251  target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1252  else
1253 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1254  if (highres == MagickFalse)
1255  target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1256  else
1257 #endif
1258  target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1259  break;
1260  }
1261  case cmsSigXYZData:
1262  {
1263  target_info.colorspace=XYZColorspace;
1264 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1265  if (highres == MagickFalse)
1266  target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1267  else
1268 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1269  if (highres == MagickFalse)
1270  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1271  else
1272 #endif
1273  target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1274  break;
1275  }
1276  default:
1278  "ColorspaceColorProfileMismatch",name);
1279  }
1280  switch (image->rendering_intent)
1281  {
1282  case AbsoluteIntent:
1283  {
1284  target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1285  break;
1286  }
1287  case PerceptualIntent:
1288  {
1289  target_info.intent=INTENT_PERCEPTUAL;
1290  break;
1291  }
1292  case RelativeIntent:
1293  {
1294  target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1295  break;
1296  }
1297  case SaturationIntent:
1298  {
1299  target_info.intent=INTENT_SATURATION;
1300  break;
1301  }
1302  default:
1303  {
1304  target_info.intent=INTENT_PERCEPTUAL;
1305  break;
1306  }
1307  }
1308  flags=cmsFLAGS_HIGHRESPRECALC;
1309 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1310  if (image->black_point_compensation != MagickFalse)
1311  flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1312 #endif
1313  transform=AcquireTransformThreadSet(&source_info,&target_info,
1314  flags,cms_context);
1315  if (transform == (cmsHTRANSFORM *) NULL)
1316  ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1317  name);
1318  /*
1319  Transform image as dictated by the source & target image profiles.
1320  */
1321  source_info.pixels=AcquirePixelThreadSet(image->columns,
1322  source_info.channels,highres);
1323  target_info.pixels=AcquirePixelThreadSet(image->columns,
1324  target_info.channels,highres);
1325  if ((source_info.pixels == (void **) NULL) ||
1326  (target_info.pixels == (void **) NULL))
1327  {
1328  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1329  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1330  transform=DestroyTransformThreadSet(transform);
1332  "MemoryAllocationFailed",image->filename);
1333  }
1334  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1335  {
1336  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1337  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1338  transform=DestroyTransformThreadSet(transform);
1339  if (source_info.profile != (cmsHPROFILE) NULL)
1340  (void) cmsCloseProfile(source_info.profile);
1341  if (target_info.profile != (cmsHPROFILE) NULL)
1342  (void) cmsCloseProfile(target_info.profile);
1343  return(MagickFalse);
1344  }
1345  if (target_info.colorspace == CMYKColorspace)
1346  (void) SetImageColorspace(image,target_info.colorspace,exception);
1347  progress=0;
1348  image_view=AcquireAuthenticCacheView(image,exception);
1349 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1350  #pragma omp parallel for schedule(static) shared(status) \
1351  magick_number_threads(image,image,image->rows,1)
1352 #endif
1353  for (y=0; y < (ssize_t) image->rows; y++)
1354  {
1355  const int
1356  id = GetOpenMPThreadId();
1357 
1359  sync;
1360 
1361  Quantum
1362  *magick_restrict q;
1363 
1364  if (status == MagickFalse)
1365  continue;
1366  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1367  exception);
1368  if (q == (Quantum *) NULL)
1369  {
1370  status=MagickFalse;
1371  continue;
1372  }
1373  if (highres != MagickFalse)
1374  TransformDoublePixels(id,image,&source_info,&target_info,transform,q);
1375  else
1376  TransformQuantumPixels(id,image,&source_info,&target_info,transform,q);
1377  sync=SyncCacheViewAuthenticPixels(image_view,exception);
1378  if (sync == MagickFalse)
1379  status=MagickFalse;
1380  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1381  {
1383  proceed;
1384 
1385 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1386  #pragma omp atomic
1387 #endif
1388  progress++;
1389  proceed=SetImageProgress(image,ProfileImageTag,progress,
1390  image->rows);
1391  if (proceed == MagickFalse)
1392  status=MagickFalse;
1393  }
1394  }
1395  image_view=DestroyCacheView(image_view);
1396  (void) SetImageColorspace(image,target_info.colorspace,exception);
1397  switch (signature)
1398  {
1399  case cmsSigRgbData:
1400  {
1401  image->type=image->alpha_trait == UndefinedPixelTrait ?
1403  break;
1404  }
1405  case cmsSigCmykData:
1406  {
1407  image->type=image->alpha_trait == UndefinedPixelTrait ?
1409  break;
1410  }
1411  case cmsSigGrayData:
1412  {
1413  image->type=image->alpha_trait == UndefinedPixelTrait ?
1415  break;
1416  }
1417  default:
1418  break;
1419  }
1420  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1421  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1422  transform=DestroyTransformThreadSet(transform);
1423  if ((status != MagickFalse) &&
1424  (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1425  status=SetImageProfile(image,name,profile,exception);
1426  if (target_info.profile != (cmsHPROFILE) NULL)
1427  (void) cmsCloseProfile(target_info.profile);
1428  }
1429  (void) cmsCloseProfile(source_info.profile);
1430  cmsDeleteContext(cms_context);
1431  }
1432 #endif
1433  }
1434  profile=DestroyStringInfo(profile);
1435  return(status);
1436 }
1437 
1438 /*
1439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440 % %
1441 % %
1442 % %
1443 % R e m o v e I m a g e P r o f i l e %
1444 % %
1445 % %
1446 % %
1447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1448 %
1449 % RemoveImageProfile() removes a named profile from the image and returns its
1450 % value.
1451 %
1452 % The format of the RemoveImageProfile method is:
1453 %
1454 % void *RemoveImageProfile(Image *image,const char *name)
1455 %
1456 % A description of each parameter follows:
1457 %
1458 % o image: the image.
1459 %
1460 % o name: the profile name.
1461 %
1462 */
1464 {
1465  StringInfo
1466  *profile;
1467 
1468  assert(image != (Image *) NULL);
1469  assert(image->signature == MagickCoreSignature);
1470  if (image->debug != MagickFalse)
1471  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1472  if (image->profiles == (SplayTreeInfo *) NULL)
1473  return((StringInfo *) NULL);
1474  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1476  image->profiles,name);
1477  return(profile);
1478 }
1479 
1480 /*
1481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1482 % %
1483 % %
1484 % %
1485 % R e s e t P r o f i l e I t e r a t o r %
1486 % %
1487 % %
1488 % %
1489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1490 %
1491 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1492 % conjunction with GetNextImageProfile() to iterate over all the profiles
1493 % associated with an image.
1494 %
1495 % The format of the ResetImageProfileIterator method is:
1496 %
1497 % ResetImageProfileIterator(Image *image)
1498 %
1499 % A description of each parameter follows:
1500 %
1501 % o image: the image.
1502 %
1503 */
1505 {
1506  assert(image != (Image *) NULL);
1507  assert(image->signature == MagickCoreSignature);
1508  if (image->debug != MagickFalse)
1509  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1510  if (image->profiles == (SplayTreeInfo *) NULL)
1511  return;
1513 }
1514 
1515 /*
1516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1517 % %
1518 % %
1519 % %
1520 % S e t I m a g e P r o f i l e %
1521 % %
1522 % %
1523 % %
1524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1525 %
1526 % SetImageProfile() adds a named profile to the image. If a profile with the
1527 % same name already exists, it is replaced. This method differs from the
1528 % ProfileImage() method in that it does not apply CMS color profiles.
1529 %
1530 % The format of the SetImageProfile method is:
1531 %
1532 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1533 % const StringInfo *profile)
1534 %
1535 % A description of each parameter follows:
1536 %
1537 % o image: the image.
1538 %
1539 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1540 % Photoshop wrapper for iptc profiles).
1541 %
1542 % o profile: A StringInfo structure that contains the named profile.
1543 %
1544 */
1545 
1546 static void *DestroyProfile(void *profile)
1547 {
1548  return((void *) DestroyStringInfo((StringInfo *) profile));
1549 }
1550 
1551 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1552  unsigned char *quantum)
1553 {
1554  *quantum=(*p++);
1555  return(p);
1556 }
1557 
1558 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1559  unsigned int *quantum)
1560 {
1561  *quantum=(unsigned int) (*p++) << 24;
1562  *quantum|=(unsigned int) (*p++) << 16;
1563  *quantum|=(unsigned int) (*p++) << 8;
1564  *quantum|=(unsigned int) (*p++);
1565  return(p);
1566 }
1567 
1568 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1569  unsigned short *quantum)
1570 {
1571  *quantum=(unsigned short) (*p++) << 8;
1572  *quantum|=(unsigned short) (*p++);
1573  return(p);
1574 }
1575 
1576 static inline void WriteResourceLong(unsigned char *p,
1577  const unsigned int quantum)
1578 {
1579  unsigned char
1580  buffer[4];
1581 
1582  buffer[0]=(unsigned char) (quantum >> 24);
1583  buffer[1]=(unsigned char) (quantum >> 16);
1584  buffer[2]=(unsigned char) (quantum >> 8);
1585  buffer[3]=(unsigned char) quantum;
1586  (void) memcpy(p,buffer,4);
1587 }
1588 
1589 static void WriteTo8BimProfile(Image *image,const char *name,
1590  const StringInfo *profile)
1591 {
1592  const unsigned char
1593  *datum,
1594  *q;
1595 
1596  const unsigned char
1597  *p;
1598 
1599  size_t
1600  length;
1601 
1602  StringInfo
1603  *profile_8bim;
1604 
1605  ssize_t
1606  count;
1607 
1608  unsigned char
1609  length_byte;
1610 
1611  unsigned int
1612  value;
1613 
1614  unsigned short
1615  id,
1616  profile_id;
1617 
1618  if (LocaleCompare(name,"icc") == 0)
1619  profile_id=0x040f;
1620  else
1621  if (LocaleCompare(name,"iptc") == 0)
1622  profile_id=0x0404;
1623  else
1624  if (LocaleCompare(name,"xmp") == 0)
1625  profile_id=0x0424;
1626  else
1627  return;
1628  profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1629  image->profiles,"8bim");
1630  if (profile_8bim == (StringInfo *) NULL)
1631  return;
1632  datum=GetStringInfoDatum(profile_8bim);
1633  length=GetStringInfoLength(profile_8bim);
1634  for (p=datum; p < (datum+length-16); )
1635  {
1636  q=p;
1637  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1638  break;
1639  p+=4;
1640  p=ReadResourceShort(p,&id);
1641  p=ReadResourceByte(p,&length_byte);
1642  p+=length_byte;
1643  if (((length_byte+1) & 0x01) != 0)
1644  p++;
1645  if (p > (datum+length-4))
1646  break;
1647  p=ReadResourceLong(p,&value);
1648  count=(ssize_t) value;
1649  if ((count & 0x01) != 0)
1650  count++;
1651  if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1652  break;
1653  if (id != profile_id)
1654  p+=count;
1655  else
1656  {
1657  size_t
1658  extent,
1659  offset;
1660 
1661  ssize_t
1662  extract_extent;
1663 
1664  StringInfo
1665  *extract_profile;
1666 
1667  extract_extent=0;
1668  extent=(datum+length)-(p+count);
1669  if (profile == (StringInfo *) NULL)
1670  {
1671  offset=(q-datum);
1672  extract_profile=AcquireStringInfo(offset+extent);
1673  (void) memcpy(extract_profile->datum,datum,offset);
1674  }
1675  else
1676  {
1677  offset=(p-datum);
1678  extract_extent=profile->length;
1679  if ((extract_extent & 0x01) != 0)
1680  extract_extent++;
1681  extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1682  (void) memcpy(extract_profile->datum,datum,offset-4);
1683  WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
1684  profile->length);
1685  (void) memcpy(extract_profile->datum+offset,
1686  profile->datum,profile->length);
1687  }
1688  (void) memcpy(extract_profile->datum+offset+extract_extent,
1689  p+count,extent);
1690  (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1691  ConstantString("8bim"),CloneStringInfo(extract_profile));
1692  extract_profile=DestroyStringInfo(extract_profile);
1693  break;
1694  }
1695  }
1696 }
1697 
1699  const StringInfo *resource_block,ExceptionInfo *exception)
1700 {
1701  const unsigned char
1702  *datum;
1703 
1704  const unsigned char
1705  *p;
1706 
1707  size_t
1708  length;
1709 
1710  ssize_t
1711  count;
1712 
1713  StringInfo
1714  *profile;
1715 
1716  unsigned char
1717  length_byte;
1718 
1719  unsigned int
1720  value;
1721 
1722  unsigned short
1723  id;
1724 
1725  datum=GetStringInfoDatum(resource_block);
1726  length=GetStringInfoLength(resource_block);
1727  for (p=datum; p < (datum+length-16); )
1728  {
1729  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1730  break;
1731  p+=4;
1732  p=ReadResourceShort(p,&id);
1733  p=ReadResourceByte(p,&length_byte);
1734  p+=length_byte;
1735  if (((length_byte+1) & 0x01) != 0)
1736  p++;
1737  if (p > (datum+length-4))
1738  break;
1739  p=ReadResourceLong(p,&value);
1740  count=(ssize_t) value;
1741  if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1742  break;
1743  switch (id)
1744  {
1745  case 0x03ed:
1746  {
1747  unsigned int
1748  resolution;
1749 
1750  unsigned short
1751  units;
1752 
1753  /*
1754  Resolution.
1755  */
1756  if (count < 10)
1757  break;
1758  p=ReadResourceLong(p,&resolution);
1759  image->resolution.x=((double) resolution)/65536.0;
1760  p=ReadResourceShort(p,&units)+2;
1761  p=ReadResourceLong(p,&resolution)+4;
1762  image->resolution.y=((double) resolution)/65536.0;
1763  /*
1764  Values are always stored as pixels per inch.
1765  */
1768  else
1769  {
1771  image->resolution.x/=2.54;
1772  image->resolution.y/=2.54;
1773  }
1774  break;
1775  }
1776  case 0x0404:
1777  {
1778  /*
1779  IPTC Profile
1780  */
1781  profile=AcquireStringInfo(count);
1782  SetStringInfoDatum(profile,p);
1783  (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1784  exception);
1785  profile=DestroyStringInfo(profile);
1786  p+=count;
1787  break;
1788  }
1789  case 0x040c:
1790  {
1791  /*
1792  Thumbnail.
1793  */
1794  p+=count;
1795  break;
1796  }
1797  case 0x040f:
1798  {
1799  /*
1800  ICC Profile.
1801  */
1802  profile=AcquireStringInfo(count);
1803  SetStringInfoDatum(profile,p);
1804  (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1805  exception);
1806  profile=DestroyStringInfo(profile);
1807  p+=count;
1808  break;
1809  }
1810  case 0x0422:
1811  {
1812  /*
1813  EXIF Profile.
1814  */
1815  profile=AcquireStringInfo(count);
1816  SetStringInfoDatum(profile,p);
1817  (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1818  exception);
1819  profile=DestroyStringInfo(profile);
1820  p+=count;
1821  break;
1822  }
1823  case 0x0424:
1824  {
1825  /*
1826  XMP Profile.
1827  */
1828  profile=AcquireStringInfo(count);
1829  SetStringInfoDatum(profile,p);
1830  (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1831  exception);
1832  profile=DestroyStringInfo(profile);
1833  p+=count;
1834  break;
1835  }
1836  default:
1837  {
1838  p+=count;
1839  break;
1840  }
1841  }
1842  if ((count & 0x01) != 0)
1843  p++;
1844  }
1845 }
1846 
1847 static void PatchCorruptProfile(const char *name,StringInfo *profile)
1848 {
1849  unsigned char
1850  *p;
1851 
1852  size_t
1853  length;
1854 
1855  /*
1856  Detect corrupt profiles and if discovered, repair.
1857  */
1858  if (LocaleCompare(name,"xmp") == 0)
1859  {
1860  /*
1861  Remove garbage after xpacket end.
1862  */
1863  p=GetStringInfoDatum(profile);
1864  p=(unsigned char *) strstr((const char *) p,"<?xpacket end=\"w\"?>");
1865  if (p != (unsigned char *) NULL)
1866  {
1867  p+=19;
1868  length=p-GetStringInfoDatum(profile);
1869  if (length != GetStringInfoLength(profile))
1870  {
1871  *p='\0';
1872  SetStringInfoLength(profile,length);
1873  }
1874  }
1875  return;
1876  }
1877  if (LocaleCompare(name,"exif") == 0)
1878  {
1879  /*
1880  Check if profile starts with byte order marker instead of Exif.
1881  */
1882  p=GetStringInfoDatum(profile);
1883  if ((LocaleNCompare((const char *) p,"MM",2) == 0) ||
1884  (LocaleNCompare((const char *) p,"II",2) == 0))
1885  {
1886  const unsigned char
1887  profile_start[] = "Exif\0\0";
1888 
1889  StringInfo
1890  *exif_profile;
1891 
1892  exif_profile=AcquireStringInfo(6);
1893  if (exif_profile != (StringInfo *) NULL)
1894  {
1895  SetStringInfoDatum(exif_profile,profile_start);
1896  ConcatenateStringInfo(exif_profile,profile);
1897  SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
1898  SetStringInfo(profile,exif_profile);
1899  exif_profile=DestroyStringInfo(exif_profile);
1900  }
1901  }
1902  }
1903 }
1904 
1905 #if defined(MAGICKCORE_XML_DELEGATE)
1907  const StringInfo *profile,ExceptionInfo *exception)
1908 {
1909  xmlDocPtr
1910  document;
1911 
1912  /*
1913  Parse XML profile.
1914  */
1915  document=xmlReadMemory((const char *) GetStringInfoDatum(profile),(int)
1916  GetStringInfoLength(profile),"xmp.xml",NULL,XML_PARSE_NOERROR |
1917  XML_PARSE_NOWARNING);
1918  if (document == (xmlDocPtr) NULL)
1919  {
1921  "CorruptImageProfile","`%s' (XMP)",image->filename);
1922  return(MagickFalse);
1923  }
1924  xmlFreeDoc(document);
1925  return(MagickTrue);
1926 }
1927 #else
1929  const StringInfo *profile,ExceptionInfo *exception)
1930 {
1932  "DelegateLibrarySupportNotBuiltIn","'%s' (XML)",image->filename);
1933  return(MagickFalse);
1934 }
1935 #endif
1936 
1937 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1938  const StringInfo *profile,const MagickBooleanType recursive,
1939  ExceptionInfo *exception)
1940 {
1941  char
1942  key[MagickPathExtent];
1943 
1945  status;
1946 
1947  StringInfo
1948  *clone_profile;
1949 
1950  assert(image != (Image *) NULL);
1951  assert(image->signature == MagickCoreSignature);
1952  if (image->debug != MagickFalse)
1953  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1954  clone_profile=CloneStringInfo(profile);
1955  PatchCorruptProfile(name,clone_profile);
1956  if ((LocaleCompare(name,"xmp") == 0) &&
1957  (ValidateXMPProfile(image,clone_profile,exception) == MagickFalse))
1958  {
1959  clone_profile=DestroyStringInfo(clone_profile);
1960  return(MagickTrue);
1961  }
1962  if (image->profiles == (SplayTreeInfo *) NULL)
1964  DestroyProfile);
1965  (void) CopyMagickString(key,name,MagickPathExtent);
1966  LocaleLower(key);
1967  status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1968  ConstantString(key),clone_profile);
1969  if (status != MagickFalse)
1970  {
1971  if (LocaleCompare(name,"8bim") == 0)
1972  GetProfilesFromResourceBlock(image,clone_profile,exception);
1973  else
1974  if (recursive == MagickFalse)
1975  WriteTo8BimProfile(image,name,clone_profile);
1976  }
1977  return(status);
1978 }
1979 
1981  const StringInfo *profile,ExceptionInfo *exception)
1982 {
1983  return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1984 }
1985 
1986 /*
1987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1988 % %
1989 % %
1990 % %
1991 % S y n c I m a g e P r o f i l e s %
1992 % %
1993 % %
1994 % %
1995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1996 %
1997 % SyncImageProfiles() synchronizes image properties with the image profiles.
1998 % Currently we only support updating the EXIF resolution and orientation.
1999 %
2000 % The format of the SyncImageProfiles method is:
2001 %
2002 % MagickBooleanType SyncImageProfiles(Image *image)
2003 %
2004 % A description of each parameter follows:
2005 %
2006 % o image: the image.
2007 %
2008 */
2009 
2010 static inline int ReadProfileByte(unsigned char **p,size_t *length)
2011 {
2012  int
2013  c;
2014 
2015  if (*length < 1)
2016  return(EOF);
2017  c=(int) (*(*p)++);
2018  (*length)--;
2019  return(c);
2020 }
2021 
2022 static inline signed short ReadProfileShort(const EndianType endian,
2023  unsigned char *buffer)
2024 {
2025  union
2026  {
2027  unsigned int
2028  unsigned_value;
2029 
2030  signed int
2031  signed_value;
2032  } quantum;
2033 
2034  unsigned short
2035  value;
2036 
2037  if (endian == LSBEndian)
2038  {
2039  value=(unsigned short) buffer[1] << 8;
2040  value|=(unsigned short) buffer[0];
2041  quantum.unsigned_value=value & 0xffff;
2042  return(quantum.signed_value);
2043  }
2044  value=(unsigned short) buffer[0] << 8;
2045  value|=(unsigned short) buffer[1];
2046  quantum.unsigned_value=value & 0xffff;
2047  return(quantum.signed_value);
2048 }
2049 
2050 static inline signed int ReadProfileLong(const EndianType endian,
2051  unsigned char *buffer)
2052 {
2053  union
2054  {
2055  unsigned int
2056  unsigned_value;
2057 
2058  signed int
2059  signed_value;
2060  } quantum;
2061 
2062  unsigned int
2063  value;
2064 
2065  if (endian == LSBEndian)
2066  {
2067  value=(unsigned int) buffer[3] << 24;
2068  value|=(unsigned int) buffer[2] << 16;
2069  value|=(unsigned int) buffer[1] << 8;
2070  value|=(unsigned int) buffer[0];
2071  quantum.unsigned_value=value & 0xffffffff;
2072  return(quantum.signed_value);
2073  }
2074  value=(unsigned int) buffer[0] << 24;
2075  value|=(unsigned int) buffer[1] << 16;
2076  value|=(unsigned int) buffer[2] << 8;
2077  value|=(unsigned int) buffer[3];
2078  quantum.unsigned_value=value & 0xffffffff;
2079  return(quantum.signed_value);
2080 }
2081 
2082 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
2083 {
2084  signed int
2085  value;
2086 
2087  if (*length < 4)
2088  return(0);
2089  value=ReadProfileLong(MSBEndian,*p);
2090  (*length)-=4;
2091  *p+=4;
2092  return(value);
2093 }
2094 
2095 static inline signed short ReadProfileMSBShort(unsigned char **p,
2096  size_t *length)
2097 {
2098  signed short
2099  value;
2100 
2101  if (*length < 2)
2102  return(0);
2103  value=ReadProfileShort(MSBEndian,*p);
2104  (*length)-=2;
2105  *p+=2;
2106  return(value);
2107 }
2108 
2109 static inline void WriteProfileLong(const EndianType endian,
2110  const size_t value,unsigned char *p)
2111 {
2112  unsigned char
2113  buffer[4];
2114 
2115  if (endian == LSBEndian)
2116  {
2117  buffer[0]=(unsigned char) value;
2118  buffer[1]=(unsigned char) (value >> 8);
2119  buffer[2]=(unsigned char) (value >> 16);
2120  buffer[3]=(unsigned char) (value >> 24);
2121  (void) memcpy(p,buffer,4);
2122  return;
2123  }
2124  buffer[0]=(unsigned char) (value >> 24);
2125  buffer[1]=(unsigned char) (value >> 16);
2126  buffer[2]=(unsigned char) (value >> 8);
2127  buffer[3]=(unsigned char) value;
2128  (void) memcpy(p,buffer,4);
2129 }
2130 
2131 static void WriteProfileShort(const EndianType endian,
2132  const unsigned short value,unsigned char *p)
2133 {
2134  unsigned char
2135  buffer[2];
2136 
2137  if (endian == LSBEndian)
2138  {
2139  buffer[0]=(unsigned char) value;
2140  buffer[1]=(unsigned char) (value >> 8);
2141  (void) memcpy(p,buffer,2);
2142  return;
2143  }
2144  buffer[0]=(unsigned char) (value >> 8);
2145  buffer[1]=(unsigned char) value;
2146  (void) memcpy(p,buffer,2);
2147 }
2148 
2150 {
2151  size_t
2152  length;
2153 
2154  ssize_t
2155  count;
2156 
2157  unsigned char
2158  *p;
2159 
2160  unsigned short
2161  id;
2162 
2163  length=GetStringInfoLength(profile);
2164  p=GetStringInfoDatum(profile);
2165  while (length != 0)
2166  {
2167  if (ReadProfileByte(&p,&length) != 0x38)
2168  continue;
2169  if (ReadProfileByte(&p,&length) != 0x42)
2170  continue;
2171  if (ReadProfileByte(&p,&length) != 0x49)
2172  continue;
2173  if (ReadProfileByte(&p,&length) != 0x4D)
2174  continue;
2175  if (length < 7)
2176  return(MagickFalse);
2177  id=ReadProfileMSBShort(&p,&length);
2178  count=(ssize_t) ReadProfileByte(&p,&length);
2179  if ((count >= (ssize_t) length) || (count < 0))
2180  return(MagickFalse);
2181  p+=count;
2182  length-=count;
2183  if ((*p & 0x01) == 0)
2184  (void) ReadProfileByte(&p,&length);
2185  count=(ssize_t) ReadProfileMSBLong(&p,&length);
2186  if ((count > (ssize_t) length) || (count < 0))
2187  return(MagickFalse);
2188  if ((id == 0x3ED) && (count == 16))
2189  {
2190  if (image->units == PixelsPerCentimeterResolution)
2192  image->resolution.x*2.54*65536.0),p);
2193  else
2195  image->resolution.x*65536.0),p);
2196  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2197  if (image->units == PixelsPerCentimeterResolution)
2199  image->resolution.y*2.54*65536.0),p+8);
2200  else
2202  image->resolution.y*65536.0),p+8);
2203  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2204  }
2205  p+=count;
2206  length-=count;
2207  }
2208  return(MagickTrue);
2209 }
2210 
2212 {
2213 #define MaxDirectoryStack 16
2214 #define EXIF_DELIMITER "\n"
2215 #define EXIF_NUM_FORMATS 12
2216 #define TAG_EXIF_OFFSET 0x8769
2217 #define TAG_INTEROP_OFFSET 0xa005
2218 
2219  typedef struct _DirectoryInfo
2220  {
2221  unsigned char
2222  *directory;
2223 
2224  size_t
2225  entry;
2226  } DirectoryInfo;
2227 
2228  DirectoryInfo
2229  directory_stack[MaxDirectoryStack];
2230 
2231  EndianType
2232  endian;
2233 
2234  size_t
2235  entry,
2236  length,
2237  number_entries;
2238 
2240  *exif_resources;
2241 
2242  ssize_t
2243  id,
2244  level,
2245  offset;
2246 
2247  static int
2248  format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2249 
2250  unsigned char
2251  *directory,
2252  *exif;
2253 
2254  /*
2255  Set EXIF resolution tag.
2256  */
2257  length=GetStringInfoLength(profile);
2258  exif=GetStringInfoDatum(profile);
2259  if (length < 16)
2260  return(MagickFalse);
2261  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2262  if ((id != 0x4949) && (id != 0x4D4D))
2263  {
2264  while (length != 0)
2265  {
2266  if (ReadProfileByte(&exif,&length) != 0x45)
2267  continue;
2268  if (ReadProfileByte(&exif,&length) != 0x78)
2269  continue;
2270  if (ReadProfileByte(&exif,&length) != 0x69)
2271  continue;
2272  if (ReadProfileByte(&exif,&length) != 0x66)
2273  continue;
2274  if (ReadProfileByte(&exif,&length) != 0x00)
2275  continue;
2276  if (ReadProfileByte(&exif,&length) != 0x00)
2277  continue;
2278  break;
2279  }
2280  if (length < 16)
2281  return(MagickFalse);
2282  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2283  }
2284  endian=LSBEndian;
2285  if (id == 0x4949)
2286  endian=LSBEndian;
2287  else
2288  if (id == 0x4D4D)
2289  endian=MSBEndian;
2290  else
2291  return(MagickFalse);
2292  if (ReadProfileShort(endian,exif+2) != 0x002a)
2293  return(MagickFalse);
2294  /*
2295  This the offset to the first IFD.
2296  */
2297  offset=(ssize_t) ReadProfileLong(endian,exif+4);
2298  if ((offset < 0) || ((size_t) offset >= length))
2299  return(MagickFalse);
2300  directory=exif+offset;
2301  level=0;
2302  entry=0;
2303  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2304  (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2305  do
2306  {
2307  if (level > 0)
2308  {
2309  level--;
2310  directory=directory_stack[level].directory;
2311  entry=directory_stack[level].entry;
2312  }
2313  if ((directory < exif) || (directory > (exif+length-2)))
2314  break;
2315  /*
2316  Determine how many entries there are in the current IFD.
2317  */
2318  number_entries=ReadProfileShort(endian,directory);
2319  for ( ; entry < number_entries; entry++)
2320  {
2321  int
2322  components;
2323 
2324  unsigned char
2325  *p,
2326  *q;
2327 
2328  size_t
2329  number_bytes;
2330 
2331  ssize_t
2332  format,
2333  tag_value;
2334 
2335  q=(unsigned char *) (directory+2+(12*entry));
2336  if (q > (exif+length-12))
2337  break; /* corrupt EXIF */
2338  if (GetValueFromSplayTree(exif_resources,q) == q)
2339  break;
2340  (void) AddValueToSplayTree(exif_resources,q,q);
2341  tag_value=(ssize_t) ReadProfileShort(endian,q);
2342  format=(ssize_t) ReadProfileShort(endian,q+2);
2343  if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2344  break;
2345  components=(int) ReadProfileLong(endian,q+4);
2346  if (components < 0)
2347  break; /* corrupt EXIF */
2348  number_bytes=(size_t) components*format_bytes[format];
2349  if ((ssize_t) number_bytes < components)
2350  break; /* prevent overflow */
2351  if (number_bytes <= 4)
2352  p=q+8;
2353  else
2354  {
2355  /*
2356  The directory entry contains an offset.
2357  */
2358  offset=(ssize_t) ReadProfileLong(endian,q+8);
2359  if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2360  continue;
2361  if (~length < number_bytes)
2362  continue; /* prevent overflow */
2363  p=(unsigned char *) (exif+offset);
2364  }
2365  switch (tag_value)
2366  {
2367  case 0x011a:
2368  {
2369  (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2370  if (number_bytes == 8)
2371  (void) WriteProfileLong(endian,1UL,p+4);
2372  break;
2373  }
2374  case 0x011b:
2375  {
2376  (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2377  if (number_bytes == 8)
2378  (void) WriteProfileLong(endian,1UL,p+4);
2379  break;
2380  }
2381  case 0x0112:
2382  {
2383  if (number_bytes == 4)
2384  {
2385  (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2386  break;
2387  }
2388  (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2389  p);
2390  break;
2391  }
2392  case 0x0128:
2393  {
2394  if (number_bytes == 4)
2395  {
2396  (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2397  break;
2398  }
2399  (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2400  break;
2401  }
2402  default:
2403  break;
2404  }
2405  if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2406  {
2407  offset=(ssize_t) ReadProfileLong(endian,p);
2408  if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2409  {
2410  directory_stack[level].directory=directory;
2411  entry++;
2412  directory_stack[level].entry=entry;
2413  level++;
2414  directory_stack[level].directory=exif+offset;
2415  directory_stack[level].entry=0;
2416  level++;
2417  if ((directory+2+(12*number_entries)) > (exif+length))
2418  break;
2419  offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2420  number_entries));
2421  if ((offset != 0) && ((size_t) offset < length) &&
2422  (level < (MaxDirectoryStack-2)))
2423  {
2424  directory_stack[level].directory=exif+offset;
2425  directory_stack[level].entry=0;
2426  level++;
2427  }
2428  }
2429  break;
2430  }
2431  }
2432  } while (level > 0);
2433  exif_resources=DestroySplayTree(exif_resources);
2434  return(MagickTrue);
2435 }
2436 
2438 {
2440  status;
2441 
2442  StringInfo
2443  *profile;
2444 
2445  status=MagickTrue;
2446  profile=(StringInfo *) GetImageProfile(image,"8BIM");
2447  if (profile != (StringInfo *) NULL)
2448  if (Sync8BimProfile(image,profile) == MagickFalse)
2449  status=MagickFalse;
2450  profile=(StringInfo *) GetImageProfile(image,"EXIF");
2451  if (profile != (StringInfo *) NULL)
2452  if (SyncExifProfile(image,profile) == MagickFalse)
2453  status=MagickFalse;
2454  return(status);
2455 }
2456 
2457 static void UpdateClipPath(unsigned char *blob,size_t length,
2458  const size_t old_columns,const size_t old_rows,
2459  const RectangleInfo *new_geometry)
2460 {
2461  ssize_t
2462  i;
2463 
2464  ssize_t
2465  knot_count,
2466  selector;
2467 
2468  knot_count=0;
2469  while (length != 0)
2470  {
2471  selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2472  switch (selector)
2473  {
2474  case 0:
2475  case 3:
2476  {
2477  if (knot_count != 0)
2478  {
2479  blob+=24;
2480  length-=MagickMin(24,(ssize_t) length);
2481  break;
2482  }
2483  /*
2484  Expected subpath length record.
2485  */
2486  knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2487  blob+=22;
2488  length-=MagickMin(22,(ssize_t) length);
2489  break;
2490  }
2491  case 1:
2492  case 2:
2493  case 4:
2494  case 5:
2495  {
2496  if (knot_count == 0)
2497  {
2498  /*
2499  Unexpected subpath knot.
2500  */
2501  blob+=24;
2502  length-=MagickMin(24,(ssize_t) length);
2503  break;
2504  }
2505  /*
2506  Add sub-path knot
2507  */
2508  for (i=0; i < 3; i++)
2509  {
2510  double
2511  x,
2512  y;
2513 
2514  signed int
2515  xx,
2516  yy;
2517 
2518  y=(double) ReadProfileMSBLong(&blob,&length);
2519  y=y*old_rows/4096.0/4096.0;
2520  y-=new_geometry->y;
2521  yy=(signed int) ((y*4096*4096)/new_geometry->height);
2522  WriteProfileLong(MSBEndian,(size_t) yy,blob-4);
2523  x=(double) ReadProfileMSBLong(&blob,&length);
2524  x=x*old_columns/4096.0/4096.0;
2525  x-=new_geometry->x;
2526  xx=(signed int) ((x*4096*4096)/new_geometry->width);
2527  WriteProfileLong(MSBEndian,(size_t) xx,blob-4);
2528  }
2529  knot_count--;
2530  break;
2531  }
2532  case 6:
2533  case 7:
2534  case 8:
2535  default:
2536  {
2537  blob+=24;
2538  length-=MagickMin(24,(ssize_t) length);
2539  break;
2540  }
2541  }
2542  }
2543 }
2544 
2546  const size_t old_columns,const size_t old_rows,
2547  const RectangleInfo *new_geometry)
2548 {
2549  const StringInfo
2550  *profile;
2551 
2552  size_t
2553  length;
2554 
2555  ssize_t
2556  count,
2557  id;
2558 
2559  unsigned char
2560  *info;
2561 
2562  assert(image != (Image *) NULL);
2563  assert(new_geometry != (RectangleInfo *) NULL);
2564  profile=GetImageProfile(image,"8bim");
2565  if (profile == (StringInfo *) NULL)
2566  return;
2567  length=GetStringInfoLength(profile);
2568  info=GetStringInfoDatum(profile);
2569  while (length > 0)
2570  {
2571  if (ReadProfileByte(&info,&length) != (unsigned char) '8')
2572  continue;
2573  if (ReadProfileByte(&info,&length) != (unsigned char) 'B')
2574  continue;
2575  if (ReadProfileByte(&info,&length) != (unsigned char) 'I')
2576  continue;
2577  if (ReadProfileByte(&info,&length) != (unsigned char) 'M')
2578  continue;
2579  id=(ssize_t) ReadProfileMSBShort(&info,&length);
2580  count=(ssize_t) ReadProfileByte(&info,&length);
2581  if ((count != 0) && ((size_t) count <= length))
2582  {
2583  info+=count;
2584  length-=count;
2585  }
2586  if ((count & 0x01) == 0)
2587  (void) ReadProfileByte(&info,&length);
2588  count=(ssize_t) ReadProfileMSBLong(&info,&length);
2589  if ((count < 0) || ((size_t) count > length))
2590  {
2591  length=0;
2592  continue;
2593  }
2594  if ((id > 1999) && (id < 2999))
2595  UpdateClipPath(info,(size_t) count,old_columns,old_rows,new_geometry);
2596  info+=count;
2597  length-=MagickMin(count,(ssize_t) length);
2598  }
2599 }
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:1431
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:2807
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:2050
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:1937
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:1551
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:1546
struct _CMSExceptionInfo CMSExceptionInfo
MagickBooleanType SyncExifProfile(Image *image, StringInfo *profile)
Definition: profile.c:2211
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:2131
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:1180
static MagickBooleanType ValidateXMPProfile(Image *image, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1928
#define MaxDirectoryStack
MagickBooleanType
Definition: magick-type.h:169
MagickExport void LocaleLower(char *string)
Definition: locale.c:1447
static void WriteProfileLong(const EndianType endian, const size_t value, unsigned char *p)
Definition: profile.c:2109
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:1698
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:1527
double y
Definition: geometry.h:124
static int GetOpenMPThreadId(void)
static signed short ReadProfileShort(const EndianType endian, unsigned char *buffer)
Definition: profile.c:2022
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:624
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:2457
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:1589
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:2545
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:1428
static const unsigned char * ReadResourceShort(const unsigned char *p, unsigned short *quantum)
Definition: profile.c:1568
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:1441
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:1463
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:2437
MagickExport MagickBooleanType SetImageProfile(Image *image, const char *name, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1980
static MagickBooleanType Sync8BimProfile(Image *image, StringInfo *profile)
Definition: profile.c:2149
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1403
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:1710
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:2082
#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:1576
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:2010
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:1504
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:917
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:1209
static signed short ReadProfileMSBShort(unsigned char **p, size_t *length)
Definition: profile.c:2095
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:1558
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:1847
MagickExport void SetStringInfoDatum(StringInfo *string_info, const unsigned char *source)
Definition: string.c:1677
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:1637