MagickCore  7.0.9
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/attribute.h"
44 #include "MagickCore/cache.h"
45 #include "MagickCore/color.h"
47 #include "MagickCore/configure.h"
48 #include "MagickCore/exception.h"
50 #include "MagickCore/image.h"
51 #include "MagickCore/linked-list.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/monitor.h"
55 #include "MagickCore/option.h"
58 #include "MagickCore/profile.h"
60 #include "MagickCore/property.h"
61 #include "MagickCore/quantum.h"
63 #include "MagickCore/resource_.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/string_.h"
68 #include "MagickCore/token.h"
69 #include "MagickCore/utility.h"
70 #if defined(MAGICKCORE_LCMS_DELEGATE)
71 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
72 #include <wchar.h>
73 #include <lcms/lcms2.h>
74 #else
75 #include <wchar.h>
76 #include "lcms2.h"
77 #endif
78 #endif
79 #if defined(MAGICKCORE_XML_DELEGATE)
80 # if defined(MAGICKCORE_WINDOWS_SUPPORT)
81 # if !defined(__MINGW32__)
82 # include <win32config.h>
83 # endif
84 # endif
85 # include <libxml/parser.h>
86 # include <libxml/tree.h>
87 #endif
88 
89 /*
90  Definitions
91 */
92 #define LCMSHDRI
93 #if !defined(MAGICKCORE_HDRI_SUPPORT)
94  #if (MAGICKCORE_QUANTUM_DEPTH == 8)
95  #undef LCMSHDRI
96  #define LCMSScaleSource(pixel) ScaleQuantumToShort(pixel)
97  #define LCMSScaleTarget(pixel) ScaleShortToQuantum(pixel)
98  typedef unsigned short
99  LCMSType;
100  #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
101  #undef LCMSHDRI
102  #define LCMSScaleSource(pixel) (pixel)
103  #define LCMSScaleTarget(pixel) (pixel)
104  typedef unsigned short
105  LCMSType;
106  #endif
107 #endif
108 
109 #if defined(LCMSHDRI)
110 #define LCMSScaleSource(pixel) (source_scale*QuantumScale*(pixel))
111 #define LCMSScaleTarget(pixel) ClampToQuantum(target_scale*QuantumRange*(pixel))
112 typedef double
114 #endif
115 
116 /*
117  Forward declarations
118 */
119 static MagickBooleanType
120  SetImageProfileInternal(Image *,const char *,const StringInfo *,
122 
123 static void
124  WriteTo8BimProfile(Image *,const char*,const StringInfo *);
125 
126 /*
127  Typedef declarations
128 */
130 {
131  char
133 
134  size_t
136 
137  unsigned char
139 
140  size_t
142 };
143 
144 typedef struct _CMSExceptionInfo
145 {
146  Image
148 
152 
153 /*
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155 % %
156 % %
157 % %
158 % C l o n e I m a g e P r o f i l e s %
159 % %
160 % %
161 % %
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163 %
164 % CloneImageProfiles() clones one or more image profiles.
165 %
166 % The format of the CloneImageProfiles method is:
167 %
168 % MagickBooleanType CloneImageProfiles(Image *image,
169 % const Image *clone_image)
170 %
171 % A description of each parameter follows:
172 %
173 % o image: the image.
174 %
175 % o clone_image: the clone image.
176 %
177 */
179  const Image *clone_image)
180 {
181  assert(image != (Image *) NULL);
182  assert(image->signature == MagickCoreSignature);
183  if (image->debug != MagickFalse)
184  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
185  assert(clone_image != (const Image *) NULL);
186  assert(clone_image->signature == MagickCoreSignature);
187  if (clone_image->profiles != (void *) NULL)
188  {
189  if (image->profiles != (void *) NULL)
190  DestroyImageProfiles(image);
191  image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
192  (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
193  }
194  return(MagickTrue);
195 }
196 
197 /*
198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199 % %
200 % %
201 % %
202 % D e l e t e I m a g e P r o f i l e %
203 % %
204 % %
205 % %
206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 %
208 % DeleteImageProfile() deletes a profile from the image by its name.
209 %
210 % The format of the DeleteImageProfile method is:
211 %
212 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
213 %
214 % A description of each parameter follows:
215 %
216 % o image: the image.
217 %
218 % o name: the profile name.
219 %
220 */
222 {
223  assert(image != (Image *) NULL);
224  assert(image->signature == MagickCoreSignature);
225  if (image->debug != MagickFalse)
226  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
227  if (image->profiles == (SplayTreeInfo *) NULL)
228  return(MagickFalse);
229  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
230  return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
231 }
232 
233 /*
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 % %
236 % %
237 % %
238 % D e s t r o y I m a g e P r o f i l e s %
239 % %
240 % %
241 % %
242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243 %
244 % DestroyImageProfiles() releases memory associated with an image profile map.
245 %
246 % The format of the DestroyProfiles method is:
247 %
248 % void DestroyImageProfiles(Image *image)
249 %
250 % A description of each parameter follows:
251 %
252 % o image: the image.
253 %
254 */
256 {
257  if (image->profiles != (SplayTreeInfo *) NULL)
258  image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
259 }
260 
261 /*
262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263 % %
264 % %
265 % %
266 % G e t I m a g e P r o f i l e %
267 % %
268 % %
269 % %
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 %
272 % GetImageProfile() gets a profile associated with an image by name.
273 %
274 % The format of the GetImageProfile method is:
275 %
276 % const StringInfo *GetImageProfile(const Image *image,const char *name)
277 %
278 % A description of each parameter follows:
279 %
280 % o image: the image.
281 %
282 % o name: the profile name.
283 %
284 */
286  const char *name)
287 {
288  const StringInfo
289  *profile;
290 
291  assert(image != (Image *) NULL);
292  assert(image->signature == MagickCoreSignature);
293  if (image->debug != MagickFalse)
294  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
295  if (image->profiles == (SplayTreeInfo *) NULL)
296  return((StringInfo *) NULL);
297  profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
298  image->profiles,name);
299  return(profile);
300 }
301 
302 /*
303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304 % %
305 % %
306 % %
307 % G e t N e x t I m a g e P r o f i l e %
308 % %
309 % %
310 % %
311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312 %
313 % GetNextImageProfile() gets the next profile name for an image.
314 %
315 % The format of the GetNextImageProfile method is:
316 %
317 % char *GetNextImageProfile(const Image *image)
318 %
319 % A description of each parameter follows:
320 %
321 % o hash_info: the hash info.
322 %
323 */
325 {
326  assert(image != (Image *) NULL);
327  assert(image->signature == MagickCoreSignature);
328  if (image->debug != MagickFalse)
329  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
330  if (image->profiles == (SplayTreeInfo *) NULL)
331  return((char *) NULL);
332  return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
333 }
334 
335 /*
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 % %
338 % %
339 % %
340 % P r o f i l e I m a g e %
341 % %
342 % %
343 % %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 %
346 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
347 % profile with / to / from an image. If the profile is NULL, it is removed
348 % from the image otherwise added or applied. Use a name of '*' and a profile
349 % of NULL to remove all profiles from the image.
350 %
351 % ICC and ICM profiles are handled as follows: If the image does not have
352 % an associated color profile, the one you provide is associated with the
353 % image and the image pixels are not transformed. Otherwise, the colorspace
354 % transform defined by the existing and new profile are applied to the image
355 % pixels and the new profile is associated with the image.
356 %
357 % The format of the ProfileImage method is:
358 %
359 % MagickBooleanType ProfileImage(Image *image,const char *name,
360 % const void *datum,const size_t length,const MagickBooleanType clone)
361 %
362 % A description of each parameter follows:
363 %
364 % o image: the image.
365 %
366 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
367 %
368 % o datum: the profile data.
369 %
370 % o length: the length of the profile.
371 %
372 % o clone: should be MagickFalse.
373 %
374 */
375 
376 #if defined(MAGICKCORE_LCMS_DELEGATE)
377 
378 #if LCMS_VERSION < 2060
379 static void* cmsGetContextUserData(cmsContext ContextID)
380 {
381  return(ContextID);
382 }
383 
384 static cmsContext cmsCreateContext(void *magick_unused(Plugin),void *UserData)
385 {
386  magick_unreferenced(Plugin);
387  return((cmsContext) UserData);
388 }
389 
390 static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
391  cmsLogErrorHandlerFunction Fn)
392 {
393  magick_unreferenced(ContextID);
394  cmsSetLogErrorHandler(Fn);
395 }
396 
397 static void cmsDeleteContext(cmsContext magick_unused(ContextID))
398 {
399  magick_unreferenced(ContextID);
400 }
401 #endif
402 
403 static LCMSType **DestroyPixelThreadSet(LCMSType **pixels)
404 {
405  register ssize_t
406  i;
407 
408  if (pixels == (LCMSType **) NULL)
409  return((LCMSType **) NULL);
410  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
411  if (pixels[i] != (LCMSType *) NULL)
412  pixels[i]=(LCMSType *) RelinquishMagickMemory(pixels[i]);
413  pixels=(LCMSType **) RelinquishMagickMemory(pixels);
414  return(pixels);
415 }
416 
417 static LCMSType **AcquirePixelThreadSet(const size_t columns,
418  const size_t channels)
419 {
420  LCMSType
421  **pixels;
422 
423  register ssize_t
424  i;
425 
426  size_t
427  number_threads;
428 
429  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
430  pixels=(LCMSType **) AcquireQuantumMemory(number_threads,sizeof(*pixels));
431  if (pixels == (LCMSType **) NULL)
432  return((LCMSType **) NULL);
433  (void) memset(pixels,0,number_threads*sizeof(*pixels));
434  for (i=0; i < (ssize_t) number_threads; i++)
435  {
436  pixels[i]=(LCMSType *) AcquireQuantumMemory(columns,channels*
437  sizeof(**pixels));
438  if (pixels[i] == (LCMSType *) NULL)
439  return(DestroyPixelThreadSet(pixels));
440  }
441  return(pixels);
442 }
443 
444 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
445 {
446  register ssize_t
447  i;
448 
449  assert(transform != (cmsHTRANSFORM *) NULL);
450  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
451  if (transform[i] != (cmsHTRANSFORM) NULL)
452  cmsDeleteTransform(transform[i]);
453  transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
454  return(transform);
455 }
456 
457 static cmsHTRANSFORM *AcquireTransformThreadSet(
458  const cmsHPROFILE source_profile,const cmsUInt32Number source_type,
459  const cmsHPROFILE target_profile,const cmsUInt32Number target_type,
460  const int intent,const cmsUInt32Number flags,cmsContext cms_context)
461 {
462  cmsHTRANSFORM
463  *transform;
464 
465  register ssize_t
466  i;
467 
468  size_t
469  number_threads;
470 
471  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
472  transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
473  sizeof(*transform));
474  if (transform == (cmsHTRANSFORM *) NULL)
475  return((cmsHTRANSFORM *) NULL);
476  (void) memset(transform,0,number_threads*sizeof(*transform));
477  for (i=0; i < (ssize_t) number_threads; i++)
478  {
479  transform[i]=cmsCreateTransformTHR(cms_context,source_profile,source_type,
480  target_profile,target_type,intent,flags);
481  if (transform[i] == (cmsHTRANSFORM) NULL)
482  return(DestroyTransformThreadSet(transform));
483  }
484  return(transform);
485 }
486 
487 static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
488  const char *message)
489 {
491  *cms_exception;
492 
494  *exception;
495 
496  Image
497  *image;
498 
499  cms_exception=(CMSExceptionInfo *) cmsGetContextUserData(context);
500  if (cms_exception == (CMSExceptionInfo *) NULL)
501  return;
502  exception=cms_exception->exception;
503  if (exception == (ExceptionInfo *) NULL)
504  return;
505  image=cms_exception->image;
506  if (image == (Image *) NULL)
507  {
509  "UnableToTransformColorspace","`%s'","unknown context");
510  return;
511  }
512  if (image->debug != MagickFalse)
513  (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
514  severity,message != (char *) NULL ? message : "no message");
516  "UnableToTransformColorspace","`%s', %s (#%u)",image->filename,
517  message != (char *) NULL ? message : "no message",severity);
518 }
519 #endif
520 
522  ExceptionInfo *exception)
523 {
524  static unsigned char
525  sRGBProfile[] =
526  {
527  0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
528  0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
529  0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
530  0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
531  0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
532  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
533  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
534  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
538  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
539  0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
540  0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
541  0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
542  0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
543  0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
544  0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
545  0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
546  0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
547  0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
548  0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
549  0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
550  0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
551  0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
552  0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
553  0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
554  0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
555  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
556  0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
557  0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
558  0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
559  0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
560  0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
561  0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562  0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
563  0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
564  0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
565  0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
566  0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
567  0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568  0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
569  0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
570  0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
571  0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
572  0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
573  0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
574  0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
575  0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
576  0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
577  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
578  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
579  0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580  0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
581  0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
582  0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586  0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
587  0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
588  0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
589  0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
590  0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
591  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
592  0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
593  0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
594  0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
595  0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597  0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
598  0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
599  0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
600  0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601  0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
602  0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607  0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
608  0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
609  0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
610  0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
611  0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
612  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
613  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614  0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
615  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
616  0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
617  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618  0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
619  0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
620  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
621  0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
622  0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
623  0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
624  0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
625  0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
626  0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
627  0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
628  0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
629  0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
630  0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
631  0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
632  0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
633  0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
634  0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
635  0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
636  0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
637  0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
638  0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
639  0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
640  0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
641  0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
642  0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
643  0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
644  0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
645  0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
646  0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
647  0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
648  0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
649  0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
650  0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
651  0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
652  0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
653  0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
654  0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
655  0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
656  0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
657  0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
658  0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
659  0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
660  0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
661  0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
662  0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
663  0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
664  0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
665  0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
666  0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
667  0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
668  0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
669  0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
670  0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
671  0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
672  0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
673  0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
674  0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
675  0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
676  0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
677  0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
678  0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
679  0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
680  0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
681  0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
682  0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
683  0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
684  0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
685  0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
686  0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
687  0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
688  0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
689  0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
690  0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
691  0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
692  0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
693  0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
694  0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
695  0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
696  0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
697  0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
698  0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
699  0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
700  0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
701  0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
702  0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
703  0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
704  0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
705  0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
706  0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
707  0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
708  0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
709  0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
710  0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
711  0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
712  0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
713  0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
714  0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
715  0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
716  0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
717  0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
718  0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
719  0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
720  0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
721  0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
722  0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
723  0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
724  0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
725  0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
726  0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
727  0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
728  0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
729  0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
730  0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
731  0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
732  0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
733  0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
734  0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
735  0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
736  0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
737  0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
738  0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
739  0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
740  0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
741  0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
742  0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
743  0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
744  0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
745  0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
746  0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
747  0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
748  0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
749  0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
750  0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
751  0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
752  0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
753  0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
754  0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
755  0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
756  0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
757  0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
758  0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
759  0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
760  0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
761  0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
762  0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
763  0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
764  0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
765  0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
766  0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
767  0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
768  0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
769  0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
770  0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
771  0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
772  0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
773  0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
774  0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
775  0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
776  0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
777  0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
778  0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
779  0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
780  0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
781  0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
782  0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
783  0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
784  0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
785  0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
786  0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
787  0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
788  0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
789  0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
790  0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
791  0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
792  0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
793  0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
794  0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
795  };
796 
797  StringInfo
798  *profile;
799 
801  status;
802 
803  assert(image != (Image *) NULL);
804  assert(image->signature == MagickCoreSignature);
805  if (GetImageProfile(image,"icc") != (const StringInfo *) NULL)
806  return(MagickFalse);
807  profile=AcquireStringInfo(sizeof(sRGBProfile));
808  SetStringInfoDatum(profile,sRGBProfile);
809  status=SetImageProfile(image,"icc",profile,exception);
810  profile=DestroyStringInfo(profile);
811  return(status);
812 }
813 
815  const void *datum,const size_t length,ExceptionInfo *exception)
816 {
817 #define ProfileImageTag "Profile/Image"
818 #define ThrowProfileException(severity,tag,context) \
819 { \
820  if (cms_context != (cmsContext) NULL) \
821  cmsDeleteContext(cms_context); \
822  if (source_profile != (cmsHPROFILE) NULL) \
823  (void) cmsCloseProfile(source_profile); \
824  if (target_profile != (cmsHPROFILE) NULL) \
825  (void) cmsCloseProfile(target_profile); \
826  ThrowBinaryException(severity,tag,context); \
827 }
828 
830  status;
831 
832  StringInfo
833  *profile;
834 
835  assert(image != (Image *) NULL);
836  assert(image->signature == MagickCoreSignature);
837  if (image->debug != MagickFalse)
838  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
839  assert(name != (const char *) NULL);
840  if ((datum == (const void *) NULL) || (length == 0))
841  {
842  char
843  *next;
844 
845  /*
846  Delete image profile(s).
847  */
849  for (next=GetNextImageProfile(image); next != (const char *) NULL; )
850  {
851  if (IsOptionMember(next,name) != MagickFalse)
852  {
853  (void) DeleteImageProfile(image,next);
855  }
856  next=GetNextImageProfile(image);
857  }
858  return(MagickTrue);
859  }
860  /*
861  Add a ICC, IPTC, or generic profile to the image.
862  */
863  status=MagickTrue;
864  profile=AcquireStringInfo((size_t) length);
865  SetStringInfoDatum(profile,(unsigned char *) datum);
866  if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
867  status=SetImageProfile(image,name,profile,exception);
868  else
869  {
870  const StringInfo
871  *icc_profile;
872 
873  icc_profile=GetImageProfile(image,"icc");
874  if ((icc_profile != (const StringInfo *) NULL) &&
875  (CompareStringInfo(icc_profile,profile) == 0))
876  {
877  const char
878  *value;
879 
880  value=GetImageProperty(image,"exif:ColorSpace",exception);
881  (void) value;
882  if (LocaleCompare(value,"1") != 0)
883  (void) SetsRGBImageProfile(image,exception);
884  value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
885  if (LocaleCompare(value,"R98.") != 0)
886  (void) SetsRGBImageProfile(image,exception);
887  /* Future.
888  value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
889  if (LocaleCompare(value,"R03.") != 0)
890  (void) SetAdobeRGB1998ImageProfile(image,exception);
891  */
892  icc_profile=GetImageProfile(image,"icc");
893  }
894  if ((icc_profile != (const StringInfo *) NULL) &&
895  (CompareStringInfo(icc_profile,profile) == 0))
896  {
897  profile=DestroyStringInfo(profile);
898  return(MagickTrue);
899  }
900 #if !defined(MAGICKCORE_LCMS_DELEGATE)
901  (void) ThrowMagickException(exception,GetMagickModule(),
902  MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
903  "'%s' (LCMS)",image->filename);
904 #else
905  {
906  cmsHPROFILE
907  source_profile;
908 
909  cmsContext
910  cms_context;
911 
913  cms_exception;
914 
915  /*
916  Transform pixel colors as defined by the color profiles.
917  */
918  cms_exception.image=image;
919  cms_exception.exception=exception;
920  cms_context=cmsCreateContext(NULL,&cms_exception);
921  if (cms_context == (cmsContext) NULL)
923  "ColorspaceColorProfileMismatch",name);
924  cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
925  source_profile=cmsOpenProfileFromMemTHR(cms_context,
926  GetStringInfoDatum(profile),(cmsUInt32Number)
927  GetStringInfoLength(profile));
928  if (source_profile == (cmsHPROFILE) NULL)
929  {
930  cmsDeleteContext(cms_context);
932  "ColorspaceColorProfileMismatch",name);
933  }
934  if ((cmsGetDeviceClass(source_profile) != cmsSigLinkClass) &&
935  (icc_profile == (StringInfo *) NULL))
936  status=SetImageProfile(image,name,profile,exception);
937  else
938  {
939  CacheView
940  *image_view;
941 
943  source_colorspace,
944  target_colorspace;
945 
946  cmsColorSpaceSignature
947  signature;
948 
949  cmsHPROFILE
950  target_profile;
951 
952  cmsHTRANSFORM
953  *magick_restrict transform;
954 
955  cmsUInt32Number
956  flags,
957  source_type,
958  target_type;
959 
960  int
961  intent;
962 
963  LCMSType
964  **magick_restrict source_pixels,
965  **magick_restrict target_pixels;
966 
967 #if defined(LCMSHDRI)
968  LCMSType
969  source_scale,
970  target_scale;
971 #endif
972 
974  progress;
975 
976  size_t
977  source_channels,
978  target_channels;
979 
980  ssize_t
981  y;
982 
983  target_profile=(cmsHPROFILE) NULL;
984  if (icc_profile != (StringInfo *) NULL)
985  {
986  target_profile=source_profile;
987  source_profile=cmsOpenProfileFromMemTHR(cms_context,
988  GetStringInfoDatum(icc_profile),
989  (cmsUInt32Number) GetStringInfoLength(icc_profile));
990  if (source_profile == (cmsHPROFILE) NULL)
992  "ColorspaceColorProfileMismatch",name);
993  }
994 #if defined(LCMSHDRI)
995  source_scale=1.0;
996 #endif
997  source_colorspace=sRGBColorspace;
998  source_channels=3;
999  switch (cmsGetColorSpace(source_profile))
1000  {
1001  case cmsSigCmykData:
1002  {
1003  source_colorspace=CMYKColorspace;
1004  source_channels=4;
1005 #if defined(LCMSHDRI)
1006  source_type=(cmsUInt32Number) TYPE_CMYK_DBL;
1007  source_scale=100.0;
1008 #else
1009  source_type=(cmsUInt32Number) TYPE_CMYK_16;
1010 #endif
1011  break;
1012  }
1013  case cmsSigGrayData:
1014  {
1015  source_colorspace=GRAYColorspace;
1016  source_channels=1;
1017 #if defined(LCMSHDRI)
1018  source_type=(cmsUInt32Number) TYPE_GRAY_DBL;
1019 #else
1020  source_type=(cmsUInt32Number) TYPE_GRAY_16;
1021 #endif
1022  break;
1023  }
1024  case cmsSigLabData:
1025  {
1026  source_colorspace=LabColorspace;
1027 #if defined(LCMSHDRI)
1028  source_type=(cmsUInt32Number) TYPE_Lab_DBL;
1029  source_scale=100.0;
1030 #else
1031  source_type=(cmsUInt32Number) TYPE_Lab_16;
1032 #endif
1033  break;
1034  }
1035 #if !defined(LCMSHDRI)
1036  case cmsSigLuvData:
1037  {
1038  source_colorspace=YUVColorspace;
1039  source_type=(cmsUInt32Number) TYPE_YUV_16;
1040  break;
1041  }
1042 #endif
1043  case cmsSigRgbData:
1044  {
1045  source_colorspace=sRGBColorspace;
1046 #if defined(LCMSHDRI)
1047  source_type=(cmsUInt32Number) TYPE_RGB_DBL;
1048 #else
1049  source_type=(cmsUInt32Number) TYPE_RGB_16;
1050 #endif
1051  break;
1052  }
1053  case cmsSigXYZData:
1054  {
1055  source_colorspace=XYZColorspace;
1056 #if defined(LCMSHDRI)
1057  source_type=(cmsUInt32Number) TYPE_XYZ_DBL;
1058 #else
1059  source_type=(cmsUInt32Number) TYPE_XYZ_16;
1060 #endif
1061  break;
1062  }
1063 #if !defined(LCMSHDRI)
1064  case cmsSigYCbCrData:
1065  {
1066  source_colorspace=YUVColorspace;
1067  source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1068  break;
1069  }
1070 #endif
1071  default:
1073  "ColorspaceColorProfileMismatch",name);
1074  }
1075  (void) source_colorspace;
1076  signature=cmsGetPCS(source_profile);
1077  if (target_profile != (cmsHPROFILE) NULL)
1078  signature=cmsGetColorSpace(target_profile);
1079 #if defined(LCMSHDRI)
1080  target_scale=1.0;
1081 #endif
1082  target_channels=3;
1083  switch (signature)
1084  {
1085  case cmsSigCmykData:
1086  {
1087  target_colorspace=CMYKColorspace;
1088  target_channels=4;
1089 #if defined(LCMSHDRI)
1090  target_type=(cmsUInt32Number) TYPE_CMYK_DBL;
1091  target_scale=0.01;
1092 #else
1093  target_type=(cmsUInt32Number) TYPE_CMYK_16;
1094 #endif
1095  break;
1096  }
1097  case cmsSigGrayData:
1098  {
1099  target_colorspace=GRAYColorspace;
1100  target_channels=1;
1101 #if defined(LCMSHDRI)
1102  target_type=(cmsUInt32Number) TYPE_GRAY_DBL;
1103 #else
1104  target_type=(cmsUInt32Number) TYPE_GRAY_16;
1105 #endif
1106  break;
1107  }
1108  case cmsSigLabData:
1109  {
1110  target_colorspace=LabColorspace;
1111 #if defined(LCMSHDRI)
1112  target_type=(cmsUInt32Number) TYPE_Lab_DBL;
1113  target_scale=0.01;
1114 #else
1115  target_type=(cmsUInt32Number) TYPE_Lab_16;
1116 #endif
1117  break;
1118  }
1119 #if !defined(LCMSHDRI)
1120  case cmsSigLuvData:
1121  {
1122  target_colorspace=YUVColorspace;
1123  target_type=(cmsUInt32Number) TYPE_YUV_16;
1124  break;
1125  }
1126 #endif
1127  case cmsSigRgbData:
1128  {
1129  target_colorspace=sRGBColorspace;
1130 #if defined(LCMSHDRI)
1131  target_type=(cmsUInt32Number) TYPE_RGB_DBL;
1132 #else
1133  target_type=(cmsUInt32Number) TYPE_RGB_16;
1134 #endif
1135  break;
1136  }
1137  case cmsSigXYZData:
1138  {
1139  target_colorspace=XYZColorspace;
1140 #if defined(LCMSHDRI)
1141  target_type=(cmsUInt32Number) TYPE_XYZ_DBL;
1142 #else
1143  target_type=(cmsUInt32Number) TYPE_XYZ_16;
1144 #endif
1145  break;
1146  }
1147 #if !defined(LCMSHDRI)
1148  case cmsSigYCbCrData:
1149  {
1150  target_colorspace=YUVColorspace;
1151  target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1152  break;
1153  }
1154 #endif
1155  default:
1157  "ColorspaceColorProfileMismatch",name);
1158  }
1159  switch (image->rendering_intent)
1160  {
1161  case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1162  case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1163  case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1164  case SaturationIntent: intent=INTENT_SATURATION; break;
1165  default: intent=INTENT_PERCEPTUAL; break;
1166  }
1167  flags=cmsFLAGS_HIGHRESPRECALC;
1168 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1169  if (image->black_point_compensation != MagickFalse)
1170  flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1171 #endif
1172  transform=AcquireTransformThreadSet(source_profile,source_type,
1173  target_profile,target_type,intent,flags,cms_context);
1174  if (transform == (cmsHTRANSFORM *) NULL)
1175  ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1176  name);
1177  /*
1178  Transform image as dictated by the source & target image profiles.
1179  */
1180  source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1181  target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1182  if ((source_pixels == (LCMSType **) NULL) ||
1183  (target_pixels == (LCMSType **) NULL))
1184  {
1185  target_pixels=DestroyPixelThreadSet(target_pixels);
1186  source_pixels=DestroyPixelThreadSet(source_pixels);
1187  transform=DestroyTransformThreadSet(transform);
1189  "MemoryAllocationFailed",image->filename);
1190  }
1191  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1192  {
1193  target_pixels=DestroyPixelThreadSet(target_pixels);
1194  source_pixels=DestroyPixelThreadSet(source_pixels);
1195  transform=DestroyTransformThreadSet(transform);
1196  if (source_profile != (cmsHPROFILE) NULL)
1197  (void) cmsCloseProfile(source_profile);
1198  if (target_profile != (cmsHPROFILE) NULL)
1199  (void) cmsCloseProfile(target_profile);
1200  return(MagickFalse);
1201  }
1202  if (target_colorspace == CMYKColorspace)
1203  (void) SetImageColorspace(image,target_colorspace,exception);
1204  progress=0;
1205  image_view=AcquireAuthenticCacheView(image,exception);
1206 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1207  #pragma omp parallel for schedule(static) shared(status) \
1208  magick_number_threads(image,image,image->rows,1)
1209 #endif
1210  for (y=0; y < (ssize_t) image->rows; y++)
1211  {
1212  const int
1213  id = GetOpenMPThreadId();
1214 
1216  sync;
1217 
1218  register LCMSType
1219  *p;
1220 
1221  register Quantum
1222  *magick_restrict q;
1223 
1224  register ssize_t
1225  x;
1226 
1227  if (status == MagickFalse)
1228  continue;
1229  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1230  exception);
1231  if (q == (Quantum *) NULL)
1232  {
1233  status=MagickFalse;
1234  continue;
1235  }
1236  p=source_pixels[id];
1237  for (x=0; x < (ssize_t) image->columns; x++)
1238  {
1239  *p++=LCMSScaleSource(GetPixelRed(image,q));
1240  if (source_channels > 1)
1241  {
1242  *p++=LCMSScaleSource(GetPixelGreen(image,q));
1243  *p++=LCMSScaleSource(GetPixelBlue(image,q));
1244  }
1245  if (source_channels > 3)
1246  *p++=LCMSScaleSource(GetPixelBlack(image,q));
1247  q+=GetPixelChannels(image);
1248  }
1249  cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1250  (unsigned int) image->columns);
1251  p=target_pixels[id];
1252  q-=GetPixelChannels(image)*image->columns;
1253  for (x=0; x < (ssize_t) image->columns; x++)
1254  {
1255  if (target_channels == 1)
1256  SetPixelGray(image,LCMSScaleTarget(*p),q);
1257  else
1258  SetPixelRed(image,LCMSScaleTarget(*p),q);
1259  p++;
1260  if (target_channels > 1)
1261  {
1262  SetPixelGreen(image,LCMSScaleTarget(*p),q);
1263  p++;
1264  SetPixelBlue(image,LCMSScaleTarget(*p),q);
1265  p++;
1266  }
1267  if (target_channels > 3)
1268  {
1269  SetPixelBlack(image,LCMSScaleTarget(*p),q);
1270  p++;
1271  }
1272  q+=GetPixelChannels(image);
1273  }
1274  sync=SyncCacheViewAuthenticPixels(image_view,exception);
1275  if (sync == MagickFalse)
1276  status=MagickFalse;
1277  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1278  {
1280  proceed;
1281 
1282 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1283  #pragma omp atomic
1284 #endif
1285  progress++;
1286  proceed=SetImageProgress(image,ProfileImageTag,progress,
1287  image->rows);
1288  if (proceed == MagickFalse)
1289  status=MagickFalse;
1290  }
1291  }
1292  image_view=DestroyCacheView(image_view);
1293  (void) SetImageColorspace(image,target_colorspace,exception);
1294  switch (signature)
1295  {
1296  case cmsSigRgbData:
1297  {
1298  image->type=image->alpha_trait == UndefinedPixelTrait ?
1300  break;
1301  }
1302  case cmsSigCmykData:
1303  {
1304  image->type=image->alpha_trait == UndefinedPixelTrait ?
1306  break;
1307  }
1308  case cmsSigGrayData:
1309  {
1310  image->type=image->alpha_trait == UndefinedPixelTrait ?
1312  break;
1313  }
1314  default:
1315  break;
1316  }
1317  target_pixels=DestroyPixelThreadSet(target_pixels);
1318  source_pixels=DestroyPixelThreadSet(source_pixels);
1319  transform=DestroyTransformThreadSet(transform);
1320  if ((status != MagickFalse) &&
1321  (cmsGetDeviceClass(source_profile) != cmsSigLinkClass))
1322  status=SetImageProfile(image,name,profile,exception);
1323  if (target_profile != (cmsHPROFILE) NULL)
1324  (void) cmsCloseProfile(target_profile);
1325  }
1326  (void) cmsCloseProfile(source_profile);
1327  cmsDeleteContext(cms_context);
1328  }
1329 #endif
1330  }
1331  profile=DestroyStringInfo(profile);
1332  return(status);
1333 }
1334 
1335 /*
1336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 % %
1338 % %
1339 % %
1340 % R e m o v e I m a g e P r o f i l e %
1341 % %
1342 % %
1343 % %
1344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1345 %
1346 % RemoveImageProfile() removes a named profile from the image and returns its
1347 % value.
1348 %
1349 % The format of the RemoveImageProfile method is:
1350 %
1351 % void *RemoveImageProfile(Image *image,const char *name)
1352 %
1353 % A description of each parameter follows:
1354 %
1355 % o image: the image.
1356 %
1357 % o name: the profile name.
1358 %
1359 */
1361 {
1362  StringInfo
1363  *profile;
1364 
1365  assert(image != (Image *) NULL);
1366  assert(image->signature == MagickCoreSignature);
1367  if (image->debug != MagickFalse)
1368  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1369  if (image->profiles == (SplayTreeInfo *) NULL)
1370  return((StringInfo *) NULL);
1371  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1373  image->profiles,name);
1374  return(profile);
1375 }
1376 
1377 /*
1378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379 % %
1380 % %
1381 % %
1382 % R e s e t P r o f i l e I t e r a t o r %
1383 % %
1384 % %
1385 % %
1386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387 %
1388 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1389 % conjunction with GetNextImageProfile() to iterate over all the profiles
1390 % associated with an image.
1391 %
1392 % The format of the ResetImageProfileIterator method is:
1393 %
1394 % ResetImageProfileIterator(Image *image)
1395 %
1396 % A description of each parameter follows:
1397 %
1398 % o image: the image.
1399 %
1400 */
1402 {
1403  assert(image != (Image *) NULL);
1404  assert(image->signature == MagickCoreSignature);
1405  if (image->debug != MagickFalse)
1406  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1407  if (image->profiles == (SplayTreeInfo *) NULL)
1408  return;
1410 }
1411 
1412 /*
1413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414 % %
1415 % %
1416 % %
1417 % S e t I m a g e P r o f i l e %
1418 % %
1419 % %
1420 % %
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 %
1423 % SetImageProfile() adds a named profile to the image. If a profile with the
1424 % same name already exists, it is replaced. This method differs from the
1425 % ProfileImage() method in that it does not apply CMS color profiles.
1426 %
1427 % The format of the SetImageProfile method is:
1428 %
1429 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1430 % const StringInfo *profile)
1431 %
1432 % A description of each parameter follows:
1433 %
1434 % o image: the image.
1435 %
1436 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1437 % Photoshop wrapper for iptc profiles).
1438 %
1439 % o profile: A StringInfo structure that contains the named profile.
1440 %
1441 */
1442 
1443 static void *DestroyProfile(void *profile)
1444 {
1445  return((void *) DestroyStringInfo((StringInfo *) profile));
1446 }
1447 
1448 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1449  unsigned char *quantum)
1450 {
1451  *quantum=(*p++);
1452  return(p);
1453 }
1454 
1455 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1456  unsigned int *quantum)
1457 {
1458  *quantum=(unsigned int) (*p++) << 24;
1459  *quantum|=(unsigned int) (*p++) << 16;
1460  *quantum|=(unsigned int) (*p++) << 8;
1461  *quantum|=(unsigned int) (*p++);
1462  return(p);
1463 }
1464 
1465 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1466  unsigned short *quantum)
1467 {
1468  *quantum=(unsigned short) (*p++) << 8;
1469  *quantum|=(unsigned short) (*p++);
1470  return(p);
1471 }
1472 
1473 static inline void WriteResourceLong(unsigned char *p,
1474  const unsigned int quantum)
1475 {
1476  unsigned char
1477  buffer[4];
1478 
1479  buffer[0]=(unsigned char) (quantum >> 24);
1480  buffer[1]=(unsigned char) (quantum >> 16);
1481  buffer[2]=(unsigned char) (quantum >> 8);
1482  buffer[3]=(unsigned char) quantum;
1483  (void) memcpy(p,buffer,4);
1484 }
1485 
1486 static void WriteTo8BimProfile(Image *image,const char *name,
1487  const StringInfo *profile)
1488 {
1489  const unsigned char
1490  *datum,
1491  *q;
1492 
1493  register const unsigned char
1494  *p;
1495 
1496  size_t
1497  length;
1498 
1499  StringInfo
1500  *profile_8bim;
1501 
1502  ssize_t
1503  count;
1504 
1505  unsigned char
1506  length_byte;
1507 
1508  unsigned int
1509  value;
1510 
1511  unsigned short
1512  id,
1513  profile_id;
1514 
1515  if (LocaleCompare(name,"icc") == 0)
1516  profile_id=0x040f;
1517  else
1518  if (LocaleCompare(name,"iptc") == 0)
1519  profile_id=0x0404;
1520  else
1521  if (LocaleCompare(name,"xmp") == 0)
1522  profile_id=0x0424;
1523  else
1524  return;
1525  profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1526  image->profiles,"8bim");
1527  if (profile_8bim == (StringInfo *) NULL)
1528  return;
1529  datum=GetStringInfoDatum(profile_8bim);
1530  length=GetStringInfoLength(profile_8bim);
1531  for (p=datum; p < (datum+length-16); )
1532  {
1533  q=p;
1534  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1535  break;
1536  p+=4;
1537  p=ReadResourceShort(p,&id);
1538  p=ReadResourceByte(p,&length_byte);
1539  p+=length_byte;
1540  if (((length_byte+1) & 0x01) != 0)
1541  p++;
1542  if (p > (datum+length-4))
1543  break;
1544  p=ReadResourceLong(p,&value);
1545  count=(ssize_t) value;
1546  if ((count & 0x01) != 0)
1547  count++;
1548  if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1549  break;
1550  if (id != profile_id)
1551  p+=count;
1552  else
1553  {
1554  size_t
1555  extent,
1556  offset;
1557 
1558  ssize_t
1559  extract_extent;
1560 
1561  StringInfo
1562  *extract_profile;
1563 
1564  extract_extent=0;
1565  extent=(datum+length)-(p+count);
1566  if (profile == (StringInfo *) NULL)
1567  {
1568  offset=(q-datum);
1569  extract_profile=AcquireStringInfo(offset+extent);
1570  (void) memcpy(extract_profile->datum,datum,offset);
1571  }
1572  else
1573  {
1574  offset=(p-datum);
1575  extract_extent=profile->length;
1576  if ((extract_extent & 0x01) != 0)
1577  extract_extent++;
1578  extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1579  (void) memcpy(extract_profile->datum,datum,offset-4);
1580  WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
1581  profile->length);
1582  (void) memcpy(extract_profile->datum+offset,
1583  profile->datum,profile->length);
1584  }
1585  (void) memcpy(extract_profile->datum+offset+extract_extent,
1586  p+count,extent);
1587  (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1588  ConstantString("8bim"),CloneStringInfo(extract_profile));
1589  extract_profile=DestroyStringInfo(extract_profile);
1590  break;
1591  }
1592  }
1593 }
1594 
1596  const StringInfo *resource_block,ExceptionInfo *exception)
1597 {
1598  const unsigned char
1599  *datum;
1600 
1601  register const unsigned char
1602  *p;
1603 
1604  size_t
1605  length;
1606 
1607  ssize_t
1608  count;
1609 
1610  StringInfo
1611  *profile;
1612 
1613  unsigned char
1614  length_byte;
1615 
1616  unsigned int
1617  value;
1618 
1619  unsigned short
1620  id;
1621 
1622  datum=GetStringInfoDatum(resource_block);
1623  length=GetStringInfoLength(resource_block);
1624  for (p=datum; p < (datum+length-16); )
1625  {
1626  if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1627  break;
1628  p+=4;
1629  p=ReadResourceShort(p,&id);
1630  p=ReadResourceByte(p,&length_byte);
1631  p+=length_byte;
1632  if (((length_byte+1) & 0x01) != 0)
1633  p++;
1634  if (p > (datum+length-4))
1635  break;
1636  p=ReadResourceLong(p,&value);
1637  count=(ssize_t) value;
1638  if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1639  break;
1640  switch (id)
1641  {
1642  case 0x03ed:
1643  {
1644  unsigned int
1645  resolution;
1646 
1647  unsigned short
1648  units;
1649 
1650  /*
1651  Resolution.
1652  */
1653  if (count < 10)
1654  break;
1655  p=ReadResourceLong(p,&resolution);
1656  image->resolution.x=((double) resolution)/65536.0;
1657  p=ReadResourceShort(p,&units)+2;
1658  p=ReadResourceLong(p,&resolution)+4;
1659  image->resolution.y=((double) resolution)/65536.0;
1660  /*
1661  Values are always stored as pixels per inch.
1662  */
1665  else
1666  {
1668  image->resolution.x/=2.54;
1669  image->resolution.y/=2.54;
1670  }
1671  break;
1672  }
1673  case 0x0404:
1674  {
1675  /*
1676  IPTC Profile
1677  */
1678  profile=AcquireStringInfo(count);
1679  SetStringInfoDatum(profile,p);
1680  (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1681  exception);
1682  profile=DestroyStringInfo(profile);
1683  p+=count;
1684  break;
1685  }
1686  case 0x040c:
1687  {
1688  /*
1689  Thumbnail.
1690  */
1691  p+=count;
1692  break;
1693  }
1694  case 0x040f:
1695  {
1696  /*
1697  ICC Profile.
1698  */
1699  profile=AcquireStringInfo(count);
1700  SetStringInfoDatum(profile,p);
1701  (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1702  exception);
1703  profile=DestroyStringInfo(profile);
1704  p+=count;
1705  break;
1706  }
1707  case 0x0422:
1708  {
1709  /*
1710  EXIF Profile.
1711  */
1712  profile=AcquireStringInfo(count);
1713  SetStringInfoDatum(profile,p);
1714  (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1715  exception);
1716  profile=DestroyStringInfo(profile);
1717  p+=count;
1718  break;
1719  }
1720  case 0x0424:
1721  {
1722  /*
1723  XMP Profile.
1724  */
1725  profile=AcquireStringInfo(count);
1726  SetStringInfoDatum(profile,p);
1727  (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1728  exception);
1729  profile=DestroyStringInfo(profile);
1730  p+=count;
1731  break;
1732  }
1733  default:
1734  {
1735  p+=count;
1736  break;
1737  }
1738  }
1739  if ((count & 0x01) != 0)
1740  p++;
1741  }
1742 }
1743 
1744 #if defined(MAGICKCORE_XML_DELEGATE)
1745 static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
1746 {
1747  xmlDocPtr
1748  document;
1749 
1750  /*
1751  Parse XML profile.
1752  */
1753  document=xmlReadMemory((const char *) GetStringInfoDatum(profile),(int)
1754  GetStringInfoLength(profile),"xmp.xml",NULL,XML_PARSE_NOERROR |
1755  XML_PARSE_NOWARNING);
1756  if (document == (xmlDocPtr) NULL)
1757  return(MagickFalse);
1758  xmlFreeDoc(document);
1759  return(MagickTrue);
1760 }
1761 #else
1763 {
1764  char
1765  *p;
1766 
1767  p=StringLocateSubstring((const char *) GetStringInfoDatum(profile),"x:xmpmeta");
1768  if (p != (char *) NULL)
1769  p=StringLocateSubstring((const char *) GetStringInfoDatum(profile),"rdf:RDF");
1770  return(p == (char *) NULL ? MagickFalse : MagickTrue);
1771 }
1772 #endif
1773 
1774 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1775  const StringInfo *profile,const MagickBooleanType recursive,
1776  ExceptionInfo *exception)
1777 {
1778  char
1779  key[MagickPathExtent],
1780  property[MagickPathExtent];
1781 
1783  status;
1784 
1785  assert(image != (Image *) NULL);
1786  assert(image->signature == MagickCoreSignature);
1787  if (image->debug != MagickFalse)
1788  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1789  if ((LocaleCompare(name,"xmp") == 0) &&
1790  (ValidateXMPProfile(profile) == MagickFalse))
1791  {
1793  "CorruptImageProfile","`%s'",name);
1794  return(MagickTrue);
1795  }
1796  if (image->profiles == (SplayTreeInfo *) NULL)
1798  DestroyProfile);
1799  (void) CopyMagickString(key,name,MagickPathExtent);
1800  LocaleLower(key);
1801  status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1802  ConstantString(key),CloneStringInfo(profile));
1803  if (status != MagickFalse)
1804  {
1805  if (LocaleCompare(name,"8bim") == 0)
1806  GetProfilesFromResourceBlock(image,profile,exception);
1807  else
1808  if (recursive == MagickFalse)
1809  WriteTo8BimProfile(image,name,profile);
1810  }
1811  /*
1812  Inject profile into image properties.
1813  */
1814  (void) FormatLocaleString(property,MagickPathExtent,"%s:*",name);
1815  (void) GetImageProperty(image,property,exception);
1816  return(status);
1817 }
1818 
1820  const StringInfo *profile,ExceptionInfo *exception)
1821 {
1822  return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1823 }
1824 
1825 /*
1826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1827 % %
1828 % %
1829 % %
1830 % S y n c I m a g e P r o f i l e s %
1831 % %
1832 % %
1833 % %
1834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1835 %
1836 % SyncImageProfiles() synchronizes image properties with the image profiles.
1837 % Currently we only support updating the EXIF resolution and orientation.
1838 %
1839 % The format of the SyncImageProfiles method is:
1840 %
1841 % MagickBooleanType SyncImageProfiles(Image *image)
1842 %
1843 % A description of each parameter follows:
1844 %
1845 % o image: the image.
1846 %
1847 */
1848 
1849 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1850 {
1851  int
1852  c;
1853 
1854  if (*length < 1)
1855  return(EOF);
1856  c=(int) (*(*p)++);
1857  (*length)--;
1858  return(c);
1859 }
1860 
1861 static inline signed short ReadProfileShort(const EndianType endian,
1862  unsigned char *buffer)
1863 {
1864  union
1865  {
1866  unsigned int
1867  unsigned_value;
1868 
1869  signed int
1870  signed_value;
1871  } quantum;
1872 
1873  unsigned short
1874  value;
1875 
1876  if (endian == LSBEndian)
1877  {
1878  value=(unsigned short) buffer[1] << 8;
1879  value|=(unsigned short) buffer[0];
1880  quantum.unsigned_value=value & 0xffff;
1881  return(quantum.signed_value);
1882  }
1883  value=(unsigned short) buffer[0] << 8;
1884  value|=(unsigned short) buffer[1];
1885  quantum.unsigned_value=value & 0xffff;
1886  return(quantum.signed_value);
1887 }
1888 
1889 static inline signed int ReadProfileLong(const EndianType endian,
1890  unsigned char *buffer)
1891 {
1892  union
1893  {
1894  unsigned int
1895  unsigned_value;
1896 
1897  signed int
1898  signed_value;
1899  } quantum;
1900 
1901  unsigned int
1902  value;
1903 
1904  if (endian == LSBEndian)
1905  {
1906  value=(unsigned int) buffer[3] << 24;
1907  value|=(unsigned int) buffer[2] << 16;
1908  value|=(unsigned int) buffer[1] << 8;
1909  value|=(unsigned int) buffer[0];
1910  quantum.unsigned_value=value & 0xffffffff;
1911  return(quantum.signed_value);
1912  }
1913  value=(unsigned int) buffer[0] << 24;
1914  value|=(unsigned int) buffer[1] << 16;
1915  value|=(unsigned int) buffer[2] << 8;
1916  value|=(unsigned int) buffer[3];
1917  quantum.unsigned_value=value & 0xffffffff;
1918  return(quantum.signed_value);
1919 }
1920 
1921 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
1922 {
1923  signed int
1924  value;
1925 
1926  if (*length < 4)
1927  return(0);
1928  value=ReadProfileLong(MSBEndian,*p);
1929  (*length)-=4;
1930  *p+=4;
1931  return(value);
1932 }
1933 
1934 static inline signed short ReadProfileMSBShort(unsigned char **p,
1935  size_t *length)
1936 {
1937  signed short
1938  value;
1939 
1940  if (*length < 2)
1941  return(0);
1942  value=ReadProfileShort(MSBEndian,*p);
1943  (*length)-=2;
1944  *p+=2;
1945  return(value);
1946 }
1947 
1948 static inline void WriteProfileLong(const EndianType endian,
1949  const size_t value,unsigned char *p)
1950 {
1951  unsigned char
1952  buffer[4];
1953 
1954  if (endian == LSBEndian)
1955  {
1956  buffer[0]=(unsigned char) value;
1957  buffer[1]=(unsigned char) (value >> 8);
1958  buffer[2]=(unsigned char) (value >> 16);
1959  buffer[3]=(unsigned char) (value >> 24);
1960  (void) memcpy(p,buffer,4);
1961  return;
1962  }
1963  buffer[0]=(unsigned char) (value >> 24);
1964  buffer[1]=(unsigned char) (value >> 16);
1965  buffer[2]=(unsigned char) (value >> 8);
1966  buffer[3]=(unsigned char) value;
1967  (void) memcpy(p,buffer,4);
1968 }
1969 
1970 static void WriteProfileShort(const EndianType endian,
1971  const unsigned short value,unsigned char *p)
1972 {
1973  unsigned char
1974  buffer[2];
1975 
1976  if (endian == LSBEndian)
1977  {
1978  buffer[0]=(unsigned char) value;
1979  buffer[1]=(unsigned char) (value >> 8);
1980  (void) memcpy(p,buffer,2);
1981  return;
1982  }
1983  buffer[0]=(unsigned char) (value >> 8);
1984  buffer[1]=(unsigned char) value;
1985  (void) memcpy(p,buffer,2);
1986 }
1987 
1989 {
1990  size_t
1991  length;
1992 
1993  ssize_t
1994  count;
1995 
1996  unsigned char
1997  *p;
1998 
1999  unsigned short
2000  id;
2001 
2002  length=GetStringInfoLength(profile);
2003  p=GetStringInfoDatum(profile);
2004  while (length != 0)
2005  {
2006  if (ReadProfileByte(&p,&length) != 0x38)
2007  continue;
2008  if (ReadProfileByte(&p,&length) != 0x42)
2009  continue;
2010  if (ReadProfileByte(&p,&length) != 0x49)
2011  continue;
2012  if (ReadProfileByte(&p,&length) != 0x4D)
2013  continue;
2014  if (length < 7)
2015  return(MagickFalse);
2016  id=ReadProfileMSBShort(&p,&length);
2017  count=(ssize_t) ReadProfileByte(&p,&length);
2018  if ((count >= (ssize_t) length) || (count < 0))
2019  return(MagickFalse);
2020  p+=count;
2021  length-=count;
2022  if ((*p & 0x01) == 0)
2023  (void) ReadProfileByte(&p,&length);
2024  count=(ssize_t) ReadProfileMSBLong(&p,&length);
2025  if ((count > (ssize_t) length) || (count < 0))
2026  return(MagickFalse);
2027  if ((id == 0x3ED) && (count == 16))
2028  {
2029  if (image->units == PixelsPerCentimeterResolution)
2030  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
2031  65536.0),p);
2032  else
2033  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
2034  65536.0),p);
2035  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2036  if (image->units == PixelsPerCentimeterResolution)
2037  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
2038  65536.0),p+8);
2039  else
2040  WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
2041  65536.0),p+8);
2042  WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2043  }
2044  p+=count;
2045  length-=count;
2046  }
2047  return(MagickTrue);
2048 }
2049 
2051 {
2052 #define MaxDirectoryStack 16
2053 #define EXIF_DELIMITER "\n"
2054 #define EXIF_NUM_FORMATS 12
2055 #define TAG_EXIF_OFFSET 0x8769
2056 #define TAG_INTEROP_OFFSET 0xa005
2057 
2058  typedef struct _DirectoryInfo
2059  {
2060  unsigned char
2061  *directory;
2062 
2063  size_t
2064  entry;
2065  } DirectoryInfo;
2066 
2067  DirectoryInfo
2068  directory_stack[MaxDirectoryStack];
2069 
2070  EndianType
2071  endian;
2072 
2073  size_t
2074  entry,
2075  length,
2076  number_entries;
2077 
2079  *exif_resources;
2080 
2081  ssize_t
2082  id,
2083  level,
2084  offset;
2085 
2086  static int
2087  format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2088 
2089  unsigned char
2090  *directory,
2091  *exif;
2092 
2093  /*
2094  Set EXIF resolution tag.
2095  */
2096  length=GetStringInfoLength(profile);
2097  exif=GetStringInfoDatum(profile);
2098  if (length < 16)
2099  return(MagickFalse);
2100  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2101  if ((id != 0x4949) && (id != 0x4D4D))
2102  {
2103  while (length != 0)
2104  {
2105  if (ReadProfileByte(&exif,&length) != 0x45)
2106  continue;
2107  if (ReadProfileByte(&exif,&length) != 0x78)
2108  continue;
2109  if (ReadProfileByte(&exif,&length) != 0x69)
2110  continue;
2111  if (ReadProfileByte(&exif,&length) != 0x66)
2112  continue;
2113  if (ReadProfileByte(&exif,&length) != 0x00)
2114  continue;
2115  if (ReadProfileByte(&exif,&length) != 0x00)
2116  continue;
2117  break;
2118  }
2119  if (length < 16)
2120  return(MagickFalse);
2121  id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2122  }
2123  endian=LSBEndian;
2124  if (id == 0x4949)
2125  endian=LSBEndian;
2126  else
2127  if (id == 0x4D4D)
2128  endian=MSBEndian;
2129  else
2130  return(MagickFalse);
2131  if (ReadProfileShort(endian,exif+2) != 0x002a)
2132  return(MagickFalse);
2133  /*
2134  This the offset to the first IFD.
2135  */
2136  offset=(ssize_t) ReadProfileLong(endian,exif+4);
2137  if ((offset < 0) || ((size_t) offset >= length))
2138  return(MagickFalse);
2139  directory=exif+offset;
2140  level=0;
2141  entry=0;
2142  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2143  (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2144  do
2145  {
2146  if (level > 0)
2147  {
2148  level--;
2149  directory=directory_stack[level].directory;
2150  entry=directory_stack[level].entry;
2151  }
2152  if ((directory < exif) || (directory > (exif+length-2)))
2153  break;
2154  /*
2155  Determine how many entries there are in the current IFD.
2156  */
2157  number_entries=ReadProfileShort(endian,directory);
2158  for ( ; entry < number_entries; entry++)
2159  {
2160  int
2161  components;
2162 
2163  register unsigned char
2164  *p,
2165  *q;
2166 
2167  size_t
2168  number_bytes;
2169 
2170  ssize_t
2171  format,
2172  tag_value;
2173 
2174  q=(unsigned char *) (directory+2+(12*entry));
2175  if (q > (exif+length-12))
2176  break; /* corrupt EXIF */
2177  if (GetValueFromSplayTree(exif_resources,q) == q)
2178  break;
2179  (void) AddValueToSplayTree(exif_resources,q,q);
2180  tag_value=(ssize_t) ReadProfileShort(endian,q);
2181  format=(ssize_t) ReadProfileShort(endian,q+2);
2182  if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2183  break;
2184  components=(int) ReadProfileLong(endian,q+4);
2185  if (components < 0)
2186  break; /* corrupt EXIF */
2187  number_bytes=(size_t) components*format_bytes[format];
2188  if ((ssize_t) number_bytes < components)
2189  break; /* prevent overflow */
2190  if (number_bytes <= 4)
2191  p=q+8;
2192  else
2193  {
2194  /*
2195  The directory entry contains an offset.
2196  */
2197  offset=(ssize_t) ReadProfileLong(endian,q+8);
2198  if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2199  continue;
2200  if (~length < number_bytes)
2201  continue; /* prevent overflow */
2202  p=(unsigned char *) (exif+offset);
2203  }
2204  switch (tag_value)
2205  {
2206  case 0x011a:
2207  {
2208  (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2209  if (number_bytes == 8)
2210  (void) WriteProfileLong(endian,1UL,p+4);
2211  break;
2212  }
2213  case 0x011b:
2214  {
2215  (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2216  if (number_bytes == 8)
2217  (void) WriteProfileLong(endian,1UL,p+4);
2218  break;
2219  }
2220  case 0x0112:
2221  {
2222  if (number_bytes == 4)
2223  {
2224  (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2225  break;
2226  }
2227  (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2228  p);
2229  break;
2230  }
2231  case 0x0128:
2232  {
2233  if (number_bytes == 4)
2234  {
2235  (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2236  break;
2237  }
2238  (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2239  break;
2240  }
2241  default:
2242  break;
2243  }
2244  if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2245  {
2246  offset=(ssize_t) ReadProfileLong(endian,p);
2247  if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2248  {
2249  directory_stack[level].directory=directory;
2250  entry++;
2251  directory_stack[level].entry=entry;
2252  level++;
2253  directory_stack[level].directory=exif+offset;
2254  directory_stack[level].entry=0;
2255  level++;
2256  if ((directory+2+(12*number_entries)) > (exif+length))
2257  break;
2258  offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2259  number_entries));
2260  if ((offset != 0) && ((size_t) offset < length) &&
2261  (level < (MaxDirectoryStack-2)))
2262  {
2263  directory_stack[level].directory=exif+offset;
2264  directory_stack[level].entry=0;
2265  level++;
2266  }
2267  }
2268  break;
2269  }
2270  }
2271  } while (level > 0);
2272  exif_resources=DestroySplayTree(exif_resources);
2273  return(MagickTrue);
2274 }
2275 
2277 {
2279  status;
2280 
2281  StringInfo
2282  *profile;
2283 
2284  status=MagickTrue;
2285  profile=(StringInfo *) GetImageProfile(image,"8BIM");
2286  if (profile != (StringInfo *) NULL)
2287  if (Sync8BimProfile(image,profile) == MagickFalse)
2288  status=MagickFalse;
2289  profile=(StringInfo *) GetImageProfile(image,"EXIF");
2290  if (profile != (StringInfo *) NULL)
2291  if (SyncExifProfile(image,profile) == MagickFalse)
2292  status=MagickFalse;
2293  return(status);
2294 }
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 int CompareStringInfo(const StringInfo *target, const StringInfo *source)
Definition: string.c:378
MagickExport MagickBooleanType IsOptionMember(const char *option, const char *options)
Definition: option.c:2727
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:1889
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:1774
MagickExport MagickBooleanType DeleteImageProfile(Image *image, const char *name)
Definition: profile.c:221
static const unsigned char * ReadResourceByte(const unsigned char *p, unsigned char *quantum)
Definition: profile.c:1448
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:147
static void * DestroyProfile(void *profile)
Definition: profile.c:1443
struct _CMSExceptionInfo CMSExceptionInfo
MagickBooleanType SyncExifProfile(Image *image, StringInfo *profile)
Definition: profile.c:2050
MagickExport void DestroyImageProfiles(Image *image)
Definition: profile.c:255
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:499
MagickExport size_t CopyMagickString(char *magick_restrict destination, const char *magick_restrict source, const size_t length)
Definition: string.c:755
ResolutionType units
Definition: image.h:198
static void WriteProfileShort(const EndianType endian, const unsigned short value, unsigned char *p)
Definition: profile.c:1970
unsigned char * info
Definition: profile.c:138
#define ThrowBinaryException(severity, tag, context)
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:129
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:1215
#define LCMSScaleTarget(pixel)
Definition: profile.c:111
#define MaxDirectoryStack
MagickBooleanType
Definition: magick-type.h:158
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:1948
MagickBooleanType black_point_compensation
Definition: image.h:258
static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
Definition: profile.c:1762
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:850
static void GetProfilesFromResourceBlock(Image *image, const StringInfo *resource_block, ExceptionInfo *exception)
Definition: profile.c:1595
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:553
MagickExport MagickBooleanType CloneImageProfiles(Image *image, const Image *clone_image)
Definition: profile.c:178
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:1861
MagickExport const StringInfo * GetImageProfile(const Image *image, const char *name)
Definition: profile.c:285
#define magick_unused(x)
static MagickBooleanType SetsRGBImageProfile(Image *image, ExceptionInfo *exception)
Definition: profile.c:521
size_t signature
Definition: profile.c:141
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:1486
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:1413
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
Definition: resource.c:790
static DoublePixelPacket ** DestroyPixelThreadSet(DoublePixelPacket **pixels)
Definition: quantize.c:1425
static const unsigned char * ReadResourceShort(const unsigned char *p, unsigned short *quantum)
Definition: profile.c:1465
static DoublePixelPacket ** AcquirePixelThreadSet(const size_t count)
Definition: quantize.c:1438
#define LCMSScaleSource(pixel)
Definition: profile.c:110
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:2615
MagickExport StringInfo * RemoveImageProfile(Image *image, const char *name)
Definition: profile.c:1360
MagickExport const void * GetValueFromSplayTree(SplayTreeInfo *splay_tree, const void *key)
Definition: splay-tree.c:921
MagickExport char * GetNextImageProfile(const Image *image)
Definition: profile.c:324
MagickExport StringInfo * AcquireStringInfo(const size_t length)
Definition: string.c:187
MagickExport MagickBooleanType SetImageProfile(Image *image, const char *name, const StringInfo *profile, ExceptionInfo *exception)
Definition: profile.c:1819
static MagickBooleanType Sync8BimProfile(Image *image, StringInfo *profile)
Definition: profile.c:1988
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:82
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1196
MagickExport const char * GetImageProperty(const Image *image, const char *property, ExceptionInfo *exception)
Definition: property.c:2236
static signed int ReadProfileMSBLong(unsigned char **p, size_t *length)
Definition: profile.c:1921
MagickExport void * RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree, const void *key)
Definition: splay-tree.c:1299
double LCMSType
Definition: profile.c:113
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:1473
size_t length
Definition: profile.c:135
ColorspaceType
Definition: colorspace.h:25
MagickPrivate MagickBooleanType SyncImageProfiles(Image *)
Definition: profile.c:2276
MagickExport void ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:1472
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1084
PointInfo resolution
Definition: image.h:209
#define magick_unreferenced(x)
#define TAG_EXIF_OFFSET
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
static int ReadProfileByte(unsigned char **p, size_t *length)
Definition: profile.c:1849
static void SetPixelRed(const Image *magick_restrict image, const Quantum red, Quantum *magick_restrict pixel)
char * name
Definition: profile.c:132
ResolutionType
Definition: image.h:89
#define MagickPrivate
MagickExport void ResetImageProfileIterator(const Image *image)
Definition: profile.c:1401
size_t length
Definition: string_.h:36
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
OrientationType orientation
Definition: image.h:166
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
MagickExport MagickBooleanType ProfileImage(Image *image, const char *name, const void *datum, const size_t length, ExceptionInfo *exception)
Definition: profile.c:814
static void SetPixelBlack(const Image *magick_restrict image, const Quantum black, Quantum *magick_restrict pixel)
static char * StringLocateSubstring(const char *haystack, const char *needle)
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:1244
static signed short ReadProfileMSBShort(unsigned char **p, size_t *length)
Definition: profile.c:1934
MagickExport char * ConstantString(const char *source)
Definition: string.c:700
static const unsigned char * ReadResourceLong(const unsigned char *p, unsigned int *quantum)
Definition: profile.c:1455
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:1712
MagickBooleanType debug
Definition: image.h:334
ExceptionInfo * exception
Definition: profile.c:150
static void SetPixelGreen(const Image *magick_restrict image, const Quantum green, Quantum *magick_restrict pixel)