profile.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %               PPPP   RRRR    OOO   FFFFF  IIIII  L      EEEEE               %
00007 %               P   P  R   R  O   O  F        I    L      E                   %
00008 %               PPPP   RRRR   O   O  FFF      I    L      EEE                 %
00009 %               P      R R    O   O  F        I    L      E                   %
00010 %               P      R  R    OOO   F      IIIII  LLLLL  EEEEE               %
00011 %                                                                             %
00012 %                                                                             %
00013 %                       MagickCore Image Profile Methods                      %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 July 1992                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "magick/studio.h"
00043 #include "magick/cache.h"
00044 #include "magick/color.h"
00045 #include "magick/configure.h"
00046 #include "magick/exception.h"
00047 #include "magick/exception-private.h"
00048 #include "magick/hashmap.h"
00049 #include "magick/image.h"
00050 #include "magick/memory_.h"
00051 #include "magick/monitor.h"
00052 #include "magick/option.h"
00053 #include "magick/profile.h"
00054 #include "magick/property.h"
00055 #include "magick/quantum.h"
00056 #include "magick/quantum-private.h"
00057 #include "magick/splay-tree.h"
00058 #include "magick/string_.h"
00059 #include "magick/token.h"
00060 #include "magick/utility.h"
00061 #if defined(MAGICKCORE_LCMS_DELEGATE)
00062 #if defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
00063 #include <lcms/lcms.h>
00064 #else
00065 #include "lcms.h"
00066 #endif
00067 #endif
00068 
00069 /*
00070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00071 %                                                                             %
00072 %                                                                             %
00073 %                                                                             %
00074 %   C l o n e I m a g e P r o f i l e s                                       %
00075 %                                                                             %
00076 %                                                                             %
00077 %                                                                             %
00078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00079 %
00080 %  CloneImageProfiles() clones one or more image profiles.
00081 %
00082 %  The format of the CloneImageProfiles method is:
00083 %
00084 %      MagickBooleanType CloneImageProfiles(Image *image,
00085 %        const Image *clone_image)
00086 %
00087 %  A description of each parameter follows:
00088 %
00089 %    o image: the image.
00090 %
00091 %    o clone_image: the clone image.
00092 %
00093 */
00094 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
00095   const Image *clone_image)
00096 {
00097   assert(image != (Image *) NULL);
00098   assert(image->signature == MagickSignature);
00099   if (image->debug != MagickFalse)
00100     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00101   assert(clone_image != (const Image *) NULL);
00102   assert(clone_image->signature == MagickSignature);
00103   image->color_profile.length=clone_image->color_profile.length;
00104   image->color_profile.info=clone_image->color_profile.info;
00105   image->iptc_profile.length=clone_image->iptc_profile.length;
00106   image->iptc_profile.info=clone_image->iptc_profile.info;
00107   if (clone_image->profiles != (void *) NULL)
00108     image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
00109       (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
00110   return(MagickTrue);
00111 }
00112 
00113 /*
00114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00115 %                                                                             %
00116 %                                                                             %
00117 %                                                                             %
00118 %   D e l e t e I m a g e P r o f i l e                                       %
00119 %                                                                             %
00120 %                                                                             %
00121 %                                                                             %
00122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00123 %
00124 %  DeleteImageProfile() deletes a profile from the image by its name.
00125 %
00126 %  The format of the DeleteImageProfile method is:
00127 %
00128 %      MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
00129 %
00130 %  A description of each parameter follows:
00131 %
00132 %    o image: the image.
00133 %
00134 %    o name: the profile name.
00135 %
00136 */
00137 MagickExport MagickBooleanType DeleteImageProfile(Image *image,
00138   const char *name)
00139 {
00140   assert(image != (Image *) NULL);
00141   assert(image->signature == MagickSignature);
00142   if (image->debug != MagickFalse)
00143     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00144   if (image->profiles == (SplayTreeInfo *) NULL)
00145     return(MagickFalse);
00146   if (LocaleCompare(name,"icc") == 0)
00147     {
00148       /*
00149         Continue to support deprecated color profile for now.
00150       */
00151       image->color_profile.length=0;
00152       image->color_profile.info=(unsigned char *) NULL;
00153     }
00154   if (LocaleCompare(name,"iptc") == 0)
00155     {
00156       /*
00157         Continue to support deprecated IPTC profile for now.
00158       */
00159       image->iptc_profile.length=0;
00160       image->iptc_profile.info=(unsigned char *) NULL;
00161     }
00162   return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
00163 }
00164 
00165 /*
00166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00167 %                                                                             %
00168 %                                                                             %
00169 %                                                                             %
00170 %   D e s t r o y I m a g e P r o f i l e s                                   %
00171 %                                                                             %
00172 %                                                                             %
00173 %                                                                             %
00174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00175 %
00176 %  DestroyImageProfiles() releases memory associated with an image profile map.
00177 %
00178 %  The format of the DestroyProfiles method is:
00179 %
00180 %      void DestroyImageProfiles(Image *image)
00181 %
00182 %  A description of each parameter follows:
00183 %
00184 %    o image: the image.
00185 %
00186 */
00187 MagickExport void DestroyImageProfiles(Image *image)
00188 {
00189   if (image->profiles != (SplayTreeInfo *) NULL)
00190     image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
00191 }
00192 
00193 /*
00194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00195 %                                                                             %
00196 %                                                                             %
00197 %                                                                             %
00198 %   G e t I m a g e P r o f i l e                                             %
00199 %                                                                             %
00200 %                                                                             %
00201 %                                                                             %
00202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00203 %
00204 %  GetImageProfile() gets a profile associated with an image by name.
00205 %
00206 %  The format of the GetImageProfile method is:
00207 %
00208 %      const StringInfo *GetImageProfile(const Image *image,const char *name)
00209 %
00210 %  A description of each parameter follows:
00211 %
00212 %    o image: the image.
00213 %
00214 %    o name: the profile name.
00215 %
00216 */
00217 MagickExport const StringInfo *GetImageProfile(const Image *image,
00218   const char *name)
00219 {
00220   char
00221     key[MaxTextExtent];
00222 
00223   const StringInfo
00224     *profile;
00225 
00226   assert(image != (Image *) NULL);
00227   assert(image->signature == MagickSignature);
00228   if (image->debug != MagickFalse)
00229     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00230   if (image->profiles == (SplayTreeInfo *) NULL)
00231     return((StringInfo *) NULL);
00232   (void) CopyMagickString(key,name,MaxTextExtent);
00233   profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
00234     image->profiles,key);
00235   return(profile);
00236 }
00237 
00238 /*
00239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00240 %                                                                             %
00241 %                                                                             %
00242 %                                                                             %
00243 %   G e t N e x t I m a g e P r o f i l e                                     %
00244 %                                                                             %
00245 %                                                                             %
00246 %                                                                             %
00247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00248 %
00249 %  GetNextImageProfile() gets the next profile name for an image.
00250 %
00251 %  The format of the GetNextImageProfile method is:
00252 %
00253 %      char *GetNextImageProfile(const Image *image)
00254 %
00255 %  A description of each parameter follows:
00256 %
00257 %    o hash_info: the hash info.
00258 %
00259 */
00260 MagickExport char *GetNextImageProfile(const Image *image)
00261 {
00262   assert(image != (Image *) NULL);
00263   assert(image->signature == MagickSignature);
00264   if (image->debug != MagickFalse)
00265     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00266   if (image->profiles == (SplayTreeInfo *) NULL)
00267     return((char *) NULL);
00268   return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
00269 }
00270 
00271 /*
00272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00273 %                                                                             %
00274 %                                                                             %
00275 %                                                                             %
00276 %   P r o f i l e I m a g e                                                   %
00277 %                                                                             %
00278 %                                                                             %
00279 %                                                                             %
00280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00281 %
00282 %  ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
00283 %  profile with / to / from an image.  If the profile is NULL, it is removed
00284 %  from the image otherwise added or applied.  Use a name of '*' and a profile
00285 %  of NULL to remove all profiles from the image.
00286 %
00287 %  ICC and ICM profiles are handled as follows: If the image does not have
00288 %  an associated color profile, the one you provide is associated with the
00289 %  image and the image pixels are not transformed.  Otherwise, the colorspace
00290 %  transform defined by the existing and new profile are applied to the image
00291 %  pixels and the new profile is associated with the image.
00292 %
00293 %  The format of the ProfileImage method is:
00294 %
00295 %      MagickBooleanType ProfileImage(Image *image,const char *name,
00296 %        const void *datum,const size_t length,const MagickBooleanType clone)
00297 %
00298 %  A description of each parameter follows:
00299 %
00300 %    o image: the image.
00301 %
00302 %    o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
00303 %
00304 %    o datum: the profile data.
00305 %
00306 %    o length: the length of the profile.
00307 %
00308 %    o clone: should be MagickFalse.
00309 %
00310 */
00311 
00312 static MagickBooleanType SetAdobeRGB1998ImageProfile(Image *image)
00313 {
00314   static unsigned char
00315     AdobeRGB1998Profile[] =
00316     {
00317       0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00,
00318       0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
00319       0x5a, 0x20, 0x07, 0xd0, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x13, 0x00,
00320       0x33, 0x00, 0x3b, 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c,
00321       0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
00322       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00323       0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
00324       0x00, 0xd3, 0x2d, 0x41, 0x44, 0x42, 0x45, 0x00, 0x00, 0x00, 0x00,
00325       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00326       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00327       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00328       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
00329       0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
00330       0x32, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00,
00331       0x00, 0x6b, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9c, 0x00,
00332       0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x01, 0xb0,
00333       0x00, 0x00, 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01,
00334       0xc4, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00,
00335       0x01, 0xd4, 0x00, 0x00, 0x00, 0x0e, 0x62, 0x54, 0x52, 0x43, 0x00,
00336       0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x0e, 0x72, 0x58, 0x59, 0x5a,
00337       0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59,
00338       0x5a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58,
00339       0x59, 0x5a, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x74,
00340       0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79,
00341       0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
00342       0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
00343       0x6d, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
00344       0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
00345       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6f,
00346       0x62, 0x65, 0x20, 0x52, 0x47, 0x42, 0x20, 0x28, 0x31, 0x39, 0x39,
00347       0x38, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00348       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00349       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00350       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00351       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00352       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00353       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00354       0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
00355       0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00,
00356       0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
00357       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00358       0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00359       0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00,
00360       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
00361       0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00362       0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
00363       0x00, 0x00, 0x00, 0x00, 0x9c, 0x18, 0x00, 0x00, 0x4f, 0xa5, 0x00,
00364       0x00, 0x04, 0xfc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
00365       0x00, 0x00, 0x34, 0x8d, 0x00, 0x00, 0xa0, 0x2c, 0x00, 0x00, 0x0f,
00366       0x95, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00367       0x26, 0x31, 0x00, 0x00, 0x10, 0x2f, 0x00, 0x00, 0xbe, 0x9c
00368     };
00369 
00370   StringInfo
00371     *profile;
00372 
00373   MagickBooleanType
00374     status;
00375 
00376   assert(image != (Image *) NULL);
00377   assert(image->signature == MagickSignature);
00378   if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
00379     return(MagickFalse);
00380   profile=AcquireStringInfo(sizeof(AdobeRGB1998Profile));
00381   SetStringInfoDatum(profile,AdobeRGB1998Profile);
00382   status=SetImageProfile(image,"icm",profile);
00383   profile=DestroyStringInfo(profile);
00384   return(status);
00385 }
00386 
00387 static MagickBooleanType SetsRGBImageProfile(Image *image)
00388 {
00389   static unsigned char
00390     sRGBProfile[] =
00391     {
00392       0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
00393       0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
00394       0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
00395       0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
00396       0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
00397       0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00398       0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
00399       0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
00400       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00401       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00402       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00403       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
00404       0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00,
00405       0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00,
00406       0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00,
00407       0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04,
00408       0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02,
00409       0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00,
00410       0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00,
00411       0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64,
00412       0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64,
00413       0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75,
00414       0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76,
00415       0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24,
00416       0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00,
00417       0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00,
00418       0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00,
00419       0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c,
00420       0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04,
00421       0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00,
00422       0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00,
00423       0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
00424       0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20,
00425       0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63,
00426       0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
00427       0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
00428       0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45,
00429       0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00,
00430       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
00431       0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
00432       0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
00433       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00434       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00435       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00436       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00437       0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00438       0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58,
00439       0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00440       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a,
00441       0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00,
00442       0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00,
00443       0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85,
00444       0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
00445       0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00,
00446       0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
00447       0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
00448       0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
00449       0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00450       0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
00451       0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
00452       0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00453       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00454       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00455       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00456       0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00,
00457       0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31,
00458       0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66,
00459       0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f,
00460       0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
00461       0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
00462       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
00463       0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
00464       0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20,
00465       0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63,
00466       0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
00467       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00468       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73,
00469       0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
00470       0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
00471       0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
00472       0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
00473       0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
00474       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
00475       0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
00476       0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
00477       0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
00478       0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
00479       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00480       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00481       0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
00482       0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00,
00483       0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e,
00484       0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
00485       0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57,
00486       0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
00487       0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00488       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
00489       0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00,
00490       0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00,
00491       0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05,
00492       0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00,
00493       0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b,
00494       0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00,
00495       0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
00496       0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00,
00497       0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9,
00498       0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00,
00499       0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0,
00500       0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01,
00501       0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f,
00502       0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01,
00503       0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67,
00504       0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01,
00505       0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9,
00506       0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01,
00507       0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
00508       0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02,
00509       0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a,
00510       0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02,
00511       0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb,
00512       0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03,
00513       0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66,
00514       0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03,
00515       0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec,
00516       0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04,
00517       0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e,
00518       0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04,
00519       0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
00520       0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05,
00521       0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5,
00522       0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06,
00523       0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b,
00524       0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06,
00525       0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d,
00526       0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07,
00527       0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b,
00528       0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08,
00529       0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7,
00530       0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09,
00531       0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
00532       0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a,
00533       0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5,
00534       0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b,
00535       0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8,
00536       0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c,
00537       0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9,
00538       0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d,
00539       0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8,
00540       0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e,
00541       0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25,
00542       0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f,
00543       0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
00544       0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11,
00545       0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa,
00546       0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12,
00547       0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03,
00548       0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13,
00549       0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a,
00550       0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15,
00551       0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0,
00552       0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16,
00553       0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65,
00554       0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18,
00555       0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
00556       0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19,
00557       0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e,
00558       0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b,
00559       0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52,
00560       0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d,
00561       0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16,
00562       0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f,
00563       0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea,
00564       0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20,
00565       0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce,
00566       0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22,
00567       0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
00568       0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24,
00569       0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7,
00570       0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26,
00571       0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc,
00572       0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29,
00573       0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02,
00574       0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b,
00575       0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39,
00576       0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d,
00577       0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82,
00578       0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f,
00579       0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
00580       0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32,
00581       0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46,
00582       0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34,
00583       0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2,
00584       0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37,
00585       0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50,
00586       0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39,
00587       0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef,
00588       0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c,
00589       0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1,
00590       0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f,
00591       0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
00592       0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41,
00593       0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a,
00594       0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44,
00595       0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22,
00596       0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47,
00597       0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d,
00598       0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a,
00599       0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a,
00600       0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d,
00601       0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49,
00602       0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51,
00603       0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
00604       0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54,
00605       0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2,
00606       0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57,
00607       0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a,
00608       0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a,
00609       0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86,
00610       0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e,
00611       0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05,
00612       0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61,
00613       0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97,
00614       0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65,
00615       0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
00616       0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69,
00617       0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7,
00618       0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d,
00619       0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4,
00620       0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70,
00621       0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6,
00622       0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74,
00623       0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b,
00624       0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78,
00625       0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5,
00626       0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c,
00627       0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
00628       0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81,
00629       0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4,
00630       0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85,
00631       0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b,
00632       0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89,
00633       0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96,
00634       0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d,
00635       0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06,
00636       0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92,
00637       0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a,
00638       0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97,
00639       0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
00640       0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b,
00641       0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2,
00642       0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0,
00643       0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96,
00644       0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5,
00645       0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e,
00646       0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa,
00647       0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c,
00648       0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf,
00649       0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60,
00650       0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4,
00651       0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
00652       0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9,
00653       0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7,
00654       0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe,
00655       0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec,
00656       0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3,
00657       0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46,
00658       0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9,
00659       0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6,
00660       0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce,
00661       0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c,
00662       0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4,
00663       0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
00664       0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9,
00665       0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a,
00666       0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf,
00667       0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53,
00668       0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5,
00669       0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32,
00670       0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb,
00671       0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28,
00672       0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1,
00673       0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34,
00674       0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7,
00675       0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
00676       0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd,
00677       0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
00678     };
00679 
00680   StringInfo
00681     *profile;
00682 
00683   MagickBooleanType
00684     status;
00685 
00686   assert(image != (Image *) NULL);
00687   assert(image->signature == MagickSignature);
00688   if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
00689     return(MagickFalse);
00690   profile=AcquireStringInfo(sizeof(sRGBProfile));
00691   SetStringInfoDatum(profile,sRGBProfile);
00692   status=SetImageProfile(image,"icm",profile);
00693   profile=DestroyStringInfo(profile);
00694   return(status);
00695 }
00696 #if defined(MAGICKCORE_LCMS_DELEGATE)
00697 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
00698 static int LCMSErrorHandler(int severity,const char *message)
00699 {
00700   (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
00701     severity,message != (char *) NULL ? message : "no message");
00702   return(1);
00703 }
00704 #endif
00705 #endif
00706 
00707 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
00708   const void *datum,const size_t length,
00709   const MagickBooleanType magick_unused(clone))
00710 {
00711 #define ThrowProfileException(severity,tag,context) \
00712 { \
00713   (void) cmsCloseProfile(source_profile); \
00714   (void) cmsCloseProfile(target_profile); \
00715   ThrowBinaryException(severity,tag,context); \
00716 }
00717 
00718   MagickBooleanType
00719     status;
00720 
00721   StringInfo
00722     *profile;
00723 
00724   assert(image != (Image *) NULL);
00725   assert(image->signature == MagickSignature);
00726   if (image->debug != MagickFalse)
00727     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00728   assert(name != (const char *) NULL);
00729   if ((datum == (const void *) NULL) || (length == 0))
00730     {
00731       char
00732         **arguments,
00733         *names;
00734 
00735       int
00736         number_arguments;
00737 
00738       register long
00739         i;
00740 
00741       /*
00742         Delete image profile(s).
00743       */
00744       names=ConstantString(name);
00745       (void) SubstituteString(&names,","," ");
00746       arguments=StringToArgv(names,&number_arguments);
00747       names=DestroyString(names);
00748       if (arguments == (char **) NULL)
00749         return(MagickTrue);
00750       ResetImageProfileIterator(image);
00751       for (name=GetNextImageProfile(image); name != (const char *) NULL; )
00752       {
00753         for (i=1; i < number_arguments; i++)
00754         {
00755           if ((*arguments[i] == '!') &&
00756               (LocaleCompare(name,arguments[i]+1) == 0))
00757             break;
00758           if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
00759             {
00760               (void) DeleteImageProfile(image,name);
00761               ResetImageProfileIterator(image);
00762               break;
00763             }
00764         }
00765         name=GetNextImageProfile(image);
00766       }
00767       for (i=0; i < number_arguments; i++)
00768         arguments[i]=DestroyString(arguments[i]);
00769       arguments=(char **) RelinquishMagickMemory(arguments);
00770       return(MagickTrue);
00771     }
00772   /*
00773     Add a ICC, IPTC, or generic profile to the image.
00774   */
00775   profile=AcquireStringInfo((size_t) length);
00776   SetStringInfoDatum(profile,(unsigned char *) datum);
00777   if ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0))
00778     {
00779       const StringInfo
00780         *icc_profile;
00781 
00782       icc_profile=GetImageProfile(image,"icc");
00783       if ((icc_profile != (const StringInfo *) NULL) &&
00784           (CompareStringInfo(icc_profile,profile) == 0))
00785         {
00786           const char
00787             *value;
00788 
00789           value=GetImageProperty(image,"exif:ColorSpace");
00790           if (LocaleCompare(value,"1") != 0)
00791             (void) SetsRGBImageProfile(image);
00792           value=GetImageProperty(image,"exif:InteroperabilityIndex");
00793           if (LocaleCompare(value,"R98.") != 0)
00794             (void) SetsRGBImageProfile(image);
00795           value=GetImageProperty(image,"exif:InteroperabilityIndex");
00796           if (LocaleCompare(value,"R03.") != 0)
00797             (void) SetAdobeRGB1998ImageProfile(image);
00798           icc_profile=GetImageProfile(image,"icc");
00799         }
00800       if ((icc_profile != (const StringInfo *) NULL) &&
00801           (CompareStringInfo(icc_profile,profile) == 0))
00802         {
00803           profile=DestroyStringInfo(profile);
00804           return(MagickTrue);
00805         }
00806 #if !defined(MAGICKCORE_LCMS_DELEGATE)
00807       (void) ThrowMagickException(&image->exception,GetMagickModule(),
00808         MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
00809         image->filename);
00810 #else
00811       if (icc_profile == (StringInfo *) NULL)
00812         (void) ThrowMagickException(&image->exception,GetMagickModule(),
00813           ImageWarning,"AssociateProfile","`%s'",name);
00814       else
00815         {
00816           ColorspaceType
00817             source_colorspace,
00818             target_colorspace;
00819 
00820           cmsHPROFILE
00821             source_profile,
00822             target_profile;
00823 
00824           cmsHTRANSFORM
00825             transform;
00826 
00827           DWORD
00828             flags,
00829             source_type,
00830             target_type;
00831 
00832           ExceptionInfo
00833             *exception;
00834 
00835           int
00836             intent;
00837 
00838           long
00839             y;
00840 
00841           register IndexPacket
00842             *__restrict indexes;
00843 
00844           register long
00845             x;
00846 
00847           register PixelPacket
00848             *__restrict q;
00849 
00850           register unsigned short
00851             *p;
00852 
00853           size_t
00854             length,
00855             source_channels,
00856             target_channels;
00857 
00858           unsigned short
00859             *source_pixels,
00860             *target_pixels;
00861 
00862           /*
00863             Transform pixel colors as defined by the color profiles.
00864           */
00865 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
00866           cmsSetErrorHandler(LCMSErrorHandler);
00867 #else
00868           (void) cmsErrorAction(LCMS_ERROR_SHOW);
00869 #endif
00870           source_profile=cmsOpenProfileFromMem(GetStringInfoDatum(icc_profile),
00871             (DWORD) GetStringInfoLength(icc_profile));
00872           target_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
00873             (DWORD) GetStringInfoLength(profile));
00874           if ((source_profile == (cmsHPROFILE) NULL) ||
00875               (target_profile == (cmsHPROFILE) NULL))
00876             ThrowBinaryException(ResourceLimitError,
00877               "ColorspaceColorProfileMismatch",name);
00878           switch (cmsGetColorSpace(source_profile))
00879           {
00880             case icSigCmykData:
00881             {
00882               source_colorspace=CMYKColorspace;
00883               source_type=(DWORD) TYPE_CMYK_16;
00884               source_channels=4;
00885               break;
00886             }
00887             case icSigGrayData:
00888             {
00889               source_colorspace=GRAYColorspace;
00890               source_type=(DWORD) TYPE_GRAY_16;
00891               source_channels=1;
00892               break;
00893             }
00894             case icSigLabData:
00895             {
00896               source_colorspace=LabColorspace;
00897               source_type=(DWORD) TYPE_Lab_16;
00898               source_channels=3;
00899               break;
00900             }
00901             case icSigLuvData:
00902             {
00903               source_colorspace=YUVColorspace;
00904               source_type=(DWORD) TYPE_YUV_16;
00905               source_channels=3;
00906               break;
00907             }
00908             case icSigRgbData:
00909             {
00910               source_colorspace=RGBColorspace;
00911               source_type=(DWORD) TYPE_RGB_16;
00912               source_channels=3;
00913               break;
00914             }
00915             case icSigXYZData:
00916             {
00917               source_colorspace=XYZColorspace;
00918               source_type=(DWORD) TYPE_XYZ_16;
00919               source_channels=3;
00920               break;
00921             }
00922             case icSigYCbCrData:
00923             {
00924               source_colorspace=YCbCrColorspace;
00925               source_type=(DWORD) TYPE_YCbCr_16;
00926               source_channels=3;
00927               break;
00928             }
00929             default:
00930             {
00931               source_colorspace=UndefinedColorspace;
00932               source_type=(DWORD) TYPE_RGB_16;
00933               source_channels=3;
00934               break;
00935             }
00936           }
00937           switch (cmsGetColorSpace(target_profile))
00938           {
00939             case icSigCmykData:
00940             {
00941               target_colorspace=CMYKColorspace;
00942               target_type=(DWORD) TYPE_CMYK_16;
00943               target_channels=4;
00944               break;
00945             }
00946             case icSigLabData:
00947             {
00948               target_colorspace=LabColorspace;
00949               target_type=(DWORD) TYPE_Lab_16;
00950               target_channels=3;
00951               break;
00952             }
00953             case icSigGrayData:
00954             {
00955               target_colorspace=GRAYColorspace;
00956               target_type=(DWORD) TYPE_GRAY_16;
00957               target_channels=1;
00958               break;
00959             }
00960             case icSigLuvData:
00961             {
00962               target_colorspace=YUVColorspace;
00963               target_type=(DWORD) TYPE_YUV_16;
00964               target_channels=3;
00965               break;
00966             }
00967             case icSigRgbData:
00968             {
00969               target_colorspace=RGBColorspace;
00970               target_type=(DWORD) TYPE_RGB_16;
00971               target_channels=3;
00972               break;
00973             }
00974             case icSigXYZData:
00975             {
00976               target_colorspace=XYZColorspace;
00977               target_type=(DWORD) TYPE_XYZ_16;
00978               target_channels=3;
00979               break;
00980             }
00981             case icSigYCbCrData:
00982             {
00983               target_colorspace=YCbCrColorspace;
00984               target_type=(DWORD) TYPE_YCbCr_16;
00985               target_channels=3;
00986               break;
00987             }
00988             default:
00989             {
00990               target_colorspace=UndefinedColorspace;
00991               target_type=(DWORD) TYPE_RGB_16;
00992               target_channels=3;
00993               break;
00994             }
00995           }
00996           exception=(&image->exception);
00997           if ((source_colorspace == UndefinedColorspace) ||
00998               (target_colorspace == UndefinedColorspace))
00999             ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
01000               name);
01001            if ((source_colorspace == GRAYColorspace) &&
01002                (IsGrayImage(image,exception) == MagickFalse))
01003             ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
01004               name);
01005            if ((source_colorspace == CMYKColorspace) &&
01006                (image->colorspace != CMYKColorspace))
01007             ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
01008               name);
01009            if ((source_colorspace == XYZColorspace) &&
01010                (image->colorspace != XYZColorspace))
01011             ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
01012               name);
01013            if ((source_colorspace == YCbCrColorspace) &&
01014                (image->colorspace != YCbCrColorspace))
01015             ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
01016               name);
01017            if ((source_colorspace != CMYKColorspace) &&
01018                (source_colorspace != GRAYColorspace) &&
01019                (source_colorspace != LabColorspace) &&
01020                (source_colorspace != XYZColorspace) &&
01021                (source_colorspace != YCbCrColorspace) &&
01022                (image->colorspace != RGBColorspace))
01023             ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
01024               name);
01025           switch (image->rendering_intent)
01026           {
01027             case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
01028             case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
01029             case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
01030             case SaturationIntent: intent=INTENT_SATURATION; break;
01031             default: intent=INTENT_PERCEPTUAL; break;
01032           }
01033           flags=cmsFLAGS_HIGHRESPRECALC;
01034 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
01035           if (image->black_point_compensation != MagickFalse)
01036             flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
01037 #endif
01038           transform=cmsCreateTransform(source_profile,source_type,
01039             target_profile,target_type,intent,flags);
01040           (void) cmsCloseProfile(source_profile);
01041           if (transform == (cmsHTRANSFORM) NULL)
01042             ThrowBinaryException(ImageError,"UnableToCreateColorTransform",
01043               name);
01044           /*
01045             Transform image as dictated by the source and target image profiles.
01046           */
01047           length=(size_t) image->columns;
01048           source_pixels=(unsigned short *) AcquireQuantumMemory(length,
01049             source_channels*sizeof(*source_pixels));
01050           target_pixels=(unsigned short *) AcquireQuantumMemory(length,
01051             target_channels*sizeof(*target_pixels));
01052           if ((source_pixels == (unsigned short *) NULL) ||
01053               (target_pixels == (unsigned short *) NULL))
01054             {
01055               cmsDeleteTransform(transform);
01056               (void) cmsCloseProfile(target_profile);
01057               ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
01058                 image->filename);
01059             }
01060           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01061             {
01062               cmsDeleteTransform(transform);
01063               (void) cmsCloseProfile(target_profile);
01064               return(MagickFalse);
01065             }
01066           if (target_colorspace == CMYKColorspace)
01067             (void) SetImageColorspace(image,target_colorspace);
01068           for (y=0; y < (long) image->rows; y++)
01069           {
01070             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
01071             if (q == (PixelPacket *) NULL)
01072               break;
01073             p=source_pixels;
01074             indexes=GetAuthenticIndexQueue(image);
01075             for (x=0; x < (long) image->columns; x++)
01076             {
01077               *p++=ScaleQuantumToShort(q->red);
01078               if (source_channels > 1)
01079                 {
01080                   *p++=ScaleQuantumToShort(q->green);
01081                   *p++=ScaleQuantumToShort(q->blue);
01082                 }
01083               if (source_channels > 3)
01084                 *p++=ScaleQuantumToShort(indexes[x]);
01085               q++;
01086             }
01087             cmsDoTransform(transform,source_pixels,target_pixels,(unsigned int)
01088               image->columns);
01089             p=target_pixels;
01090             q-=image->columns;
01091             for (x=0; x < (long) image->columns; x++)
01092             {
01093               q->red=ScaleShortToQuantum(*p);
01094               q->green=q->red;
01095               q->blue=q->red;
01096               p++;
01097               if (target_channels > 1)
01098                 {
01099                   q->green=ScaleShortToQuantum(*p);
01100                   p++;
01101                   q->blue=ScaleShortToQuantum(*p);
01102                   p++;
01103                 }
01104               if (target_channels > 3)
01105                 {
01106                   indexes[x]=ScaleShortToQuantum(*p);
01107                   p++;
01108                 }
01109               q++;
01110             }
01111             if (SyncAuthenticPixels(image,exception) == MagickFalse)
01112               break;
01113           }
01114           (void) SetImageColorspace(image,target_colorspace);
01115           switch (cmsGetColorSpace(target_profile))
01116           {
01117             case icSigRgbData:
01118             {
01119               image->type=image->matte == MagickFalse ? TrueColorType :
01120                 TrueColorMatteType;
01121               break;
01122             }
01123             case icSigCmykData:
01124             {
01125               image->type=image->matte == MagickFalse ? ColorSeparationType :
01126                 ColorSeparationMatteType;
01127               break;
01128             }
01129             case icSigGrayData:
01130             {
01131               image->type=image->matte == MagickFalse ? GrayscaleType :
01132                 GrayscaleMatteType;
01133               break;
01134             }
01135             default:
01136               break;
01137           }
01138           target_pixels=(unsigned short *) RelinquishMagickMemory(
01139             target_pixels);
01140           source_pixels=(unsigned short *) RelinquishMagickMemory(
01141             source_pixels);
01142           cmsDeleteTransform(transform);
01143           (void) cmsCloseProfile(target_profile);
01144         }
01145 #endif
01146     }
01147   status=SetImageProfile(image,name,profile);
01148   profile=DestroyStringInfo(profile);
01149   return(status);
01150 }
01151 
01152 /*
01153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01154 %                                                                             %
01155 %                                                                             %
01156 %                                                                             %
01157 %   R e m o v e I m a g e P r o f i l e                                       %
01158 %                                                                             %
01159 %                                                                             %
01160 %                                                                             %
01161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01162 %
01163 %  RemoveImageProfile() removes a named profile from the image and returns its
01164 %  value.
01165 %
01166 %  The format of the RemoveImageProfile method is:
01167 %
01168 %      void *RemoveImageProfile(Image *image,const char *name)
01169 %
01170 %  A description of each parameter follows:
01171 %
01172 %    o image: the image.
01173 %
01174 %    o name: the profile name.
01175 %
01176 */
01177 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
01178 {
01179   StringInfo
01180     *profile;
01181 
01182   assert(image != (Image *) NULL);
01183   assert(image->signature == MagickSignature);
01184   if (image->debug != MagickFalse)
01185     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01186   if (image->profiles == (SplayTreeInfo *) NULL)
01187     return((StringInfo *) NULL);
01188   if (LocaleCompare(name,"icc") == 0)
01189     {
01190       /*
01191         Continue to support deprecated color profile for now.
01192       */
01193       image->color_profile.length=0;
01194       image->color_profile.info=(unsigned char *) NULL;
01195     }
01196   if (LocaleCompare(name,"iptc") == 0)
01197     {
01198       /*
01199         Continue to support deprecated IPTC profile for now.
01200       */
01201       image->iptc_profile.length=0;
01202       image->iptc_profile.info=(unsigned char *) NULL;
01203     }
01204   profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
01205     image->profiles,name);
01206   return(profile);
01207 }
01208 
01209 /*
01210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01211 %                                                                             %
01212 %                                                                             %
01213 %                                                                             %
01214 %   R e s e t P r o f i l e I t e r a t o r                                   %
01215 %                                                                             %
01216 %                                                                             %
01217 %                                                                             %
01218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01219 %
01220 %  ResetImageProfileIterator() resets the image profile iterator.  Use it in
01221 %  conjunction with GetNextImageProfile() to iterate over all the profiles
01222 %  associated with an image.
01223 %
01224 %  The format of the ResetImageProfileIterator method is:
01225 %
01226 %      ResetImageProfileIterator(Image *image)
01227 %
01228 %  A description of each parameter follows:
01229 %
01230 %    o image: the image.
01231 %
01232 */
01233 MagickExport void ResetImageProfileIterator(const Image *image)
01234 {
01235   assert(image != (Image *) NULL);
01236   assert(image->signature == MagickSignature);
01237   if (image->debug != MagickFalse)
01238     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01239   if (image->profiles == (SplayTreeInfo *) NULL)
01240     return;
01241   ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
01242 }
01243 
01244 /*
01245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01246 %                                                                             %
01247 %                                                                             %
01248 %                                                                             %
01249 %   S e t I m a g e P r o f i l e                                             %
01250 %                                                                             %
01251 %                                                                             %
01252 %                                                                             %
01253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01254 %
01255 %  SetImageProfile() adds a named profile to the image.  If a profile with the
01256 %  same name already exists, it is replaced.  This method differs from the
01257 %  ProfileImage() method in that it does not apply CMS color profiles.
01258 %
01259 %  The format of the SetImageProfile method is:
01260 %
01261 %      MagickBooleanType SetImageProfile(Image *image,const char *name,
01262 %        const StringInfo *profile)
01263 %
01264 %  A description of each parameter follows:
01265 %
01266 %    o image: the image.
01267 %
01268 %    o name: the profile name, for example icc, exif, and 8bim (8bim is the
01269 %      Photoshop wrapper for iptc profiles).
01270 %
01271 %    o profile: A StringInfo structure that contains the named profile.
01272 %
01273 */
01274 
01275 static void *DestroyProfile(void *profile)
01276 {
01277   return((void *) DestroyStringInfo((StringInfo *) profile));
01278 }
01279 
01280 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
01281   unsigned char *quantum)
01282 {
01283   *quantum=(*p++);
01284   return(p);
01285 }
01286 
01287 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
01288   const ssize_t count,unsigned char *quantum)
01289 {
01290   register ssize_t
01291     i;
01292 
01293   for (i=0; i < count; i++)
01294     *quantum++=(*p++);
01295   return(p);
01296 }
01297 
01298 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
01299   unsigned long *quantum)
01300 {
01301   *quantum=(unsigned long) (*p++ << 24);
01302   *quantum|=(unsigned long) (*p++ << 16);
01303   *quantum|=(unsigned long) (*p++ << 8);
01304   *quantum|=(unsigned long) (*p++ << 0);
01305   return(p);
01306 }
01307 
01308 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
01309   unsigned short *quantum)
01310 {
01311   *quantum=(unsigned short) (*p++ << 8);
01312   *quantum|=(unsigned short) (*p++ << 0);
01313   return(p);
01314 }
01315 
01316 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
01317   const StringInfo *resource_block)
01318 {
01319   const unsigned char
01320     *datum;
01321 
01322   register const unsigned char
01323     *p;
01324 
01325   size_t
01326     length;
01327 
01328   StringInfo
01329     *profile;
01330 
01331   unsigned char
01332     length_byte;
01333 
01334   unsigned long
01335     count;
01336 
01337   unsigned short
01338     id;
01339 
01340   datum=GetStringInfoDatum(resource_block);
01341   length=GetStringInfoLength(resource_block);
01342   for (p=datum; p < (datum+length-16); )
01343   {
01344     if (LocaleNCompare((char *) p,"8BIM",4) != 0)
01345       break;
01346     p+=4;
01347     p=ReadResourceShort(p,&id);
01348     p=ReadResourceByte(p,&length_byte);
01349     p+=length_byte;
01350     if (((length_byte+1) & 0x01) != 0)
01351       p++;
01352     if (p > (datum+length-4))
01353       break;
01354     p=ReadResourceLong(p,&count);
01355     if ((p > (datum+length-count)) || (count > length))
01356       break;
01357     switch (id)
01358     {
01359       case 0x03ed:
01360       {
01361         unsigned short
01362           resolution;
01363 
01364         /*
01365           Resolution.
01366         */
01367         p=ReadResourceShort(p,&resolution)+6;
01368         image->x_resolution=(double) resolution;
01369         p=ReadResourceShort(p,&resolution)+6;
01370         image->y_resolution=(double) resolution;
01371         break;
01372       }
01373       case 0x0404:
01374       {
01375         /*
01376           IPTC Profile
01377         */
01378         profile=AcquireStringInfo(count);
01379         SetStringInfoDatum(profile,p);
01380         (void) SetImageProfile(image,"iptc",profile);
01381         profile=DestroyStringInfo(profile);
01382         p+=count;
01383         break;
01384       }
01385       case 0x040c:
01386       {
01387         /*
01388           Thumbnail.
01389         */
01390         p+=count;
01391         break;
01392       }
01393       case 0x040f:
01394       {
01395         /*
01396           ICC Profile.
01397         */
01398         profile=AcquireStringInfo(count);
01399         SetStringInfoDatum(profile,p);
01400         (void) SetImageProfile(image,"icc",profile);
01401         profile=DestroyStringInfo(profile);
01402         p+=count;
01403         break;
01404       }
01405       case 0x0422:
01406       {
01407         /*
01408           EXIF Profile.
01409         */
01410         profile=AcquireStringInfo(count);
01411         SetStringInfoDatum(profile,p);
01412         (void) SetImageProfile(image,"exif",profile);
01413         profile=DestroyStringInfo(profile);
01414         p+=count;
01415         break;
01416       }
01417       case 0x0424:
01418       {
01419         /*
01420           XMP Profile.
01421         */
01422         profile=AcquireStringInfo(count);
01423         SetStringInfoDatum(profile,p);
01424         (void) SetImageProfile(image,"xmp",profile);
01425         profile=DestroyStringInfo(profile);
01426         p+=count;
01427         break;
01428       }
01429       default:
01430       {
01431         p+=count;
01432         break;
01433       }
01434     }
01435     if ((count & 0x01) != 0)
01436       p++;
01437   }
01438   return(MagickTrue);
01439 }
01440 
01441 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
01442   const StringInfo *profile)
01443 {
01444   char
01445     key[MaxTextExtent],
01446     property[MaxTextExtent];
01447 
01448   MagickBooleanType
01449     status;
01450 
01451   assert(image != (Image *) NULL);
01452   assert(image->signature == MagickSignature);
01453   if (image->debug != MagickFalse)
01454     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01455   if (image->profiles == (SplayTreeInfo *) NULL)
01456     image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
01457       DestroyProfile);
01458   (void) CopyMagickString(key,name,MaxTextExtent);
01459   status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
01460     ConstantString(key),CloneStringInfo(profile));
01461   if ((status != MagickFalse) &&
01462       ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
01463     {
01464       const StringInfo
01465         *icc_profile;
01466 
01467       /*
01468         Continue to support deprecated color profile member.
01469       */
01470       icc_profile=GetImageProfile(image,name);
01471       if (icc_profile != (const StringInfo *) NULL)
01472         {
01473           image->color_profile.length=GetStringInfoLength(icc_profile);
01474           image->color_profile.info=GetStringInfoDatum(icc_profile);
01475         }
01476     }
01477   if ((status != MagickFalse) &&
01478       ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
01479     {
01480       const StringInfo
01481         *iptc_profile;
01482 
01483       /*
01484         Continue to support deprecated IPTC profile member.
01485       */
01486       iptc_profile=GetImageProfile(image,name);
01487       if (iptc_profile != (const StringInfo *) NULL)
01488         {
01489           image->iptc_profile.length=GetStringInfoLength(iptc_profile);
01490           image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
01491         }
01492       (void) GetProfilesFromResourceBlock(image,profile);
01493     }
01494   /*
01495     Inject profile into image properties.
01496   */
01497   (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
01498   (void) GetImageProperty(image,property);
01499   return(status);
01500 }
01501 
01502 /*
01503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01504 %                                                                             %
01505 %                                                                             %
01506 %                                                                             %
01507 %   S y n c I m a g e P r o f i l e s                                         %
01508 %                                                                             %
01509 %                                                                             %
01510 %                                                                             %
01511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01512 %
01513 %  SyncImageProfiles() synchronizes image properties with the image profiles.
01514 %  Currently we only support updating the EXIF resolution and orientation.
01515 %
01516 %  The format of the SyncImageProfiles method is:
01517 %
01518 %      MagickBooleanType SyncImageProfiles(Image *image)
01519 %
01520 %  A description of each parameter follows:
01521 %
01522 %    o image: the image.
01523 %
01524 */
01525 
01526 static inline int ReadProfileByte(unsigned char **p,size_t *length)
01527 {
01528   int
01529     c;
01530 
01531   if (*length < 1)
01532     return(EOF);
01533   c=(int) (*(*p)++);
01534   (*length)--;
01535   return(c);
01536 }
01537 
01538 static inline unsigned short ReadProfileShort(const EndianType endian,
01539   unsigned char *buffer)
01540 {
01541   unsigned short
01542     value;
01543 
01544   if (endian == MSBEndian)
01545     {
01546       value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
01547         ((unsigned char *) buffer)[1]);
01548       return((unsigned short) (value & 0xffff));
01549     }
01550   value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
01551   return((unsigned short) (value & 0xffff));
01552 }
01553 
01554 static inline unsigned long ReadProfileLong(const EndianType endian,
01555   unsigned char *buffer)
01556 {
01557   unsigned long
01558     value;
01559 
01560   if (endian == MSBEndian)
01561     {
01562       value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
01563         (buffer[2] << 8) | buffer[3]);
01564       return((unsigned long) (value & 0xffffffff));
01565     }
01566   value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
01567     (buffer[1] << 8 ) | (buffer[0]));
01568   return((unsigned long) (value & 0xffffffff));
01569 }
01570 
01571 static inline void WriteProfileLong(const EndianType endian,
01572   const unsigned long value,unsigned char *p)
01573 {
01574   unsigned char
01575     buffer[4];
01576 
01577   if (endian == MSBEndian)
01578     {
01579       buffer[0]=(unsigned char) (value >> 24);
01580       buffer[1]=(unsigned char) (value >> 16);
01581       buffer[2]=(unsigned char) (value >> 8);
01582       buffer[3]=(unsigned char) value;
01583       (void) CopyMagickMemory(p,buffer,4);
01584       return;
01585     }
01586   buffer[0]=(unsigned char) value;
01587   buffer[1]=(unsigned char) (value >> 8);
01588   buffer[2]=(unsigned char) (value >> 16);
01589   buffer[3]=(unsigned char) (value >> 24);
01590   (void) CopyMagickMemory(p,buffer,4);
01591 }
01592 
01593 static void WriteProfileShort(const EndianType endian,
01594   const unsigned short value,unsigned char *p)
01595 {
01596   unsigned char
01597     buffer[2];
01598 
01599   if (endian == MSBEndian)
01600     {
01601       buffer[0]=(unsigned char) (value >> 8);
01602       buffer[1]=(unsigned char) value;
01603       (void) CopyMagickMemory(p,buffer,2);
01604       return;
01605     }
01606   buffer[0]=(unsigned char) value;
01607   buffer[1]=(unsigned char) (value >> 8);
01608   (void) CopyMagickMemory(p,buffer,2);
01609 }
01610 
01611 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
01612 {
01613 #define MaxDirectoryStack  16
01614 #define EXIF_DELIMITER  "\n"
01615 #define EXIF_NUM_FORMATS  12
01616 #define TAG_EXIF_OFFSET  0x8769
01617 #define TAG_INTEROP_OFFSET  0xa005
01618 
01619   typedef struct _DirectoryInfo
01620   {
01621     unsigned char
01622       *directory;
01623 
01624     unsigned long
01625       entry;
01626   } DirectoryInfo;
01627 
01628   DirectoryInfo
01629     directory_stack[MaxDirectoryStack];
01630 
01631   EndianType
01632     endian;
01633 
01634   long
01635     id,
01636     level;
01637 
01638   size_t
01639     length;
01640 
01641   ssize_t
01642     offset;
01643 
01644   static int
01645     format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
01646 
01647   StringInfo
01648     *profile;
01649 
01650   unsigned char
01651     *directory,
01652     *exif;
01653 
01654   unsigned long
01655     entry,
01656     number_entries;
01657 
01658   /*
01659     Set EXIF resolution tag.
01660   */
01661   profile=(StringInfo *) GetImageProfile(image,"EXIF");
01662   if (profile == (StringInfo *) NULL)
01663     return(MagickTrue);
01664   length=GetStringInfoLength(profile);
01665   exif=GetStringInfoDatum(profile);
01666   while (length != 0)
01667   {
01668     if (ReadProfileByte(&exif,&length) != 0x45)
01669       continue;
01670     if (ReadProfileByte(&exif,&length) != 0x78)
01671       continue;
01672     if (ReadProfileByte(&exif,&length) != 0x69)
01673       continue;
01674     if (ReadProfileByte(&exif,&length) != 0x66)
01675       continue;
01676     if (ReadProfileByte(&exif,&length) != 0x00)
01677       continue;
01678     if (ReadProfileByte(&exif,&length) != 0x00)
01679       continue;
01680     break;
01681   }
01682   if (length < 16)
01683     return(MagickFalse);
01684   id=(int) ReadProfileShort(LSBEndian,exif);
01685   endian=LSBEndian;
01686   if (id == 0x4949)
01687     endian=LSBEndian;
01688   else
01689     if (id == 0x4D4D)
01690       endian=MSBEndian;
01691     else
01692       return(MagickFalse);
01693   if (ReadProfileShort(endian,exif+2) != 0x002a)
01694     return(MagickFalse);
01695   /*
01696     This the offset to the first IFD.
01697   */
01698   offset=(ssize_t) ReadProfileLong(endian,exif+4);
01699   if ((size_t) offset >= length)
01700     return(MagickFalse);
01701   directory=exif+offset;
01702   level=0;
01703   entry=0;
01704   do
01705   {
01706     if (level > 0)
01707       {
01708         level--;
01709         directory=directory_stack[level].directory;
01710         entry=directory_stack[level].entry;
01711       }
01712     /*
01713       Determine how many entries there are in the current IFD.
01714     */
01715     number_entries=ReadProfileShort(endian,directory);
01716     for ( ; entry < number_entries; entry++)
01717     {
01718       long
01719         components,
01720         format,
01721         tag_value;
01722 
01723       register unsigned char
01724         *p,
01725         *q;
01726 
01727       size_t
01728         number_bytes;
01729 
01730       q=(unsigned char *) (directory+2+(12*entry));
01731       tag_value=(long) ReadProfileShort(endian,q);
01732       format=(long) ReadProfileShort(endian,q+2);
01733       if ((format-1) >= EXIF_NUM_FORMATS)
01734         break;
01735       components=(long) ReadProfileLong(endian,q+4);
01736       number_bytes=(size_t) components*format_bytes[format];
01737       if (number_bytes <= 4)
01738         p=q+8;
01739       else
01740         {
01741           ssize_t
01742             offset;
01743 
01744           /*
01745             The directory entry contains an offset.
01746           */
01747           offset=(ssize_t) ReadProfileLong(endian,q+8);
01748           if ((size_t) (offset+number_bytes) > length)
01749             continue;
01750           p=(unsigned char *) (exif+offset);
01751         }
01752       switch (tag_value)
01753       {
01754         case 0x011a:
01755         {
01756           (void) WriteProfileLong(endian,(unsigned long)
01757             (image->x_resolution+0.5),p);
01758           (void) WriteProfileLong(endian,1UL,p+4);
01759           break;
01760         }
01761         case 0x011b:
01762         {
01763           (void) WriteProfileLong(endian,(unsigned long)
01764             (image->y_resolution+0.5),p);
01765           (void) WriteProfileLong(endian,1UL,p+4);
01766           break;
01767         }
01768         case 0x0112:
01769         {
01770           (void) WriteProfileShort(endian,(unsigned short)
01771             image->orientation,p);
01772           (void) WriteProfileLong(endian,1UL,p+4);
01773           break;
01774         }
01775         case 0x0128:
01776         {
01777           (void) WriteProfileShort(endian,(unsigned short)
01778             (image->units+1),p);
01779           break;
01780         }
01781         default:
01782           break;
01783       }
01784       if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
01785         {
01786           size_t
01787             offset;
01788 
01789           offset=(size_t) ReadProfileLong(endian,p);
01790           if ((offset < length) && (level < (MaxDirectoryStack-2)))
01791             {
01792               directory_stack[level].directory=directory;
01793               entry++;
01794               directory_stack[level].entry=entry;
01795               level++;
01796               directory_stack[level].directory=exif+offset;
01797               directory_stack[level].entry=0;
01798               level++;
01799               if ((directory+2+(12*number_entries)) > (exif+length))
01800                 break;
01801               offset=(size_t) ReadProfileLong(endian,directory+2+(12*
01802                 number_entries));
01803               if ((offset != 0) && (offset < length) &&
01804                   (level < (MaxDirectoryStack-2)))
01805                 {
01806                   directory_stack[level].directory=exif+offset;
01807                   directory_stack[level].entry=0;
01808                   level++;
01809                 }
01810             }
01811           break;
01812         }
01813     }
01814   } while (level > 0);
01815   return(MagickTrue);
01816 }

Generated on Thu Jul 2 12:03:21 2009 for MagickCore by  doxygen 1.5.8