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-2020 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  register 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  register 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  register 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  register 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  register double
534  *p;
535 
536  register 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  register Quantum
584  *p;
585 
586  register 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  if (highres != MagickFalse)
1087  {
1088  source_info.scale=1.0;
1089  source_info.translate=0.0;
1090  }
1091  source_info.colorspace=sRGBColorspace;
1092  source_info.channels=3;
1093  switch (cmsGetColorSpace(source_info.profile))
1094  {
1095  case cmsSigCmykData:
1096  {
1097  source_info.colorspace=CMYKColorspace;
1098  source_info.channels=4;
1099 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1100  if (highres == MagickFalse)
1101  source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1102  else
1103 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1104  if (highres == MagickFalse)
1105  source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1106  else
1107 #endif
1108  {
1109  source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1110  source_info.scale=100.0;
1111  }
1112  break;
1113  }
1114  case cmsSigGrayData:
1115  {
1116  source_info.colorspace=GRAYColorspace;
1117  source_info.channels=1;
1118 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1119  if (highres == MagickFalse)
1120  source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1121  else
1122 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1123  if (highres == MagickFalse)
1124  source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1125  else
1126 #endif
1127  source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1128  break;
1129  }
1130  case cmsSigLabData:
1131  {
1132  source_info.colorspace=LabColorspace;
1133 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1134  if (highres == MagickFalse)
1135  source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1136  else
1137 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1138  if (highres == MagickFalse)
1139  source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1140  else
1141 #endif
1142  {
1143  source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1144  source_info.scale=100.0;
1145  source_info.translate=(-0.5);
1146  }
1147  break;
1148  }
1149  case cmsSigRgbData:
1150  {
1151  source_info.colorspace=sRGBColorspace;
1152 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1153  if (highres == MagickFalse)
1154  source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1155  else
1156 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1157  if (highres == MagickFalse)
1158  source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1159  else
1160 #endif
1161  source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1162  break;
1163  }
1164  case cmsSigXYZData:
1165  {
1166  source_info.colorspace=XYZColorspace;
1167 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1168  if (highres == MagickFalse)
1169  source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1170  else
1171 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1172  if (highres == MagickFalse)
1173  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1174  else
1175 #endif
1176  source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1177  break;
1178  }
1179  default:
1181  "ColorspaceColorProfileMismatch",name);
1182  }
1183  signature=cmsGetPCS(source_info.profile);
1184  if (target_info.profile != (cmsHPROFILE) NULL)
1185  signature=cmsGetColorSpace(target_info.profile);
1186  if (highres != MagickFalse)
1187  {
1188  target_info.scale=1.0;
1189  target_info.translate=0.0;
1190  }
1191  target_info.channels=3;
1192  switch (signature)
1193  {
1194  case cmsSigCmykData:
1195  {
1196  target_info.colorspace=CMYKColorspace;
1197  target_info.channels=4;
1198 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1199  if (highres == MagickFalse)
1200  target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1201  else
1202 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1203  if (highres == MagickFalse)
1204  target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1205  else
1206 #endif
1207  {
1208  target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1209  target_info.scale=0.01;
1210  }
1211  break;
1212  }
1213  case cmsSigGrayData:
1214  {
1215  target_info.colorspace=GRAYColorspace;
1216  target_info.channels=1;
1217 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1218  if (highres == MagickFalse)
1219  target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1220  else
1221 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1222  if (highres == MagickFalse)
1223  target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1224  else
1225 #endif
1226  target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1227  break;
1228  }
1229  case cmsSigLabData:
1230  {
1231  target_info.colorspace=LabColorspace;
1232 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1233  if (highres == MagickFalse)
1234  target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1235  else
1236 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1237  if (highres == MagickFalse)
1238  target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1239  else
1240 #endif
1241  {
1242  target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1243  target_info.scale=0.01;
1244  target_info.translate=0.5;
1245  }
1246  break;
1247  }
1248  case cmsSigRgbData:
1249  {
1250  target_info.colorspace=sRGBColorspace;
1251 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1252  if (highres == MagickFalse)
1253  target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1254  else
1255 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1256  if (highres == MagickFalse)
1257  target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1258  else
1259 #endif
1260  target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1261  break;
1262  }
1263  case cmsSigXYZData:
1264  {
1265  target_info.colorspace=XYZColorspace;
1266 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
1267  if (highres == MagickFalse)
1268  target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1269  else
1270 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1271  if (highres == MagickFalse)
1272  source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1273  else
1274 #endif
1275  target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1276  break;
1277  }
1278  default:
1280  "ColorspaceColorProfileMismatch",name);
1281  }
1282  switch (image->rendering_intent)
1283  {
1284  case AbsoluteIntent:
1285  {
1286  target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1287  break;
1288  }
1289  case PerceptualIntent:
1290  {
1291  target_info.intent=INTENT_PERCEPTUAL;
1292  break;
1293  }
1294  case RelativeIntent:
1295  {
1296  target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1297  break;
1298  }
1299  case SaturationIntent:
1300  {
1301  target_info.intent=INTENT_SATURATION;
1302  break;
1303  }
1304  default:
1305  {
1306  target_info.intent=INTENT_PERCEPTUAL;
1307  break;
1308  }
1309  }
1310  flags=cmsFLAGS_HIGHRESPRECALC;
1311 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1312  if (image->black_point_compensation != MagickFalse)
1313  flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1314 #endif
1315  transform=AcquireTransformThreadSet(&source_info,&target_info,
1316  flags,cms_context);
1317  if (transform == (cmsHTRANSFORM *) NULL)
1318  ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1319  name);
1320  /*
1321  Transform image as dictated by the source & target image profiles.
1322  */
1323  source_info.pixels=AcquirePixelThreadSet(image->columns,
1324  source_info.channels,highres);
1325  target_info.pixels=AcquirePixelThreadSet(image->columns,
1326  target_info.channels,highres);
1327  if ((source_info.pixels == (void **) NULL) ||
1328  (target_info.pixels == (void **) NULL))
1329  {
1330  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1331  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1332  transform=DestroyTransformThreadSet(transform);
1334  "MemoryAllocationFailed",image->filename);
1335  }
1336  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1337  {
1338  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1339  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1340  transform=DestroyTransformThreadSet(transform);
1341  if (source_info.profile != (cmsHPROFILE) NULL)
1342  (void) cmsCloseProfile(source_info.profile);
1343  if (target_info.profile != (cmsHPROFILE) NULL)
1344  (void) cmsCloseProfile(target_info.profile);
1345  return(MagickFalse);
1346  }
1347  if (target_info.colorspace == CMYKColorspace)
1348  (void) SetImageColorspace(image,target_info.colorspace,exception);
1349  progress=0;
1350  image_view=AcquireAuthenticCacheView(image,exception);
1351 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1352  #pragma omp parallel for schedule(static) shared(status) \
1353  magick_number_threads(image,image,image->rows,1)
1354 #endif
1355  for (y=0; y < (ssize_t) image->rows; y++)
1356  {
1357  const int
1358  id = GetOpenMPThreadId();
1359 
1361  sync;
1362 
1363  register Quantum
1364  *magick_restrict q;
1365 
1366  if (status == MagickFalse)
1367  continue;
1368  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1369  exception);
1370  if (q == (Quantum *) NULL)
1371  {
1372  status=MagickFalse;
1373  continue;
1374  }
1375  if (highres != MagickFalse)
1376  TransformDoublePixels(id,image,&source_info,&target_info,transform,q);
1377  else
1378  TransformQuantumPixels(id,image,&source_info,&target_info,transform,q);
1379  sync=SyncCacheViewAuthenticPixels(image_view,exception);
1380  if (sync == MagickFalse)
1381  status=MagickFalse;
1382  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1383  {
1385  proceed;
1386 
1387 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1388  #pragma omp atomic
1389 #endif
1390  progress++;
1391  proceed=SetImageProgress(image,ProfileImageTag,progress,
1392  image->rows);
1393  if (proceed == MagickFalse)
1394  status=MagickFalse;
1395  }
1396  }
1397  image_view=DestroyCacheView(image_view);
1398  (void) SetImageColorspace(image,target_info.colorspace,exception);
1399  switch (signature)
1400  {
1401  case cmsSigRgbData:
1402  {
1403  image->type=image->alpha_trait == UndefinedPixelTrait ?
1405  break;
1406  }
1407  case cmsSigCmykData:
1408  {
1409  image->type=image->alpha_trait == UndefinedPixelTrait ?
1411  break;
1412  }
1413  case cmsSigGrayData:
1414  {
1415  image->type=image->alpha_trait == UndefinedPixelTrait ?
1417  break;
1418  }
1419  default:
1420  break;
1421  }
1422  target_info.pixels=DestroyPixelThreadSet(target_info.pixels);
1423  source_info.pixels=DestroyPixelThreadSet(source_info.pixels);
1424  transform=DestroyTransformThreadSet(transform);
1425  if ((status != MagickFalse) &&
1426  (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1427  status=SetImageProfile(image,name,profile,exception);
1428  if (target_info.profile != (cmsHPROFILE) NULL)
1429  (void) cmsCloseProfile(target_info.profile);
1430  }
1431  (void) cmsCloseProfile(source_info.profile);
1432  cmsDeleteContext(cms_context);
1433  }
1434 #endif
1435  }
1436  profile=DestroyStringInfo(profile);
1437  return(status);
1438 }
1439 
1440 /*
1441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1442 % %
1443 % %
1444 % %
1445 % R e m o v e I m a g e P r o f i l e %
1446 % %
1447 % %
1448 % %
1449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1450 %
1451 % RemoveImageProfile() removes a named profile from the image and returns its
1452 % value.
1453 %
1454 % The format of the RemoveImageProfile method is:
1455 %
1456 % void *RemoveImageProfile(Image *image,const char *name)
1457 %
1458 % A description of each parameter follows:
1459 %
1460 % o image: the image.
1461 %
1462 % o name: the profile name.
1463 %
1464 */
1466 {
1467  StringInfo
1468  *profile;
1469 
1470  assert(image != (Image *) NULL);
1471  assert(image->signature == MagickCoreSignature);
1472  if (image->debug != MagickFalse)
1473  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1474  if (image->profiles == (SplayTreeInfo *) NULL)
1475  return((StringInfo *) NULL);
1476  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1478  image->profiles,name);
1479  return(profile);
1480 }
1481 
1482 /*
1483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1484 % %
1485 % %
1486 % %
1487 % R e s e t P r o f i l e I t e r a t o r %
1488 % %
1489 % %
1490 % %
1491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492 %
1493 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1494 % conjunction with GetNextImageProfile() to iterate over all the profiles
1495 % associated with an image.
1496 %
1497 % The format of the ResetImageProfileIterator method is:
1498 %
1499 % ResetImageProfileIterator(Image *image)
1500 %
1501 % A description of each parameter follows:
1502 %
1503 % o image: the image.
1504 %
1505 */
1507 {
1508  assert(image != (Image *) NULL);
1509  assert(image->signature == MagickCoreSignature);
1510  if (image->debug != MagickFalse)
1511  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1512  if (image->profiles == (SplayTreeInfo *) NULL)
1513  return;
1515 }
1516 
1517 /*
1518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1519 % %
1520 % %
1521 % %
1522 % S e t I m a g e P r o f i l e %
1523 % %
1524 % %
1525 % %
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 %
1528 % SetImageProfile() adds a named profile to the image. If a profile with the
1529 % same name already exists, it is replaced. This method differs from the
1530 % ProfileImage() method in that it does not apply CMS color profiles.
1531 %
1532 % The format of the SetImageProfile method is:
1533 %
1534 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1535 % const StringInfo *profile)
1536 %
1537 % A description of each parameter follows:
1538 %
1539 % o image: the image.
1540 %
1541 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1542 % Photoshop wrapper for iptc profiles).
1543 %
1544 % o profile: A StringInfo structure that contains the named profile.
1545 %
1546 */
1547 
1548 static void *DestroyProfile(void *profile)
1549 {
1550  return((void *) DestroyStringInfo((StringInfo *) profile));
1551 }
1552 
1553 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1554  unsigned char *quantum)
1555 {
1556  *quantum=(*p++);
1557  return(p);
1558 }
1559 
1560 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1561  unsigned int *quantum)
1562 {
1563  *quantum=(unsigned int) (*p++) << 24;
1564  *quantum|=(unsigned int) (*p++) << 16;
1565  *quantum|=(unsigned int) (*p++) << 8;
1566  *quantum|=(unsigned int) (*p++);
1567  return(p);
1568 }
1569 
1570 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1571  unsigned short *quantum)
1572 {
1573  *quantum=(unsigned short) (*p++) << 8;
1574  *quantum|=(unsigned short) (*p++);
1575  return(p);
1576 }
1577 
1578 static inline void WriteResourceLong(unsigned char *p,
1579  const unsigned int quantum)
1580 {
1581  unsigned char
1582  buffer[4];
1583 
1584  buffer[0]=(unsigned char) (quantum >> 24);
1585  buffer[1]=(unsigned char) (quantum >> 16);
1586  buffer[2]=(unsigned char) (quantum >> 8);
1587  buffer[3]=(unsigned char) quantum;
1588  (void) memcpy(p,buffer,4);
1589 }
1590 
1591 static void WriteTo8BimProfile(Image *image,const char *name,
1592  const StringInfo *profile)
1593 {
1594  const unsigned char
1595  *datum,
1596  *q;
1597 
1598  register const unsigned char
1599  *p;
1600 
1601  size_t
1602  length;
1603 
1604  StringInfo
1605  *profile_8bim;
1606 
1607  ssize_t
1608  count;
1609 
1610  unsigned char
1611  length_byte;
1612 
1613  unsigned int
1614  value;
1615 
1616  unsigned short
1617  id,
1618  profile_id;
1619 
1620  if (LocaleCompare(name,"icc") == 0)
1621  profile_id=0x040f;
1622  else
1623  if (LocaleCompare(name,"iptc") == 0)
1624  profile_id=0x0404;
1625  else
1626  if (LocaleCompare(name,"xmp") == 0)
1627  profile_id=0x0424;
1628  else
1629  return;
1630  profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1631  image->profiles,"8bim");
1632  if (profile_8bim == (StringInfo *) NULL)
1633  return;
1634  datum=GetStringInfoDatum(profile_8bim);
1635  length=GetStringInfoLength(profile_8bim);
1636  for (p=datum; p < (datum+length-16); )
1637  {
1638  q=p;
1639  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1640  break;
1641  p+=4;
1642  p=ReadResourceShort(p,&id);
1643  p=ReadResourceByte(p,&length_byte);
1644  p+=length_byte;
1645  if (((length_byte+1) & 0x01) != 0)
1646  p++;
1647  if (p > (datum+length-4))
1648  break;
1649  p=ReadResourceLong(p,&value);
1650  count=(ssize_t) value;
1651  if ((count & 0x01) != 0)
1652  count++;
1653  if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1654  break;
1655  if (id != profile_id)
1656  p+=count;
1657  else
1658  {
1659  size_t
1660  extent,
1661  offset;
1662 
1663  ssize_t
1664  extract_extent;
1665 
1666  StringInfo
1667  *extract_profile;
1668 
1669  extract_extent=0;
1670  extent=(datum+length)-(p+count);
1671  if (profile == (StringInfo *) NULL)
1672  {
1673  offset=(q-datum);
1674  extract_profile=AcquireStringInfo(offset+extent);
1675  (void) memcpy(extract_profile->datum,datum,offset);
1676  }
1677  else
1678  {
1679  offset=(p-datum);
1680  extract_extent=profile->length;
1681  if ((extract_extent & 0x01) != 0)
1682  extract_extent++;
1683  extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1684  (void) memcpy(extract_profile->datum,datum,offset-4);
1685  WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
1686  profile->length);
1687  (void) memcpy(extract_profile->datum+offset,
1688  profile->datum,profile->length);
1689  }
1690  (void) memcpy(extract_profile->datum+offset+extract_extent,
1691  p+count,extent);
1692  (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1693  ConstantString("8bim"),CloneStringInfo(extract_profile));
1694  extract_profile=DestroyStringInfo(extract_profile);
1695  break;
1696  }
1697  }
1698 }
1699 
1701  const StringInfo *resource_block,ExceptionInfo *exception)
1702 {
1703  const unsigned char
1704  *datum;
1705 
1706  register const unsigned char
1707  *p;
1708 
1709  size_t
1710  length;
1711 
1712  ssize_t
1713  count;
1714 
1715  StringInfo
1716  *profile;
1717 
1718  unsigned char
1719  length_byte;
1720 
1721  unsigned int
1722  value;
1723 
1724  unsigned short
1725  id;
1726 
1727  datum=GetStringInfoDatum(resource_block);
1728  length=GetStringInfoLength(resource_block);
1729  for (p=datum; p < (datum+length-16); )
1730  {
1731  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1732  break;
1733  p+=4;
1734  p=ReadResourceShort(p,&id);
1735  p=ReadResourceByte(p,&length_byte);
1736  p+=length_byte;
1737  if (((length_byte+1) & 0x01) != 0)
1738  p++;
1739  if (p > (datum+length-4))
1740  break;
1741  p=ReadResourceLong(p,&value);
1742  count=(ssize_t) value;
1743  if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1744  break;
1745  switch (id)
1746  {
1747  case 0x03ed:
1748  {
1749  unsigned int
1750  resolution;
1751 
1752  unsigned short
1753  units;
1754 
1755  /*
1756  Resolution.
1757  */
1758  if (count < 10)
1759  break;
1760  p=ReadResourceLong(p,&resolution);
1761  image->resolution.x=((double) resolution)/65536.0;
1762  p=ReadResourceShort(p,&units)+2;
1763  p=ReadResourceLong(p,&resolution)+4;
1764  image->resolution.y=((double) resolution)/65536.0;
1765  /*
1766  Values are always stored as pixels per inch.
1767  */
1770  else
1771  {
1773  image->resolution.x/=2.54;
1774  image->resolution.y/=2.54;
1775  }
1776  break;
1777  }
1778  case 0x0404:
1779  {
1780  /*
1781  IPTC Profile
1782  */
1783  profile=AcquireStringInfo(count);
1784  SetStringInfoDatum(profile,p);
1785  (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1786  exception);
1787  profile=DestroyStringInfo(profile);
1788  p+=count;
1789  break;
1790  }
1791  case 0x040c:
1792  {
1793  /*
1794  Thumbnail.
1795  */
1796  p+=count;
1797  break;
1798  }
1799  case 0x040f:
1800  {
1801  /*
1802  ICC Profile.
1803  */
1804  profile=AcquireStringInfo(count);
1805  SetStringInfoDatum(profile,p);
1806  (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1807  exception);
1808  profile=DestroyStringInfo(profile);
1809  p+=count;
1810  break;
1811  }
1812  case 0x0422:
1813  {
1814  /*
1815  EXIF Profile.
1816  */
1817  profile=AcquireStringInfo(count);
1818  SetStringInfoDatum(profile,p);
1819  (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1820  exception);
1821  profile=DestroyStringInfo(profile);
1822  p+=count;
1823  break;
1824  }
1825  case 0x0424:
1826  {
1827  /*
1828  XMP Profile.
1829  */
1830  profile=AcquireStringInfo(count);
1831  SetStringInfoDatum(profile,p);
1832  (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1833  exception);
1834  profile=DestroyStringInfo(profile);
1835  p+=count;
1836  break;
1837  }
1838  default:
1839  {
1840  p+=count;
1841  break;
1842  }
1843  }
1844  if ((count & 0x01) != 0)
1845  p++;
1846  }
1847 }
1848 
1849 #if defined(MAGICKCORE_XML_DELEGATE)
1850 static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
1851 {
1852  xmlDocPtr
1853  document;
1854 
1855  /*
1856  Parse XML profile.
1857  */
1858  document=xmlReadMemory((const char *) GetStringInfoDatum(profile),(int)
1859  GetStringInfoLength(profile),"xmp.xml",NULL,XML_PARSE_NOERROR |
1860  XML_PARSE_NOWARNING);
1861  if (document == (xmlDocPtr) NULL)
1862  return(MagickFalse);
1863  xmlFreeDoc(document);
1864  return(MagickTrue);
1865 }
1866 #else
1868 {
1869  return(MagickFalse);
1870 }
1871 #endif
1872 
1873 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1874  const StringInfo *profile,const MagickBooleanType recursive,
1875  ExceptionInfo *exception)
1876 {
1877  char
1878  key[MagickPathExtent];
1879 
1881  status;
1882 
1883  assert(image != (Image *) NULL);
1884  assert(image->signature == MagickCoreSignature);
1885  if (image->debug != MagickFalse)
1886  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1887  if ((LocaleCompare(name,"xmp") == 0) &&
1888  (ValidateXMPProfile(profile) == MagickFalse))
1889  {
1891  "CorruptImageProfile","`%s'",name);
1892  return(MagickTrue);
1893  }
1894  if (image->profiles == (SplayTreeInfo *) NULL)
1896  DestroyProfile);
1897  (void) CopyMagickString(key,name,MagickPathExtent);
1898  LocaleLower(key);
1899  status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1900  ConstantString(key),CloneStringInfo(profile));
1901  if (status != MagickFalse)
1902  {
1903  if (LocaleCompare(name,"8bim") == 0)
1904  GetProfilesFromResourceBlock(image,profile,exception);
1905  else
1906  if (recursive == MagickFalse)
1907  WriteTo8BimProfile(image,name,profile);
1908  }
1909  return(status);
1910 }
1911 
1913  const StringInfo *profile,ExceptionInfo *exception)
1914 {
1915  return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1916 }
1917 
1918 /*
1919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1920 % %
1921 % %
1922 % %
1923 % S y n c I m a g e P r o f i l e s %
1924 % %
1925 % %
1926 % %
1927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1928 %
1929 % SyncImageProfiles() synchronizes image properties with the image profiles.
1930 % Currently we only support updating the EXIF resolution and orientation.
1931 %
1932 % The format of the SyncImageProfiles method is:
1933 %
1934 % MagickBooleanType SyncImageProfiles(Image *image)
1935 %
1936 % A description of each parameter follows:
1937 %
1938 % o image: the image.
1939 %
1940 */
1941 
1942 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1943 {
1944  int
1945  c;
1946 
1947  if (*length < 1)
1948  return(EOF);
1949  c=(int) (*(*p)++);
1950  (*length)--;
1951  return(c);
1952 }
1953 
1954 static inline signed short ReadProfileShort(const EndianType endian,
1955  unsigned char *buffer)
1956 {
1957  union
1958  {
1959  unsigned int
1960  unsigned_value;
1961 
1962  signed int
1963  signed_value;
1964  } quantum;
1965 
1966  unsigned short
1967  value;
1968 
1969  if (endian == LSBEndian)
1970  {
1971  value=(unsigned short) buffer[1] << 8;
1972  value|=(unsigned short) buffer[0];
1973  quantum.unsigned_value=value & 0xffff;
1974  return(quantum.signed_value);
1975  }
1976  value=(unsigned short) buffer[0] << 8;
1977  value|=(unsigned short) buffer[1];
1978  quantum.unsigned_value=value & 0xffff;
1979  return(quantum.signed_value);
1980 }
1981 
1982 static inline signed int ReadProfileLong(const EndianType endian,
1983  unsigned char *buffer)
1984 {
1985  union
1986  {
1987  unsigned int
1988  unsigned_value;
1989 
1990  signed int
1991  signed_value;
1992  } quantum;
1993 
1994  unsigned int
1995  value;
1996 
1997  if (endian == LSBEndian)
1998  {
1999  value=(unsigned int) buffer[3] << 24;
2000  value|=(unsigned int) buffer[2] << 16;
2001  value|=(unsigned int) buffer[1] << 8;
2002  value|=(unsigned int) buffer[0];
2003  quantum.unsigned_value=value & 0xffffffff;
2004  return(quantum.signed_value);
2005  }
2006  value=(unsigned int) buffer[0] << 24;
2007  value|=(unsigned int) buffer[1] << 16;
2008  value|=(unsigned int) buffer[2] << 8;
2009  value|=(unsigned int) buffer[3];
2010  quantum.unsigned_value=value & 0xffffffff;
2011  return(quantum.signed_value);
2012 }
2013 
2014 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
2015 {
2016  signed int
2017  value;
2018 
2019  if (*length < 4)
2020  return(0);
2021  value=ReadProfileLong(MSBEndian,*p);
2022  (*length)-=4;
2023  *p+=4;
2024  return(value);
2025 }
2026 
2027 static inline signed short ReadProfileMSBShort(unsigned char **p,
2028  size_t *length)
2029 {
2030  signed short
2031  value;
2032 
2033  if (*length < 2)
2034  return(0);
2035  value=ReadProfileShort(MSBEndian,*p);
2036  (*length)-=2;
2037  *p+=2;
2038  return(value);
2039 }
2040 
2041 static inline void WriteProfileLong(const EndianType endian,
2042  const size_t value,unsigned char *p)
2043 {
2044  unsigned char
2045  buffer[4];
2046 
2047  if (endian == LSBEndian)
2048  {
2049  buffer[0]=(unsigned char) value;
2050  buffer[1]=(unsigned char) (value >> 8);
2051  buffer[2]=(unsigned char) (value >> 16);
2052  buffer[3]=(unsigned char) (value >> 24);
2053  (void) memcpy(p,buffer,4);
2054  return;
2055  }
2056  buffer[0]=(unsigned char) (value >> 24);
2057  buffer[1]=(unsigned char) (value >> 16);
2058  buffer[2]=(unsigned char) (value >> 8);
2059  buffer[3]=(unsigned char) value;
2060  (void) memcpy(p,buffer,4);
2061 }
2062 
2063 static void WriteProfileShort(const EndianType endian,
2064  const unsigned short value,unsigned char *p)
2065 {
2066  unsigned char
2067  buffer[2];
2068 
2069  if (endian == LSBEndian)
2070  {
2071  buffer[0]=(unsigned char) value;
2072  buffer[1]=(unsigned char) (value >> 8);
2073  (void) memcpy(p,buffer,2);
2074  return;
2075  }
2076  buffer[0]=(unsigned char) (value >> 8);
2077  buffer[1]=(unsigned char) value;
2078  (void) memcpy(p,buffer,2);
2079 }
2080 
2082 {
2083  size_t
2084  length;
2085 
2086  ssize_t
2087  count;
2088 
2089  unsigned char
2090  *p;
2091 
2092  unsigned short
2093  id;
2094 
2095  length=GetStringInfoLength(profile);
2096  p=GetStringInfoDatum(profile);
2097  while (length != 0)
2098  {
2099  if (ReadProfileByte(&p,&length) != 0x38)
2100  continue;
2101  if (ReadProfileByte(&p,&length) != 0x42)
2102  continue;
2103  if (ReadProfileByte(&p,&length) != 0x49)
2104  continue;
2105  if (ReadProfileByte(&p,&length) != 0x4D)
2106  continue;
2107  if (length < 7)
2108  return(MagickFalse);
2109  id=ReadProfileMSBShort(&p,&length);
2110  count=(ssize_t) ReadProfileByte(&p,&length);
2111  if ((count >= (ssize_t) length) || (count < 0))
2112  return(MagickFalse);
2113  p+=count;
2114  length-=count;
2115  if ((*p & 0x01) == 0)
2116  (void) ReadProfileByte(&p,&length);
2117  count=(ssize_t) ReadProfileMSBLong(&p,&length);
2118  if ((count > (ssize_t) length) || (count < 0))
2119  return(MagickFalse);
2120  if ((id == 0x3ED) && (count == 16))
2121  {
2122  if (image->units == PixelsPerCentimeterResolution)
2123  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
2124  65536.0),p);
2125  else
2126  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
2127  65536.0),p);
2128  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2129  if (image->units == PixelsPerCentimeterResolution)
2130  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
2131  65536.0),p+8);
2132  else
2133  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
2134  65536.0),p+8);
2135  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2136  }
2137  p+=count;
2138  length-=count;
2139  }
2140  return(MagickTrue);
2141 }
2142 
2144 {
2145 #define MaxDirectoryStack 16
2146 #define EXIF_DELIMITER "\n"
2147 #define EXIF_NUM_FORMATS 12
2148 #define TAG_EXIF_OFFSET 0x8769
2149 #define TAG_INTEROP_OFFSET 0xa005
2150 
2151  typedef struct _DirectoryInfo
2152  {
2153  unsigned char
2154  *directory;
2155 
2156  size_t
2157  entry;
2158  } DirectoryInfo;
2159 
2160  DirectoryInfo
2161  directory_stack[MaxDirectoryStack];
2162 
2163  EndianType
2164  endian;
2165 
2166  size_t
2167  entry,
2168  length,
2169  number_entries;
2170 
2172  *exif_resources;
2173 
2174  ssize_t
2175  id,
2176  level,
2177  offset;
2178 
2179  static int
2180  format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2181 
2182  unsigned char
2183  *directory,
2184  *exif;
2185 
2186  /*
2187  Set EXIF resolution tag.
2188  */
2189  length=GetStringInfoLength(profile);
2190  exif=GetStringInfoDatum(profile);
2191  if (length < 16)
2192  return(MagickFalse);
2193  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2194  if ((id != 0x4949) && (id != 0x4D4D))
2195  {
2196  while (length != 0)
2197  {
2198  if (ReadProfileByte(&exif,&length) != 0x45)
2199  continue;
2200  if (ReadProfileByte(&exif,&length) != 0x78)
2201  continue;
2202  if (ReadProfileByte(&exif,&length) != 0x69)
2203  continue;
2204  if (ReadProfileByte(&exif,&length) != 0x66)
2205  continue;
2206  if (ReadProfileByte(&exif,&length) != 0x00)
2207  continue;
2208  if (ReadProfileByte(&exif,&length) != 0x00)
2209  continue;
2210  break;
2211  }
2212  if (length < 16)
2213  return(MagickFalse);
2214  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2215  }
2216  endian=LSBEndian;
2217  if (id == 0x4949)
2218  endian=LSBEndian;
2219  else
2220  if (id == 0x4D4D)
2221  endian=MSBEndian;
2222  else
2223  return(MagickFalse);
2224  if (ReadProfileShort(endian,exif+2) != 0x002a)
2225  return(MagickFalse);
2226  /*
2227  This the offset to the first IFD.
2228  */
2229  offset=(ssize_t) ReadProfileLong(endian,exif+4);
2230  if ((offset < 0) || ((size_t) offset >= length))
2231  return(MagickFalse);
2232  directory=exif+offset;
2233  level=0;
2234  entry=0;
2235  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2236  (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2237  do
2238  {
2239  if (level > 0)
2240  {
2241  level--;
2242  directory=directory_stack[level].directory;
2243  entry=directory_stack[level].entry;
2244  }
2245  if ((directory < exif) || (directory > (exif+length-2)))
2246  break;
2247  /*
2248  Determine how many entries there are in the current IFD.
2249  */
2250  number_entries=ReadProfileShort(endian,directory);
2251  for ( ; entry < number_entries; entry++)
2252  {
2253  int
2254  components;
2255 
2256  register unsigned char
2257  *p,
2258  *q;
2259 
2260  size_t
2261  number_bytes;
2262 
2263  ssize_t
2264  format,
2265  tag_value;
2266 
2267  q=(unsigned char *) (directory+2+(12*entry));
2268  if (q > (exif+length-12))
2269  break; /* corrupt EXIF */
2270  if (GetValueFromSplayTree(exif_resources,q) == q)
2271  break;
2272  (void) AddValueToSplayTree(exif_resources,q,q);
2273  tag_value=(ssize_t) ReadProfileShort(endian,q);
2274  format=(ssize_t) ReadProfileShort(endian,q+2);
2275  if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2276  break;
2277  components=(int) ReadProfileLong(endian,q+4);
2278  if (components < 0)
2279  break; /* corrupt EXIF */
2280  number_bytes=(size_t) components*format_bytes[format];
2281  if ((ssize_t) number_bytes < components)
2282  break; /* prevent overflow */
2283  if (number_bytes <= 4)
2284  p=q+8;
2285  else
2286  {
2287  /*
2288  The directory entry contains an offset.
2289  */
2290  offset=(ssize_t) ReadProfileLong(endian,q+8);
2291  if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2292  continue;
2293  if (~length < number_bytes)
2294  continue; /* prevent overflow */
2295  p=(unsigned char *) (exif+offset);
2296  }
2297  switch (tag_value)
2298  {
2299  case 0x011a:
2300  {
2301  (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2302  if (number_bytes == 8)
2303  (void) WriteProfileLong(endian,1UL,p+4);
2304  break;
2305  }
2306  case 0x011b:
2307  {
2308  (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2309  if (number_bytes == 8)
2310  (void) WriteProfileLong(endian,1UL,p+4);
2311  break;
2312  }
2313  case 0x0112:
2314  {
2315  if (number_bytes == 4)
2316  {
2317  (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2318  break;
2319  }
2320  (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2321  p);
2322  break;
2323  }
2324  case 0x0128:
2325  {
2326  if (number_bytes == 4)
2327  {
2328  (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2329  break;
2330  }
2331  (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2332  break;
2333  }
2334  default:
2335  break;
2336  }
2337  if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2338  {
2339  offset=(ssize_t) ReadProfileLong(endian,p);
2340  if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2341  {
2342  directory_stack[level].directory=directory;
2343  entry++;
2344  directory_stack[level].entry=entry;
2345  level++;
2346  directory_stack[level].directory=exif+offset;
2347  directory_stack[level].entry=0;
2348  level++;
2349  if ((directory+2+(12*number_entries)) > (exif+length))
2350  break;
2351  offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2352  number_entries));
2353  if ((offset != 0) && ((size_t) offset < length) &&
2354  (level < (MaxDirectoryStack-2)))
2355  {
2356  directory_stack[level].directory=exif+offset;
2357  directory_stack[level].entry=0;
2358  level++;
2359  }
2360  }
2361  break;
2362  }
2363  }
2364  } while (level > 0);
2365  exif_resources=DestroySplayTree(exif_resources);
2366  return(MagickTrue);
2367 }
2368 
2370 {
2372  status;
2373 
2374  StringInfo
2375  *profile;
2376 
2377  status=MagickTrue;
2378  profile=(StringInfo *) GetImageProfile(image,"8BIM");
2379  if (profile != (StringInfo *) NULL)
2380  if (Sync8BimProfile(image,profile) == MagickFalse)
2381  status=MagickFalse;
2382  profile=(StringInfo *) GetImageProfile(image,"EXIF");
2383  if (profile != (StringInfo *) NULL)
2384  if (SyncExifProfile(image,profile) == MagickFalse)
2385  status=MagickFalse;
2386  return(status);
2387 }
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:1456
MagickExport int CompareStringInfo(const StringInfo *target, const StringInfo *source)
Definition: string.c:380
MagickExport MagickBooleanType IsOptionMember(const char *option, const char *options)
Definition: option.c:2740
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:1982
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:1873
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:1553
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:1548
struct _CMSExceptionInfo CMSExceptionInfo
MagickBooleanType SyncExifProfile(Image *image, StringInfo *profile)
Definition: profile.c:2143
MagickExport void DestroyImageProfiles(Image *image)
Definition: profile.c:229
MagickExport size_t CopyMagickString(char *magick_restrict destination, const char *magick_restrict source, const size_t length)
Definition: string.c:756
ResolutionType units
Definition: image.h:198
static void WriteProfileShort(const EndianType endian, const unsigned short value, unsigned char *p)
Definition: profile.c:2063
unsigned char * info
Definition: profile.c:112
#define ThrowBinaryException(severity, tag, context)
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:133
EndianType
Definition: quantum.h:29
Definition: image.h:151
double x
Definition: geometry.h:123
#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:1205
#define MaxDirectoryStack
MagickBooleanType
Definition: magick-type.h:169
MagickExport void LocaleLower(char *string)
Definition: locale.c:1490
static void WriteProfileLong(const EndianType endian, const size_t value, unsigned char *p)
Definition: profile.c:2041
MagickBooleanType black_point_compensation
Definition: image.h:258
static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
Definition: profile.c:1867
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:840
static void GetProfilesFromResourceBlock(Image *image, const StringInfo *resource_block, ExceptionInfo *exception)
Definition: profile.c:1700
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:634
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:1570
double y
Definition: geometry.h:123
static int GetOpenMPThreadId(void)
static signed short ReadProfileShort(const EndianType endian, unsigned char *buffer)
Definition: profile.c:1954
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
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:1591
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)
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:1570
static DoublePixelPacket ** AcquirePixelThreadSet(const size_t count)
Definition: quantize.c:1443
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:2595
MagickExport StringInfo * RemoveImageProfile(Image *image, const char *name)
Definition: profile.c:1465
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:187
MagickExport MagickBooleanType SetImageProfile(Image *image, const char *name, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1912
static MagickBooleanType Sync8BimProfile(Image *image, StringInfo *profile)
Definition: profile.c:2081
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1435
char filename[MagickPathExtent]
Definition: image.h:319
MagickExport SplayTreeInfo * CloneSplayTree(SplayTreeInfo *splay_tree, void *(*clone_key)(void *), void *(*clone_value)(void *))
Definition: splay-tree.c:346
#define GetMagickModule()
Definition: log.h:28
MagickExport int CompareSplayTreeString(const void *target, const void *source)
Definition: splay-tree.c:412
RenderingIntent rendering_intent
Definition: image.h:192
MagickExport const void * GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:769
#define EXIF_NUM_FORMATS
unsigned short Quantum
Definition: magick-type.h:86
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1312
MagickExport const char * GetImageProperty(const Image *image, const char *property, ExceptionInfo *exception)
Definition: property.c:2237
static signed int ReadProfileMSBLong(unsigned char **p, size_t *length)
Definition: profile.c:2014
#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:1578
size_t length
Definition: profile.c:109
ColorspaceType
Definition: colorspace.h:25
MagickPrivate MagickBooleanType SyncImageProfiles(Image *)
Definition: profile.c:2369
MagickExport void ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:1472
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1123
PointInfo resolution
Definition: image.h:209
#define magick_unreferenced(x)
#define TAG_EXIF_OFFSET
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
static int ReadProfileByte(unsigned char **p, size_t *length)
Definition: profile.c:1942
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:1506
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
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:1234
static signed short ReadProfileMSBShort(unsigned char **p, size_t *length)
Definition: profile.c:2027
MagickExport char * ConstantString(const char *source)
Definition: string.c:702
static const unsigned char * ReadResourceLong(const unsigned char *p, unsigned int *quantum)
Definition: profile.c:1560
ColorspaceType colorspace
Definition: image.h:157
MagickExport StringInfo * CloneStringInfo(const StringInfo *string_info)
Definition: string.c:338
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
MagickExport void SetStringInfoDatum(StringInfo *string_info, const unsigned char *source)
Definition: string.c:1702
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)