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