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