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