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