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  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  register 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  register 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  register 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 #if defined(MAGICKCORE_XML_DELEGATE)
1844 static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
1845 {
1846  xmlDocPtr
1847  document;
1848 
1849  /*
1850  Parse XML profile.
1851  */
1852  document=xmlReadMemory((const char *) GetStringInfoDatum(profile),(int)
1853  GetStringInfoLength(profile),"xmp.xml",NULL,XML_PARSE_NOERROR |
1854  XML_PARSE_NOWARNING);
1855  if (document == (xmlDocPtr) NULL)
1856  return(MagickFalse);
1857  xmlFreeDoc(document);
1858  return(MagickTrue);
1859 }
1860 #else
1862 {
1863  return(MagickFalse);
1864 }
1865 #endif
1866 
1867 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1868  const StringInfo *profile,const MagickBooleanType recursive,
1869  ExceptionInfo *exception)
1870 {
1871  char
1872  key[MagickPathExtent];
1873 
1875  status;
1876 
1877  assert(image != (Image *) NULL);
1878  assert(image->signature == MagickCoreSignature);
1879  if (image->debug != MagickFalse)
1880  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1881  if ((LocaleCompare(name,"xmp") == 0) &&
1882  (ValidateXMPProfile(profile) == MagickFalse))
1883  {
1885  "CorruptImageProfile","`%s'",name);
1886  return(MagickTrue);
1887  }
1888  if (image->profiles == (SplayTreeInfo *) NULL)
1890  DestroyProfile);
1891  (void) CopyMagickString(key,name,MagickPathExtent);
1892  LocaleLower(key);
1893  status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1894  ConstantString(key),CloneStringInfo(profile));
1895  if (status != MagickFalse)
1896  {
1897  if (LocaleCompare(name,"8bim") == 0)
1898  GetProfilesFromResourceBlock(image,profile,exception);
1899  else
1900  if (recursive == MagickFalse)
1901  WriteTo8BimProfile(image,name,profile);
1902  }
1903  return(status);
1904 }
1905 
1907  const StringInfo *profile,ExceptionInfo *exception)
1908 {
1909  return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1910 }
1911 
1912 /*
1913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1914 % %
1915 % %
1916 % %
1917 % S y n c I m a g e P r o f i l e s %
1918 % %
1919 % %
1920 % %
1921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1922 %
1923 % SyncImageProfiles() synchronizes image properties with the image profiles.
1924 % Currently we only support updating the EXIF resolution and orientation.
1925 %
1926 % The format of the SyncImageProfiles method is:
1927 %
1928 % MagickBooleanType SyncImageProfiles(Image *image)
1929 %
1930 % A description of each parameter follows:
1931 %
1932 % o image: the image.
1933 %
1934 */
1935 
1936 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1937 {
1938  int
1939  c;
1940 
1941  if (*length < 1)
1942  return(EOF);
1943  c=(int) (*(*p)++);
1944  (*length)--;
1945  return(c);
1946 }
1947 
1948 static inline signed short ReadProfileShort(const EndianType endian,
1949  unsigned char *buffer)
1950 {
1951  union
1952  {
1953  unsigned int
1954  unsigned_value;
1955 
1956  signed int
1957  signed_value;
1958  } quantum;
1959 
1960  unsigned short
1961  value;
1962 
1963  if (endian == LSBEndian)
1964  {
1965  value=(unsigned short) buffer[1] << 8;
1966  value|=(unsigned short) buffer[0];
1967  quantum.unsigned_value=value & 0xffff;
1968  return(quantum.signed_value);
1969  }
1970  value=(unsigned short) buffer[0] << 8;
1971  value|=(unsigned short) buffer[1];
1972  quantum.unsigned_value=value & 0xffff;
1973  return(quantum.signed_value);
1974 }
1975 
1976 static inline signed int ReadProfileLong(const EndianType endian,
1977  unsigned char *buffer)
1978 {
1979  union
1980  {
1981  unsigned int
1982  unsigned_value;
1983 
1984  signed int
1985  signed_value;
1986  } quantum;
1987 
1988  unsigned int
1989  value;
1990 
1991  if (endian == LSBEndian)
1992  {
1993  value=(unsigned int) buffer[3] << 24;
1994  value|=(unsigned int) buffer[2] << 16;
1995  value|=(unsigned int) buffer[1] << 8;
1996  value|=(unsigned int) buffer[0];
1997  quantum.unsigned_value=value & 0xffffffff;
1998  return(quantum.signed_value);
1999  }
2000  value=(unsigned int) buffer[0] << 24;
2001  value|=(unsigned int) buffer[1] << 16;
2002  value|=(unsigned int) buffer[2] << 8;
2003  value|=(unsigned int) buffer[3];
2004  quantum.unsigned_value=value & 0xffffffff;
2005  return(quantum.signed_value);
2006 }
2007 
2008 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
2009 {
2010  signed int
2011  value;
2012 
2013  if (*length < 4)
2014  return(0);
2015  value=ReadProfileLong(MSBEndian,*p);
2016  (*length)-=4;
2017  *p+=4;
2018  return(value);
2019 }
2020 
2021 static inline signed short ReadProfileMSBShort(unsigned char **p,
2022  size_t *length)
2023 {
2024  signed short
2025  value;
2026 
2027  if (*length < 2)
2028  return(0);
2029  value=ReadProfileShort(MSBEndian,*p);
2030  (*length)-=2;
2031  *p+=2;
2032  return(value);
2033 }
2034 
2035 static inline void WriteProfileLong(const EndianType endian,
2036  const size_t value,unsigned char *p)
2037 {
2038  unsigned char
2039  buffer[4];
2040 
2041  if (endian == LSBEndian)
2042  {
2043  buffer[0]=(unsigned char) value;
2044  buffer[1]=(unsigned char) (value >> 8);
2045  buffer[2]=(unsigned char) (value >> 16);
2046  buffer[3]=(unsigned char) (value >> 24);
2047  (void) memcpy(p,buffer,4);
2048  return;
2049  }
2050  buffer[0]=(unsigned char) (value >> 24);
2051  buffer[1]=(unsigned char) (value >> 16);
2052  buffer[2]=(unsigned char) (value >> 8);
2053  buffer[3]=(unsigned char) value;
2054  (void) memcpy(p,buffer,4);
2055 }
2056 
2057 static void WriteProfileShort(const EndianType endian,
2058  const unsigned short value,unsigned char *p)
2059 {
2060  unsigned char
2061  buffer[2];
2062 
2063  if (endian == LSBEndian)
2064  {
2065  buffer[0]=(unsigned char) value;
2066  buffer[1]=(unsigned char) (value >> 8);
2067  (void) memcpy(p,buffer,2);
2068  return;
2069  }
2070  buffer[0]=(unsigned char) (value >> 8);
2071  buffer[1]=(unsigned char) value;
2072  (void) memcpy(p,buffer,2);
2073 }
2074 
2076 {
2077  size_t
2078  length;
2079 
2080  ssize_t
2081  count;
2082 
2083  unsigned char
2084  *p;
2085 
2086  unsigned short
2087  id;
2088 
2089  length=GetStringInfoLength(profile);
2090  p=GetStringInfoDatum(profile);
2091  while (length != 0)
2092  {
2093  if (ReadProfileByte(&p,&length) != 0x38)
2094  continue;
2095  if (ReadProfileByte(&p,&length) != 0x42)
2096  continue;
2097  if (ReadProfileByte(&p,&length) != 0x49)
2098  continue;
2099  if (ReadProfileByte(&p,&length) != 0x4D)
2100  continue;
2101  if (length < 7)
2102  return(MagickFalse);
2103  id=ReadProfileMSBShort(&p,&length);
2104  count=(ssize_t) ReadProfileByte(&p,&length);
2105  if ((count >= (ssize_t) length) || (count < 0))
2106  return(MagickFalse);
2107  p+=count;
2108  length-=count;
2109  if ((*p & 0x01) == 0)
2110  (void) ReadProfileByte(&p,&length);
2111  count=(ssize_t) ReadProfileMSBLong(&p,&length);
2112  if ((count > (ssize_t) length) || (count < 0))
2113  return(MagickFalse);
2114  if ((id == 0x3ED) && (count == 16))
2115  {
2116  if (image->units == PixelsPerCentimeterResolution)
2117  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
2118  65536.0),p);
2119  else
2120  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
2121  65536.0),p);
2122  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2123  if (image->units == PixelsPerCentimeterResolution)
2124  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
2125  65536.0),p+8);
2126  else
2127  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
2128  65536.0),p+8);
2129  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2130  }
2131  p+=count;
2132  length-=count;
2133  }
2134  return(MagickTrue);
2135 }
2136 
2138 {
2139 #define MaxDirectoryStack 16
2140 #define EXIF_DELIMITER "\n"
2141 #define EXIF_NUM_FORMATS 12
2142 #define TAG_EXIF_OFFSET 0x8769
2143 #define TAG_INTEROP_OFFSET 0xa005
2144 
2145  typedef struct _DirectoryInfo
2146  {
2147  unsigned char
2148  *directory;
2149 
2150  size_t
2151  entry;
2152  } DirectoryInfo;
2153 
2154  DirectoryInfo
2155  directory_stack[MaxDirectoryStack];
2156 
2157  EndianType
2158  endian;
2159 
2160  size_t
2161  entry,
2162  length,
2163  number_entries;
2164 
2166  *exif_resources;
2167 
2168  ssize_t
2169  id,
2170  level,
2171  offset;
2172 
2173  static int
2174  format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2175 
2176  unsigned char
2177  *directory,
2178  *exif;
2179 
2180  /*
2181  Set EXIF resolution tag.
2182  */
2183  length=GetStringInfoLength(profile);
2184  exif=GetStringInfoDatum(profile);
2185  if (length < 16)
2186  return(MagickFalse);
2187  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2188  if ((id != 0x4949) && (id != 0x4D4D))
2189  {
2190  while (length != 0)
2191  {
2192  if (ReadProfileByte(&exif,&length) != 0x45)
2193  continue;
2194  if (ReadProfileByte(&exif,&length) != 0x78)
2195  continue;
2196  if (ReadProfileByte(&exif,&length) != 0x69)
2197  continue;
2198  if (ReadProfileByte(&exif,&length) != 0x66)
2199  continue;
2200  if (ReadProfileByte(&exif,&length) != 0x00)
2201  continue;
2202  if (ReadProfileByte(&exif,&length) != 0x00)
2203  continue;
2204  break;
2205  }
2206  if (length < 16)
2207  return(MagickFalse);
2208  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2209  }
2210  endian=LSBEndian;
2211  if (id == 0x4949)
2212  endian=LSBEndian;
2213  else
2214  if (id == 0x4D4D)
2215  endian=MSBEndian;
2216  else
2217  return(MagickFalse);
2218  if (ReadProfileShort(endian,exif+2) != 0x002a)
2219  return(MagickFalse);
2220  /*
2221  This the offset to the first IFD.
2222  */
2223  offset=(ssize_t) ReadProfileLong(endian,exif+4);
2224  if ((offset < 0) || ((size_t) offset >= length))
2225  return(MagickFalse);
2226  directory=exif+offset;
2227  level=0;
2228  entry=0;
2229  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2230  (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2231  do
2232  {
2233  if (level > 0)
2234  {
2235  level--;
2236  directory=directory_stack[level].directory;
2237  entry=directory_stack[level].entry;
2238  }
2239  if ((directory < exif) || (directory > (exif+length-2)))
2240  break;
2241  /*
2242  Determine how many entries there are in the current IFD.
2243  */
2244  number_entries=ReadProfileShort(endian,directory);
2245  for ( ; entry < number_entries; entry++)
2246  {
2247  int
2248  components;
2249 
2250  register unsigned char
2251  *p,
2252  *q;
2253 
2254  size_t
2255  number_bytes;
2256 
2257  ssize_t
2258  format,
2259  tag_value;
2260 
2261  q=(unsigned char *) (directory+2+(12*entry));
2262  if (q > (exif+length-12))
2263  break; /* corrupt EXIF */
2264  if (GetValueFromSplayTree(exif_resources,q) == q)
2265  break;
2266  (void) AddValueToSplayTree(exif_resources,q,q);
2267  tag_value=(ssize_t) ReadProfileShort(endian,q);
2268  format=(ssize_t) ReadProfileShort(endian,q+2);
2269  if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2270  break;
2271  components=(int) ReadProfileLong(endian,q+4);
2272  if (components < 0)
2273  break; /* corrupt EXIF */
2274  number_bytes=(size_t) components*format_bytes[format];
2275  if ((ssize_t) number_bytes < components)
2276  break; /* prevent overflow */
2277  if (number_bytes <= 4)
2278  p=q+8;
2279  else
2280  {
2281  /*
2282  The directory entry contains an offset.
2283  */
2284  offset=(ssize_t) ReadProfileLong(endian,q+8);
2285  if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2286  continue;
2287  if (~length < number_bytes)
2288  continue; /* prevent overflow */
2289  p=(unsigned char *) (exif+offset);
2290  }
2291  switch (tag_value)
2292  {
2293  case 0x011a:
2294  {
2295  (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2296  if (number_bytes == 8)
2297  (void) WriteProfileLong(endian,1UL,p+4);
2298  break;
2299  }
2300  case 0x011b:
2301  {
2302  (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2303  if (number_bytes == 8)
2304  (void) WriteProfileLong(endian,1UL,p+4);
2305  break;
2306  }
2307  case 0x0112:
2308  {
2309  if (number_bytes == 4)
2310  {
2311  (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2312  break;
2313  }
2314  (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2315  p);
2316  break;
2317  }
2318  case 0x0128:
2319  {
2320  if (number_bytes == 4)
2321  {
2322  (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2323  break;
2324  }
2325  (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2326  break;
2327  }
2328  default:
2329  break;
2330  }
2331  if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2332  {
2333  offset=(ssize_t) ReadProfileLong(endian,p);
2334  if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2335  {
2336  directory_stack[level].directory=directory;
2337  entry++;
2338  directory_stack[level].entry=entry;
2339  level++;
2340  directory_stack[level].directory=exif+offset;
2341  directory_stack[level].entry=0;
2342  level++;
2343  if ((directory+2+(12*number_entries)) > (exif+length))
2344  break;
2345  offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2346  number_entries));
2347  if ((offset != 0) && ((size_t) offset < length) &&
2348  (level < (MaxDirectoryStack-2)))
2349  {
2350  directory_stack[level].directory=exif+offset;
2351  directory_stack[level].entry=0;
2352  level++;
2353  }
2354  }
2355  break;
2356  }
2357  }
2358  } while (level > 0);
2359  exif_resources=DestroySplayTree(exif_resources);
2360  return(MagickTrue);
2361 }
2362 
2364 {
2366  status;
2367 
2368  StringInfo
2369  *profile;
2370 
2371  status=MagickTrue;
2372  profile=(StringInfo *) GetImageProfile(image,"8BIM");
2373  if (profile != (StringInfo *) NULL)
2374  if (Sync8BimProfile(image,profile) == MagickFalse)
2375  status=MagickFalse;
2376  profile=(StringInfo *) GetImageProfile(image,"EXIF");
2377  if (profile != (StringInfo *) NULL)
2378  if (SyncExifProfile(image,profile) == MagickFalse)
2379  status=MagickFalse;
2380  return(status);
2381 }
2382 
2383 static void UpdateClipPath(unsigned char *blob,size_t length,
2384  const size_t old_columns,const size_t old_rows,
2385  const RectangleInfo *new_geometry)
2386 {
2387  register ssize_t
2388  i;
2389 
2390  ssize_t
2391  knot_count,
2392  selector;
2393 
2394  knot_count=0;
2395  while (length != 0)
2396  {
2397  selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2398  switch (selector)
2399  {
2400  case 0:
2401  case 3:
2402  {
2403  if (knot_count != 0)
2404  {
2405  blob+=24;
2406  length-=MagickMin(24,(ssize_t) length);
2407  break;
2408  }
2409  /*
2410  Expected subpath length record.
2411  */
2412  knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2413  blob+=22;
2414  length-=MagickMin(22,(ssize_t) length);
2415  break;
2416  }
2417  case 1:
2418  case 2:
2419  case 4:
2420  case 5:
2421  {
2422  if (knot_count == 0)
2423  {
2424  /*
2425  Unexpected subpath knot.
2426  */
2427  blob+=24;
2428  length-=MagickMin(24,(ssize_t) length);
2429  break;
2430  }
2431  /*
2432  Add sub-path knot
2433  */
2434  for (i=0; i < 3; i++)
2435  {
2436  double
2437  x,
2438  y;
2439 
2440  signed int
2441  xx,
2442  yy;
2443 
2444  y=(double) ReadProfileMSBLong(&blob,&length);
2445  y=y*old_rows/4096/4096;
2446  y-=new_geometry->y;
2447  yy=(signed int) ((y*4096*4096)/new_geometry->height);
2448  WriteProfileLong(MSBEndian,(size_t) yy,blob-4);
2449  x=(double) ReadProfileMSBLong(&blob,&length);
2450  x=x*old_columns/4096/4096;
2451  x-=new_geometry->x;
2452  xx=(signed int) ((x*4096*4096)/new_geometry->width);
2453  WriteProfileLong(MSBEndian,(size_t) xx,blob-4);
2454  }
2455  knot_count--;
2456  break;
2457  }
2458  case 6:
2459  case 7:
2460  case 8:
2461  default:
2462  {
2463  blob+=24;
2464  length-=MagickMin(24,(ssize_t) length);
2465  break;
2466  }
2467  }
2468  }
2469 }
2470 
2472  const size_t old_columns,const size_t old_rows,
2473  const RectangleInfo *new_geometry)
2474 {
2475  unsigned char
2476  *info;
2477 
2478  size_t
2479  length;
2480 
2481  ssize_t
2482  count,
2483  id;
2484 
2485  assert(profile != (StringInfo *) NULL);
2486  assert(new_geometry != (RectangleInfo *) NULL);
2487  length=GetStringInfoLength(profile);
2488  info=GetStringInfoDatum(profile);
2489  while (length > 0)
2490  {
2491  if (ReadProfileByte(&info,&length) != (unsigned char) '8')
2492  continue;
2493  if (ReadProfileByte(&info,&length) != (unsigned char) 'B')
2494  continue;
2495  if (ReadProfileByte(&info,&length) != (unsigned char) 'I')
2496  continue;
2497  if (ReadProfileByte(&info,&length) != (unsigned char) 'M')
2498  continue;
2499  id=(ssize_t) ReadProfileMSBShort(&info,&length);
2500  count=(ssize_t) ReadProfileByte(&info,&length);
2501  if ((count != 0) && ((size_t) count <= length))
2502  {
2503  info+=count;
2504  length-=count;
2505  }
2506  if ((count & 0x01) == 0)
2507  (void) ReadProfileByte(&info,&length);
2508  count=(ssize_t) ReadProfileMSBLong(&info,&length);
2509  if ((count < 0) || ((size_t) count > length))
2510  {
2511  length=0;
2512  continue;
2513  }
2514  if ((id > 1999) && (id < 2999))
2515  UpdateClipPath(info,(size_t) count,old_columns,old_rows,new_geometry);
2516  info+=count;
2517  length-=MagickMin(count,(ssize_t) length);
2518  }
2519 }
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:2743
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:1976
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:1867
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:2137
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:2057
unsigned char * info
Definition: profile.c:112
size_t width
Definition: geometry.h:130
MagickPrivate void Update8BIMClipPath(const StringInfo *profile, const size_t old_columns, const size_t old_rows, const RectangleInfo *new_geometry)
Definition: profile.c:2471
#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:2035
MagickBooleanType black_point_compensation
Definition: image.h:258
static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
Definition: profile.c:1861
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:840
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: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:1948
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:2383
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)
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:134
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:130
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: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:187
MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
Definition: profile.c:2363
MagickExport MagickBooleanType SetImageProfile(Image *image, const char *name, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1906
static MagickBooleanType Sync8BimProfile(Image *image, StringInfo *profile)
Definition: profile.c:2075
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:2217
static signed int ReadProfileMSBLong(unsigned char **p, size_t *length)
Definition: profile.c:2008
#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:1122
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:1936
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:134
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:2021
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:1554
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)