MagickCore  7.0.10
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)
1027  "ColorspaceColorProfileMismatch",name);
1028  cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
1029  source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1030  GetStringInfoDatum(profile),(cmsUInt32Number)
1031  GetStringInfoLength(profile));
1032  if (source_info.profile == (cmsHPROFILE) NULL)
1033  {
1034  cmsDeleteContext(cms_context);
1036  "ColorspaceColorProfileMismatch",name);
1037  }
1038  if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
1039  (icc_profile == (StringInfo *) NULL))
1040  status=SetImageProfile(image,name,profile,exception);
1041  else
1042  {
1043  CacheView
1044  *image_view;
1045 
1046  cmsColorSpaceSignature
1047  signature;
1048 
1049  cmsHTRANSFORM
1050  *magick_restrict transform;
1051 
1052  cmsUInt32Number
1053  flags;
1054 
1055 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1056  const char
1057  *artifact;
1058 #endif
1059 
1061  highres;
1062 
1064  progress;
1065 
1066  ssize_t
1067  y;
1068 
1069  target_info.profile=(cmsHPROFILE) NULL;
1070  if (icc_profile != (StringInfo *) NULL)
1071  {
1072  target_info.profile=source_info.profile;
1073  source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1074  GetStringInfoDatum(icc_profile),
1075  (cmsUInt32Number) GetStringInfoLength(icc_profile));
1076  if (source_info.profile == (cmsHPROFILE) NULL)
1078  "ColorspaceColorProfileMismatch",name);
1079  }
1080  highres=MagickTrue;
1081 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1082  artifact=GetImageArtifact(image,"profile:highres-transform");
1083  if (IsStringFalse(artifact) != MagickFalse)
1084  highres=MagickFalse;
1085 #endif
1086  source_info.scale=1.0;
1087  source_info.translate=0.0;
1088  source_info.colorspace=sRGBColorspace;
1089  source_info.channels=3;
1090  switch (cmsGetColorSpace(source_info.profile))
1091  {
1092  case cmsSigCmykData:
1093  {
1094  source_info.colorspace=CMYKColorspace;
1095  source_info.channels=4;
1096 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1097  if (highres == MagickFalse)
1098  source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1099  else
1100 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1101  if (highres == MagickFalse)
1102  source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1103  else
1104 #endif
1105  {
1106  source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1107  source_info.scale=100.0;
1108  }
1109  break;
1110  }
1111  case cmsSigGrayData:
1112  {
1113  source_info.colorspace=GRAYColorspace;
1114  source_info.channels=1;
1115 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1116  if (highres == MagickFalse)
1117  source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1118  else
1119 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1120  if (highres == MagickFalse)
1121  source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1122  else
1123 #endif
1124  source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1125  break;
1126  }
1127  case cmsSigLabData:
1128  {
1129  source_info.colorspace=LabColorspace;
1130 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1131  if (highres == MagickFalse)
1132  source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1133  else
1134 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1135  if (highres == MagickFalse)
1136  source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1137  else
1138 #endif
1139  {
1140  source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1141  source_info.scale=100.0;
1142  source_info.translate=(-0.5);
1143  }
1144  break;
1145  }
1146  case cmsSigRgbData:
1147  {
1148  source_info.colorspace=sRGBColorspace;
1149 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1150  if (highres == MagickFalse)
1151  source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1152  else
1153 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1154  if (highres == MagickFalse)
1155  source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1156  else
1157 #endif
1158  source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1159  break;
1160  }
1161  case cmsSigXYZData:
1162  {
1163  source_info.colorspace=XYZColorspace;
1164 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1165  if (highres == MagickFalse)
1166  source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1167  else
1168 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1169  if (highres == MagickFalse)
1170  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1171  else
1172 #endif
1173  source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1174  break;
1175  }
1176  default:
1178  "ColorspaceColorProfileMismatch",name);
1179  }
1180  signature=cmsGetPCS(source_info.profile);
1181  if (target_info.profile != (cmsHPROFILE) NULL)
1182  signature=cmsGetColorSpace(target_info.profile);
1183  target_info.scale=1.0;
1184  target_info.translate=0.0;
1185  target_info.channels=3;
1186  switch (signature)
1187  {
1188  case cmsSigCmykData:
1189  {
1190  target_info.colorspace=CMYKColorspace;
1191  target_info.channels=4;
1192 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1193  if (highres == MagickFalse)
1194  target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1195  else
1196 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1197  if (highres == MagickFalse)
1198  target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1199  else
1200 #endif
1201  {
1202  target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1203  target_info.scale=0.01;
1204  }
1205  break;
1206  }
1207  case cmsSigGrayData:
1208  {
1209  target_info.colorspace=GRAYColorspace;
1210  target_info.channels=1;
1211 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1212  if (highres == MagickFalse)
1213  target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1214  else
1215 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1216  if (highres == MagickFalse)
1217  target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1218  else
1219 #endif
1220  target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1221  break;
1222  }
1223  case cmsSigLabData:
1224  {
1225  target_info.colorspace=LabColorspace;
1226 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1227  if (highres == MagickFalse)
1228  target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1229  else
1230 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1231  if (highres == MagickFalse)
1232  target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1233  else
1234 #endif
1235  {
1236  target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1237  target_info.scale=0.01;
1238  target_info.translate=0.5;
1239  }
1240  break;
1241  }
1242  case cmsSigRgbData:
1243  {
1244  target_info.colorspace=sRGBColorspace;
1245 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1246  if (highres == MagickFalse)
1247  target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1248  else
1249 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1250  if (highres == MagickFalse)
1251  target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1252  else
1253 #endif
1254  target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1255  break;
1256  }
1257  case cmsSigXYZData:
1258  {
1259  target_info.colorspace=XYZColorspace;
1260 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1261  if (highres == MagickFalse)
1262  target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1263  else
1264 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1265  if (highres == MagickFalse)
1266  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1267  else
1268 #endif
1269  target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1270  break;
1271  }
1272  default:
1274  "ColorspaceColorProfileMismatch",name);
1275  }
1276  switch (image->rendering_intent)
1277  {
1278  case AbsoluteIntent:
1279  {
1280  target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1281  break;
1282  }
1283  case PerceptualIntent:
1284  {
1285  target_info.intent=INTENT_PERCEPTUAL;
1286  break;
1287  }
1288  case RelativeIntent:
1289  {
1290  target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1291  break;
1292  }
1293  case SaturationIntent:
1294  {
1295  target_info.intent=INTENT_SATURATION;
1296  break;
1297  }
1298  default:
1299  {
1300  target_info.intent=INTENT_PERCEPTUAL;
1301  break;
1302  }
1303  }
1304  flags=cmsFLAGS_HIGHRESPRECALC;
1305 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1306  if (image->black_point_compensation != MagickFalse)
1307  flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1308 #endif
1309  transform=AcquireTransformThreadSet(&source_info,&target_info,
1310  flags,cms_context);
1311  if (transform == (cmsHTRANSFORM *) NULL)
1312  ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1313  name);
1314  /*
1315  Transform image as dictated by the source & target image profiles.
1316  */
1317  source_info.pixels=AcquirePixelThreadSet(image->columns,
1318  source_info.channels,highres);
1319  target_info.pixels=AcquirePixelThreadSet(image->columns,
1320  target_info.channels,highres);
1321  if ((source_info.pixels == (void **) NULL) ||
1322  (target_info.pixels == (void **) NULL))
1323  {
1324  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1325  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1326  transform=DestroyTransformThreadSet(transform);
1328  "MemoryAllocationFailed",image->filename);
1329  }
1330  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1331  {
1332  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1333  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1334  transform=DestroyTransformThreadSet(transform);
1335  if (source_info.profile != (cmsHPROFILE) NULL)
1336  (void) cmsCloseProfile(source_info.profile);
1337  if (target_info.profile != (cmsHPROFILE) NULL)
1338  (void) cmsCloseProfile(target_info.profile);
1339  return(MagickFalse);
1340  }
1341  if (target_info.colorspace == CMYKColorspace)
1342  (void) SetImageColorspace(image,target_info.colorspace,exception);
1343  progress=0;
1344  image_view=AcquireAuthenticCacheView(image,exception);
1345 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1346  #pragma omp parallel for schedule(static) shared(status) \
1347  magick_number_threads(image,image,image->rows,1)
1348 #endif
1349  for (y=0; y < (ssize_t) image->rows; y++)
1350  {
1351  const int
1352  id = GetOpenMPThreadId();
1353 
1355  sync;
1356 
1357  Quantum
1358  *magick_restrict q;
1359 
1360  if (status == MagickFalse)
1361  continue;
1362  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1363  exception);
1364  if (q == (Quantum *) NULL)
1365  {
1366  status=MagickFalse;
1367  continue;
1368  }
1369  if (highres != MagickFalse)
1370  TransformDoublePixels(id,image,&source_info,&target_info,transform,q);
1371  else
1372  TransformQuantumPixels(id,image,&source_info,&target_info,transform,q);
1373  sync=SyncCacheViewAuthenticPixels(image_view,exception);
1374  if (sync == MagickFalse)
1375  status=MagickFalse;
1376  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1377  {
1379  proceed;
1380 
1381 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1382  #pragma omp atomic
1383 #endif
1384  progress++;
1385  proceed=SetImageProgress(image,ProfileImageTag,progress,
1386  image->rows);
1387  if (proceed == MagickFalse)
1388  status=MagickFalse;
1389  }
1390  }
1391  image_view=DestroyCacheView(image_view);
1392  (void) SetImageColorspace(image,target_info.colorspace,exception);
1393  switch (signature)
1394  {
1395  case cmsSigRgbData:
1396  {
1397  image->type=image->alpha_trait == UndefinedPixelTrait ?
1399  break;
1400  }
1401  case cmsSigCmykData:
1402  {
1403  image->type=image->alpha_trait == UndefinedPixelTrait ?
1405  break;
1406  }
1407  case cmsSigGrayData:
1408  {
1409  image->type=image->alpha_trait == UndefinedPixelTrait ?
1411  break;
1412  }
1413  default:
1414  break;
1415  }
1416  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1417  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1418  transform=DestroyTransformThreadSet(transform);
1419  if ((status != MagickFalse) &&
1420  (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1421  status=SetImageProfile(image,name,profile,exception);
1422  if (target_info.profile != (cmsHPROFILE) NULL)
1423  (void) cmsCloseProfile(target_info.profile);
1424  }
1425  (void) cmsCloseProfile(source_info.profile);
1426  cmsDeleteContext(cms_context);
1427  }
1428 #endif
1429  }
1430  profile=DestroyStringInfo(profile);
1431  return(status);
1432 }
1433 
1434 /*
1435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 % %
1437 % %
1438 % %
1439 % R e m o v e I m a g e P r o f i l e %
1440 % %
1441 % %
1442 % %
1443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444 %
1445 % RemoveImageProfile() removes a named profile from the image and returns its
1446 % value.
1447 %
1448 % The format of the RemoveImageProfile method is:
1449 %
1450 % void *RemoveImageProfile(Image *image,const char *name)
1451 %
1452 % A description of each parameter follows:
1453 %
1454 % o image: the image.
1455 %
1456 % o name: the profile name.
1457 %
1458 */
1460 {
1461  StringInfo
1462  *profile;
1463 
1464  assert(image != (Image *) NULL);
1465  assert(image->signature == MagickCoreSignature);
1466  if (image->debug != MagickFalse)
1467  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1468  if (image->profiles == (SplayTreeInfo *) NULL)
1469  return((StringInfo *) NULL);
1470  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1472  image->profiles,name);
1473  return(profile);
1474 }
1475 
1476 /*
1477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478 % %
1479 % %
1480 % %
1481 % R e s e t P r o f i l e I t e r a t o r %
1482 % %
1483 % %
1484 % %
1485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1486 %
1487 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1488 % conjunction with GetNextImageProfile() to iterate over all the profiles
1489 % associated with an image.
1490 %
1491 % The format of the ResetImageProfileIterator method is:
1492 %
1493 % ResetImageProfileIterator(Image *image)
1494 %
1495 % A description of each parameter follows:
1496 %
1497 % o image: the image.
1498 %
1499 */
1501 {
1502  assert(image != (Image *) NULL);
1503  assert(image->signature == MagickCoreSignature);
1504  if (image->debug != MagickFalse)
1505  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1506  if (image->profiles == (SplayTreeInfo *) NULL)
1507  return;
1509 }
1510 
1511 /*
1512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1513 % %
1514 % %
1515 % %
1516 % S e t I m a g e P r o f i l e %
1517 % %
1518 % %
1519 % %
1520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1521 %
1522 % SetImageProfile() adds a named profile to the image. If a profile with the
1523 % same name already exists, it is replaced. This method differs from the
1524 % ProfileImage() method in that it does not apply CMS color profiles.
1525 %
1526 % The format of the SetImageProfile method is:
1527 %
1528 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1529 % const StringInfo *profile)
1530 %
1531 % A description of each parameter follows:
1532 %
1533 % o image: the image.
1534 %
1535 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1536 % Photoshop wrapper for iptc profiles).
1537 %
1538 % o profile: A StringInfo structure that contains the named profile.
1539 %
1540 */
1541 
1542 static void *DestroyProfile(void *profile)
1543 {
1544  return((void *) DestroyStringInfo((StringInfo *) profile));
1545 }
1546 
1547 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1548  unsigned char *quantum)
1549 {
1550  *quantum=(*p++);
1551  return(p);
1552 }
1553 
1554 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1555  unsigned int *quantum)
1556 {
1557  *quantum=(unsigned int) (*p++) << 24;
1558  *quantum|=(unsigned int) (*p++) << 16;
1559  *quantum|=(unsigned int) (*p++) << 8;
1560  *quantum|=(unsigned int) (*p++);
1561  return(p);
1562 }
1563 
1564 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1565  unsigned short *quantum)
1566 {
1567  *quantum=(unsigned short) (*p++) << 8;
1568  *quantum|=(unsigned short) (*p++);
1569  return(p);
1570 }
1571 
1572 static inline void WriteResourceLong(unsigned char *p,
1573  const unsigned int quantum)
1574 {
1575  unsigned char
1576  buffer[4];
1577 
1578  buffer[0]=(unsigned char) (quantum >> 24);
1579  buffer[1]=(unsigned char) (quantum >> 16);
1580  buffer[2]=(unsigned char) (quantum >> 8);
1581  buffer[3]=(unsigned char) quantum;
1582  (void) memcpy(p,buffer,4);
1583 }
1584 
1585 static void WriteTo8BimProfile(Image *image,const char *name,
1586  const StringInfo *profile)
1587 {
1588  const unsigned char
1589  *datum,
1590  *q;
1591 
1592  const unsigned char
1593  *p;
1594 
1595  size_t
1596  length;
1597 
1598  StringInfo
1599  *profile_8bim;
1600 
1601  ssize_t
1602  count;
1603 
1604  unsigned char
1605  length_byte;
1606 
1607  unsigned int
1608  value;
1609 
1610  unsigned short
1611  id,
1612  profile_id;
1613 
1614  if (LocaleCompare(name,"icc") == 0)
1615  profile_id=0x040f;
1616  else
1617  if (LocaleCompare(name,"iptc") == 0)
1618  profile_id=0x0404;
1619  else
1620  if (LocaleCompare(name,"xmp") == 0)
1621  profile_id=0x0424;
1622  else
1623  return;
1624  profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1625  image->profiles,"8bim");
1626  if (profile_8bim == (StringInfo *) NULL)
1627  return;
1628  datum=GetStringInfoDatum(profile_8bim);
1629  length=GetStringInfoLength(profile_8bim);
1630  for (p=datum; p < (datum+length-16); )
1631  {
1632  q=p;
1633  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1634  break;
1635  p+=4;
1636  p=ReadResourceShort(p,&id);
1637  p=ReadResourceByte(p,&length_byte);
1638  p+=length_byte;
1639  if (((length_byte+1) & 0x01) != 0)
1640  p++;
1641  if (p > (datum+length-4))
1642  break;
1643  p=ReadResourceLong(p,&value);
1644  count=(ssize_t) value;
1645  if ((count & 0x01) != 0)
1646  count++;
1647  if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1648  break;
1649  if (id != profile_id)
1650  p+=count;
1651  else
1652  {
1653  size_t
1654  extent,
1655  offset;
1656 
1657  ssize_t
1658  extract_extent;
1659 
1660  StringInfo
1661  *extract_profile;
1662 
1663  extract_extent=0;
1664  extent=(datum+length)-(p+count);
1665  if (profile == (StringInfo *) NULL)
1666  {
1667  offset=(q-datum);
1668  extract_profile=AcquireStringInfo(offset+extent);
1669  (void) memcpy(extract_profile->datum,datum,offset);
1670  }
1671  else
1672  {
1673  offset=(p-datum);
1674  extract_extent=profile->length;
1675  if ((extract_extent & 0x01) != 0)
1676  extract_extent++;
1677  extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1678  (void) memcpy(extract_profile->datum,datum,offset-4);
1679  WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
1680  profile->length);
1681  (void) memcpy(extract_profile->datum+offset,
1682  profile->datum,profile->length);
1683  }
1684  (void) memcpy(extract_profile->datum+offset+extract_extent,
1685  p+count,extent);
1686  (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1687  ConstantString("8bim"),CloneStringInfo(extract_profile));
1688  extract_profile=DestroyStringInfo(extract_profile);
1689  break;
1690  }
1691  }
1692 }
1693 
1695  const StringInfo *resource_block,ExceptionInfo *exception)
1696 {
1697  const unsigned char
1698  *datum;
1699 
1700  const unsigned char
1701  *p;
1702 
1703  size_t
1704  length;
1705 
1706  ssize_t
1707  count;
1708 
1709  StringInfo
1710  *profile;
1711 
1712  unsigned char
1713  length_byte;
1714 
1715  unsigned int
1716  value;
1717 
1718  unsigned short
1719  id;
1720 
1721  datum=GetStringInfoDatum(resource_block);
1722  length=GetStringInfoLength(resource_block);
1723  for (p=datum; p < (datum+length-16); )
1724  {
1725  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1726  break;
1727  p+=4;
1728  p=ReadResourceShort(p,&id);
1729  p=ReadResourceByte(p,&length_byte);
1730  p+=length_byte;
1731  if (((length_byte+1) & 0x01) != 0)
1732  p++;
1733  if (p > (datum+length-4))
1734  break;
1735  p=ReadResourceLong(p,&value);
1736  count=(ssize_t) value;
1737  if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1738  break;
1739  switch (id)
1740  {
1741  case 0x03ed:
1742  {
1743  unsigned int
1744  resolution;
1745 
1746  unsigned short
1747  units;
1748 
1749  /*
1750  Resolution.
1751  */
1752  if (count < 10)
1753  break;
1754  p=ReadResourceLong(p,&resolution);
1755  image->resolution.x=((double) resolution)/65536.0;
1756  p=ReadResourceShort(p,&units)+2;
1757  p=ReadResourceLong(p,&resolution)+4;
1758  image->resolution.y=((double) resolution)/65536.0;
1759  /*
1760  Values are always stored as pixels per inch.
1761  */
1764  else
1765  {
1767  image->resolution.x/=2.54;
1768  image->resolution.y/=2.54;
1769  }
1770  break;
1771  }
1772  case 0x0404:
1773  {
1774  /*
1775  IPTC Profile
1776  */
1777  profile=AcquireStringInfo(count);
1778  SetStringInfoDatum(profile,p);
1779  (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1780  exception);
1781  profile=DestroyStringInfo(profile);
1782  p+=count;
1783  break;
1784  }
1785  case 0x040c:
1786  {
1787  /*
1788  Thumbnail.
1789  */
1790  p+=count;
1791  break;
1792  }
1793  case 0x040f:
1794  {
1795  /*
1796  ICC Profile.
1797  */
1798  profile=AcquireStringInfo(count);
1799  SetStringInfoDatum(profile,p);
1800  (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1801  exception);
1802  profile=DestroyStringInfo(profile);
1803  p+=count;
1804  break;
1805  }
1806  case 0x0422:
1807  {
1808  /*
1809  EXIF Profile.
1810  */
1811  profile=AcquireStringInfo(count);
1812  SetStringInfoDatum(profile,p);
1813  (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1814  exception);
1815  profile=DestroyStringInfo(profile);
1816  p+=count;
1817  break;
1818  }
1819  case 0x0424:
1820  {
1821  /*
1822  XMP Profile.
1823  */
1824  profile=AcquireStringInfo(count);
1825  SetStringInfoDatum(profile,p);
1826  (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1827  exception);
1828  profile=DestroyStringInfo(profile);
1829  p+=count;
1830  break;
1831  }
1832  default:
1833  {
1834  p+=count;
1835  break;
1836  }
1837  }
1838  if ((count & 0x01) != 0)
1839  p++;
1840  }
1841 }
1842 
1843 static void PatchCorruptProfile(const char *name,StringInfo *profile)
1844 {
1845  unsigned char
1846  *p;
1847 
1848  size_t
1849  length;
1850 
1851  /*
1852  Detect corrupt profiles and if discovered, repair.
1853  */
1854  if (LocaleCompare(name,"xmp") == 0)
1855  {
1856  /*
1857  Remove garbage after xpacket end.
1858  */
1859  p=GetStringInfoDatum(profile);
1860  p=(unsigned char *) strstr((const char *) p,"<?xpacket end=\"w\"?>");
1861  if (p != (unsigned char *) NULL)
1862  {
1863  p+=19;
1864  length=p-GetStringInfoDatum(profile);
1865  if (length != GetStringInfoLength(profile))
1866  {
1867  *p='\0';
1868  SetStringInfoLength(profile,length);
1869  }
1870  }
1871  return;
1872  }
1873  if (LocaleCompare(name,"exif") == 0)
1874  {
1875  /*
1876  Check if profile starts with byte order marker instead of Exif.
1877  */
1878  p=GetStringInfoDatum(profile);
1879  if ((LocaleNCompare((const char *) p,"MM",2) == 0) ||
1880  (LocaleNCompare((const char *) p,"II",2) == 0))
1881  {
1882  const unsigned char
1883  profile_start[] = "Exif\0\0";
1884 
1885  StringInfo
1886  *exif_profile;
1887 
1888  exif_profile=AcquireStringInfo(6);
1889  if (exif_profile != (StringInfo *) NULL)
1890  {
1891  SetStringInfoDatum(exif_profile,profile_start);
1892  ConcatenateStringInfo(exif_profile,profile);
1893  SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
1894  SetStringInfo(profile,exif_profile);
1895  exif_profile=DestroyStringInfo(exif_profile);
1896  }
1897  }
1898  }
1899 }
1900 
1901 #if defined(MAGICKCORE_XML_DELEGATE)
1903  const StringInfo *profile,ExceptionInfo *exception)
1904 {
1905  xmlDocPtr
1906  document;
1907 
1908  /*
1909  Parse XML profile.
1910  */
1911  document=xmlReadMemory((const char *) GetStringInfoDatum(profile),(int)
1912  GetStringInfoLength(profile),"xmp.xml",NULL,XML_PARSE_NOERROR |
1913  XML_PARSE_NOWARNING);
1914  if (document == (xmlDocPtr) NULL)
1915  {
1917  "CorruptImageProfile","`%s' (XMP)",image->filename);
1918  return(MagickFalse);
1919  }
1920  xmlFreeDoc(document);
1921  return(MagickTrue);
1922 }
1923 #else
1925  const StringInfo *profile,ExceptionInfo *exception)
1926 {
1928  "DelegateLibrarySupportNotBuiltIn","'%s' (XML)",image->filename);
1929  return(MagickFalse);
1930 }
1931 #endif
1932 
1933 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1934  const StringInfo *profile,const MagickBooleanType recursive,
1935  ExceptionInfo *exception)
1936 {
1937  char
1938  key[MagickPathExtent];
1939 
1941  status;
1942 
1943  StringInfo
1944  *clone_profile;
1945 
1946  assert(image != (Image *) NULL);
1947  assert(image->signature == MagickCoreSignature);
1948  if (image->debug != MagickFalse)
1949  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1950  clone_profile=CloneStringInfo(profile);
1951  PatchCorruptProfile(name,clone_profile);
1952  if ((LocaleCompare(name,"xmp") == 0) &&
1953  (ValidateXMPProfile(image,clone_profile,exception) == MagickFalse))
1954  {
1955  clone_profile=DestroyStringInfo(clone_profile);
1956  return(MagickTrue);
1957  }
1958  if (image->profiles == (SplayTreeInfo *) NULL)
1960  DestroyProfile);
1961  (void) CopyMagickString(key,name,MagickPathExtent);
1962  LocaleLower(key);
1963  status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1964  ConstantString(key),clone_profile);
1965  if (status != MagickFalse)
1966  {
1967  if (LocaleCompare(name,"8bim") == 0)
1968  GetProfilesFromResourceBlock(image,clone_profile,exception);
1969  else
1970  if (recursive == MagickFalse)
1971  WriteTo8BimProfile(image,name,clone_profile);
1972  }
1973  return(status);
1974 }
1975 
1977  const StringInfo *profile,ExceptionInfo *exception)
1978 {
1979  return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1980 }
1981 
1982 /*
1983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1984 % %
1985 % %
1986 % %
1987 % S y n c I m a g e P r o f i l e s %
1988 % %
1989 % %
1990 % %
1991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1992 %
1993 % SyncImageProfiles() synchronizes image properties with the image profiles.
1994 % Currently we only support updating the EXIF resolution and orientation.
1995 %
1996 % The format of the SyncImageProfiles method is:
1997 %
1998 % MagickBooleanType SyncImageProfiles(Image *image)
1999 %
2000 % A description of each parameter follows:
2001 %
2002 % o image: the image.
2003 %
2004 */
2005 
2006 static inline int ReadProfileByte(unsigned char **p,size_t *length)
2007 {
2008  int
2009  c;
2010 
2011  if (*length < 1)
2012  return(EOF);
2013  c=(int) (*(*p)++);
2014  (*length)--;
2015  return(c);
2016 }
2017 
2018 static inline signed short ReadProfileShort(const EndianType endian,
2019  unsigned char *buffer)
2020 {
2021  union
2022  {
2023  unsigned int
2024  unsigned_value;
2025 
2026  signed int
2027  signed_value;
2028  } quantum;
2029 
2030  unsigned short
2031  value;
2032 
2033  if (endian == LSBEndian)
2034  {
2035  value=(unsigned short) buffer[1] << 8;
2036  value|=(unsigned short) buffer[0];
2037  quantum.unsigned_value=value & 0xffff;
2038  return(quantum.signed_value);
2039  }
2040  value=(unsigned short) buffer[0] << 8;
2041  value|=(unsigned short) buffer[1];
2042  quantum.unsigned_value=value & 0xffff;
2043  return(quantum.signed_value);
2044 }
2045 
2046 static inline signed int ReadProfileLong(const EndianType endian,
2047  unsigned char *buffer)
2048 {
2049  union
2050  {
2051  unsigned int
2052  unsigned_value;
2053 
2054  signed int
2055  signed_value;
2056  } quantum;
2057 
2058  unsigned int
2059  value;
2060 
2061  if (endian == LSBEndian)
2062  {
2063  value=(unsigned int) buffer[3] << 24;
2064  value|=(unsigned int) buffer[2] << 16;
2065  value|=(unsigned int) buffer[1] << 8;
2066  value|=(unsigned int) buffer[0];
2067  quantum.unsigned_value=value & 0xffffffff;
2068  return(quantum.signed_value);
2069  }
2070  value=(unsigned int) buffer[0] << 24;
2071  value|=(unsigned int) buffer[1] << 16;
2072  value|=(unsigned int) buffer[2] << 8;
2073  value|=(unsigned int) buffer[3];
2074  quantum.unsigned_value=value & 0xffffffff;
2075  return(quantum.signed_value);
2076 }
2077 
2078 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
2079 {
2080  signed int
2081  value;
2082 
2083  if (*length < 4)
2084  return(0);
2085  value=ReadProfileLong(MSBEndian,*p);
2086  (*length)-=4;
2087  *p+=4;
2088  return(value);
2089 }
2090 
2091 static inline signed short ReadProfileMSBShort(unsigned char **p,
2092  size_t *length)
2093 {
2094  signed short
2095  value;
2096 
2097  if (*length < 2)
2098  return(0);
2099  value=ReadProfileShort(MSBEndian,*p);
2100  (*length)-=2;
2101  *p+=2;
2102  return(value);
2103 }
2104 
2105 static inline void WriteProfileLong(const EndianType endian,
2106  const size_t value,unsigned char *p)
2107 {
2108  unsigned char
2109  buffer[4];
2110 
2111  if (endian == LSBEndian)
2112  {
2113  buffer[0]=(unsigned char) value;
2114  buffer[1]=(unsigned char) (value >> 8);
2115  buffer[2]=(unsigned char) (value >> 16);
2116  buffer[3]=(unsigned char) (value >> 24);
2117  (void) memcpy(p,buffer,4);
2118  return;
2119  }
2120  buffer[0]=(unsigned char) (value >> 24);
2121  buffer[1]=(unsigned char) (value >> 16);
2122  buffer[2]=(unsigned char) (value >> 8);
2123  buffer[3]=(unsigned char) value;
2124  (void) memcpy(p,buffer,4);
2125 }
2126 
2127 static void WriteProfileShort(const EndianType endian,
2128  const unsigned short value,unsigned char *p)
2129 {
2130  unsigned char
2131  buffer[2];
2132 
2133  if (endian == LSBEndian)
2134  {
2135  buffer[0]=(unsigned char) value;
2136  buffer[1]=(unsigned char) (value >> 8);
2137  (void) memcpy(p,buffer,2);
2138  return;
2139  }
2140  buffer[0]=(unsigned char) (value >> 8);
2141  buffer[1]=(unsigned char) value;
2142  (void) memcpy(p,buffer,2);
2143 }
2144 
2146 {
2147  size_t
2148  length;
2149 
2150  ssize_t
2151  count;
2152 
2153  unsigned char
2154  *p;
2155 
2156  unsigned short
2157  id;
2158 
2159  length=GetStringInfoLength(profile);
2160  p=GetStringInfoDatum(profile);
2161  while (length != 0)
2162  {
2163  if (ReadProfileByte(&p,&length) != 0x38)
2164  continue;
2165  if (ReadProfileByte(&p,&length) != 0x42)
2166  continue;
2167  if (ReadProfileByte(&p,&length) != 0x49)
2168  continue;
2169  if (ReadProfileByte(&p,&length) != 0x4D)
2170  continue;
2171  if (length < 7)
2172  return(MagickFalse);
2173  id=ReadProfileMSBShort(&p,&length);
2174  count=(ssize_t) ReadProfileByte(&p,&length);
2175  if ((count >= (ssize_t) length) || (count < 0))
2176  return(MagickFalse);
2177  p+=count;
2178  length-=count;
2179  if ((*p & 0x01) == 0)
2180  (void) ReadProfileByte(&p,&length);
2181  count=(ssize_t) ReadProfileMSBLong(&p,&length);
2182  if ((count > (ssize_t) length) || (count < 0))
2183  return(MagickFalse);
2184  if ((id == 0x3ED) && (count == 16))
2185  {
2186  if (image->units == PixelsPerCentimeterResolution)
2187  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
2188  65536.0),p);
2189  else
2190  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
2191  65536.0),p);
2192  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2193  if (image->units == PixelsPerCentimeterResolution)
2194  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
2195  65536.0),p+8);
2196  else
2197  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
2198  65536.0),p+8);
2199  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2200  }
2201  p+=count;
2202  length-=count;
2203  }
2204  return(MagickTrue);
2205 }
2206 
2208 {
2209 #define MaxDirectoryStack 16
2210 #define EXIF_DELIMITER "\n"
2211 #define EXIF_NUM_FORMATS 12
2212 #define TAG_EXIF_OFFSET 0x8769
2213 #define TAG_INTEROP_OFFSET 0xa005
2214 
2215  typedef struct _DirectoryInfo
2216  {
2217  unsigned char
2218  *directory;
2219 
2220  size_t
2221  entry;
2222  } DirectoryInfo;
2223 
2224  DirectoryInfo
2225  directory_stack[MaxDirectoryStack];
2226 
2227  EndianType
2228  endian;
2229 
2230  size_t
2231  entry,
2232  length,
2233  number_entries;
2234 
2236  *exif_resources;
2237 
2238  ssize_t
2239  id,
2240  level,
2241  offset;
2242 
2243  static int
2244  format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2245 
2246  unsigned char
2247  *directory,
2248  *exif;
2249 
2250  /*
2251  Set EXIF resolution tag.
2252  */
2253  length=GetStringInfoLength(profile);
2254  exif=GetStringInfoDatum(profile);
2255  if (length < 16)
2256  return(MagickFalse);
2257  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2258  if ((id != 0x4949) && (id != 0x4D4D))
2259  {
2260  while (length != 0)
2261  {
2262  if (ReadProfileByte(&exif,&length) != 0x45)
2263  continue;
2264  if (ReadProfileByte(&exif,&length) != 0x78)
2265  continue;
2266  if (ReadProfileByte(&exif,&length) != 0x69)
2267  continue;
2268  if (ReadProfileByte(&exif,&length) != 0x66)
2269  continue;
2270  if (ReadProfileByte(&exif,&length) != 0x00)
2271  continue;
2272  if (ReadProfileByte(&exif,&length) != 0x00)
2273  continue;
2274  break;
2275  }
2276  if (length < 16)
2277  return(MagickFalse);
2278  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2279  }
2280  endian=LSBEndian;
2281  if (id == 0x4949)
2282  endian=LSBEndian;
2283  else
2284  if (id == 0x4D4D)
2285  endian=MSBEndian;
2286  else
2287  return(MagickFalse);
2288  if (ReadProfileShort(endian,exif+2) != 0x002a)
2289  return(MagickFalse);
2290  /*
2291  This the offset to the first IFD.
2292  */
2293  offset=(ssize_t) ReadProfileLong(endian,exif+4);
2294  if ((offset < 0) || ((size_t) offset >= length))
2295  return(MagickFalse);
2296  directory=exif+offset;
2297  level=0;
2298  entry=0;
2299  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2300  (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2301  do
2302  {
2303  if (level > 0)
2304  {
2305  level--;
2306  directory=directory_stack[level].directory;
2307  entry=directory_stack[level].entry;
2308  }
2309  if ((directory < exif) || (directory > (exif+length-2)))
2310  break;
2311  /*
2312  Determine how many entries there are in the current IFD.
2313  */
2314  number_entries=ReadProfileShort(endian,directory);
2315  for ( ; entry < number_entries; entry++)
2316  {
2317  int
2318  components;
2319 
2320  unsigned char
2321  *p,
2322  *q;
2323 
2324  size_t
2325  number_bytes;
2326 
2327  ssize_t
2328  format,
2329  tag_value;
2330 
2331  q=(unsigned char *) (directory+2+(12*entry));
2332  if (q > (exif+length-12))
2333  break; /* corrupt EXIF */
2334  if (GetValueFromSplayTree(exif_resources,q) == q)
2335  break;
2336  (void) AddValueToSplayTree(exif_resources,q,q);
2337  tag_value=(ssize_t) ReadProfileShort(endian,q);
2338  format=(ssize_t) ReadProfileShort(endian,q+2);
2339  if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2340  break;
2341  components=(int) ReadProfileLong(endian,q+4);
2342  if (components < 0)
2343  break; /* corrupt EXIF */
2344  number_bytes=(size_t) components*format_bytes[format];
2345  if ((ssize_t) number_bytes < components)
2346  break; /* prevent overflow */
2347  if (number_bytes <= 4)
2348  p=q+8;
2349  else
2350  {
2351  /*
2352  The directory entry contains an offset.
2353  */
2354  offset=(ssize_t) ReadProfileLong(endian,q+8);
2355  if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2356  continue;
2357  if (~length < number_bytes)
2358  continue; /* prevent overflow */
2359  p=(unsigned char *) (exif+offset);
2360  }
2361  switch (tag_value)
2362  {
2363  case 0x011a:
2364  {
2365  (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2366  if (number_bytes == 8)
2367  (void) WriteProfileLong(endian,1UL,p+4);
2368  break;
2369  }
2370  case 0x011b:
2371  {
2372  (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2373  if (number_bytes == 8)
2374  (void) WriteProfileLong(endian,1UL,p+4);
2375  break;
2376  }
2377  case 0x0112:
2378  {
2379  if (number_bytes == 4)
2380  {
2381  (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2382  break;
2383  }
2384  (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2385  p);
2386  break;
2387  }
2388  case 0x0128:
2389  {
2390  if (number_bytes == 4)
2391  {
2392  (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2393  break;
2394  }
2395  (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2396  break;
2397  }
2398  default:
2399  break;
2400  }
2401  if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2402  {
2403  offset=(ssize_t) ReadProfileLong(endian,p);
2404  if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2405  {
2406  directory_stack[level].directory=directory;
2407  entry++;
2408  directory_stack[level].entry=entry;
2409  level++;
2410  directory_stack[level].directory=exif+offset;
2411  directory_stack[level].entry=0;
2412  level++;
2413  if ((directory+2+(12*number_entries)) > (exif+length))
2414  break;
2415  offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2416  number_entries));
2417  if ((offset != 0) && ((size_t) offset < length) &&
2418  (level < (MaxDirectoryStack-2)))
2419  {
2420  directory_stack[level].directory=exif+offset;
2421  directory_stack[level].entry=0;
2422  level++;
2423  }
2424  }
2425  break;
2426  }
2427  }
2428  } while (level > 0);
2429  exif_resources=DestroySplayTree(exif_resources);
2430  return(MagickTrue);
2431 }
2432 
2434 {
2436  status;
2437 
2438  StringInfo
2439  *profile;
2440 
2441  status=MagickTrue;
2442  profile=(StringInfo *) GetImageProfile(image,"8BIM");
2443  if (profile != (StringInfo *) NULL)
2444  if (Sync8BimProfile(image,profile) == MagickFalse)
2445  status=MagickFalse;
2446  profile=(StringInfo *) GetImageProfile(image,"EXIF");
2447  if (profile != (StringInfo *) NULL)
2448  if (SyncExifProfile(image,profile) == MagickFalse)
2449  status=MagickFalse;
2450  return(status);
2451 }
2452 
2453 static void UpdateClipPath(unsigned char *blob,size_t length,
2454  const size_t old_columns,const size_t old_rows,
2455  const RectangleInfo *new_geometry)
2456 {
2457  ssize_t
2458  i;
2459 
2460  ssize_t
2461  knot_count,
2462  selector;
2463 
2464  knot_count=0;
2465  while (length != 0)
2466  {
2467  selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2468  switch (selector)
2469  {
2470  case 0:
2471  case 3:
2472  {
2473  if (knot_count != 0)
2474  {
2475  blob+=24;
2476  length-=MagickMin(24,(ssize_t) length);
2477  break;
2478  }
2479  /*
2480  Expected subpath length record.
2481  */
2482  knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2483  blob+=22;
2484  length-=MagickMin(22,(ssize_t) length);
2485  break;
2486  }
2487  case 1:
2488  case 2:
2489  case 4:
2490  case 5:
2491  {
2492  if (knot_count == 0)
2493  {
2494  /*
2495  Unexpected subpath knot.
2496  */
2497  blob+=24;
2498  length-=MagickMin(24,(ssize_t) length);
2499  break;
2500  }
2501  /*
2502  Add sub-path knot
2503  */
2504  for (i=0; i < 3; i++)
2505  {
2506  double
2507  x,
2508  y;
2509 
2510  signed int
2511  xx,
2512  yy;
2513 
2514  y=(double) ReadProfileMSBLong(&blob,&length);
2515  y=y*old_rows/4096/4096;
2516  y-=new_geometry->y;
2517  yy=(signed int) ((y*4096*4096)/new_geometry->height);
2518  WriteProfileLong(MSBEndian,(size_t) yy,blob-4);
2519  x=(double) ReadProfileMSBLong(&blob,&length);
2520  x=x*old_columns/4096/4096;
2521  x-=new_geometry->x;
2522  xx=(signed int) ((x*4096*4096)/new_geometry->width);
2523  WriteProfileLong(MSBEndian,(size_t) xx,blob-4);
2524  }
2525  knot_count--;
2526  break;
2527  }
2528  case 6:
2529  case 7:
2530  case 8:
2531  default:
2532  {
2533  blob+=24;
2534  length-=MagickMin(24,(ssize_t) length);
2535  break;
2536  }
2537  }
2538  }
2539 }
2540 
2542  const size_t old_columns,const size_t old_rows,
2543  const RectangleInfo *new_geometry)
2544 {
2545  const StringInfo
2546  *profile;
2547 
2548  size_t
2549  length;
2550 
2551  ssize_t
2552  count,
2553  id;
2554 
2555  unsigned char
2556  *info;
2557 
2558  assert(image != (Image *) NULL);
2559  assert(new_geometry != (RectangleInfo *) NULL);
2560  profile=GetImageProfile(image,"8bim");
2561  if (profile == (StringInfo *) NULL)
2562  return;
2563  length=GetStringInfoLength(profile);
2564  info=GetStringInfoDatum(profile);
2565  while (length > 0)
2566  {
2567  if (ReadProfileByte(&info,&length) != (unsigned char) '8')
2568  continue;
2569  if (ReadProfileByte(&info,&length) != (unsigned char) 'B')
2570  continue;
2571  if (ReadProfileByte(&info,&length) != (unsigned char) 'I')
2572  continue;
2573  if (ReadProfileByte(&info,&length) != (unsigned char) 'M')
2574  continue;
2575  id=(ssize_t) ReadProfileMSBShort(&info,&length);
2576  count=(ssize_t) ReadProfileByte(&info,&length);
2577  if ((count != 0) && ((size_t) count <= length))
2578  {
2579  info+=count;
2580  length-=count;
2581  }
2582  if ((count & 0x01) == 0)
2583  (void) ReadProfileByte(&info,&length);
2584  count=(ssize_t) ReadProfileMSBLong(&info,&length);
2585  if ((count < 0) || ((size_t) count > length))
2586  {
2587  length=0;
2588  continue;
2589  }
2590  if ((id > 1999) && (id < 2999))
2591  UpdateClipPath(info,(size_t) count,old_columns,old_rows,new_geometry);
2592  info+=count;
2593  length-=MagickMin(count,(ssize_t) length);
2594  }
2595 }
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:1419
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:2750
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:2046
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:1933
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:1547
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:1542
struct _CMSExceptionInfo CMSExceptionInfo
MagickBooleanType SyncExifProfile(Image *image, StringInfo *profile)
Definition: profile.c:2207
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:719
ResolutionType units
Definition: image.h:198
static void WriteProfileShort(const EndianType endian, const unsigned short value, unsigned char *p)
Definition: profile.c:2127
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:137
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:1168
static MagickBooleanType ValidateXMPProfile(Image *image, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1924
#define MaxDirectoryStack
MagickBooleanType
Definition: magick-type.h:173
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:2105
MagickBooleanType black_point_compensation
Definition: image.h:258
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:803
static void GetProfilesFromResourceBlock(Image *image, const StringInfo *resource_block, ExceptionInfo *exception)
Definition: profile.c:1694
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:2018
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:2453
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:1585
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:2541
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:1430
static const unsigned char * ReadResourceShort(const unsigned char *p, unsigned short *quantum)
Definition: profile.c:1564
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:1443
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:2603
MagickExport StringInfo * RemoveImageProfile(Image *image, const char *name)
Definition: profile.c:1459
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:2433
MagickExport MagickBooleanType SetImageProfile(Image *image, const char *name, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1976
static MagickBooleanType Sync8BimProfile(Image *image, StringInfo *profile)
Definition: profile.c:2145
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1403
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:90
MagickExport void SetStringInfoLength(StringInfo *string_info, const size_t length)
Definition: string.c:1698
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1402
MagickExport const char * GetImageProperty(const Image *image, const char *property, ExceptionInfo *exception)
Definition: property.c:2217
static signed int ReadProfileMSBLong(unsigned char **p, size_t *length)
Definition: profile.c:2078
#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:1572
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:2006
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:1500
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:1197
static signed short ReadProfileMSBShort(unsigned char **p, size_t *length)
Definition: profile.c:2091
MagickExport char * ConstantString(const char *source)
Definition: string.c:666
static const unsigned char * ReadResourceLong(const unsigned char *p, unsigned int *quantum)
Definition: profile.c:1554
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:1843
MagickExport void SetStringInfoDatum(StringInfo *string_info, const unsigned char *source)
Definition: string.c:1665
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:1625