|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % IIIII DDDD EEEEE N N TTTTT IIIII FFFFF Y Y % 00007 % I D D E NN N T I F Y Y % 00008 % I D D EEE N N N T I FFF Y % 00009 % I D D E N NN T I F Y % 00010 % IIIII DDDD EEEEE N N T IIIII F Y % 00011 % % 00012 % % 00013 % Identify an Image Format and Characteristics. % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % September 1994 % 00018 % % 00019 % % 00020 % Copyright 1999-2008 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 % Identify describes the format and characteristics of one or more image 00037 % files. It will also report if an image is incomplete or corrupt. 00038 % 00039 % 00040 */ 00041 00042 /* 00043 Include declarations. 00044 */ 00045 #include "MagickCore/studio.h" 00046 #include "MagickCore/annotate.h" 00047 #include "MagickCore/artifact.h" 00048 #include "MagickCore/attribute.h" 00049 #include "MagickCore/blob.h" 00050 #include "MagickCore/cache.h" 00051 #include "MagickCore/client.h" 00052 #include "MagickCore/coder.h" 00053 #include "MagickCore/color.h" 00054 #include "MagickCore/configure.h" 00055 #include "MagickCore/constitute.h" 00056 #include "MagickCore/decorate.h" 00057 #include "MagickCore/delegate.h" 00058 #include "MagickCore/draw.h" 00059 #include "MagickCore/effect.h" 00060 #include "MagickCore/exception.h" 00061 #include "MagickCore/exception-private.h" 00062 #include "MagickCore/feature.h" 00063 #include "MagickCore/gem.h" 00064 #include "MagickCore/geometry.h" 00065 #include "MagickCore/histogram.h" 00066 #include "MagickCore/identify.h" 00067 #include "MagickCore/image.h" 00068 #include "MagickCore/image-private.h" 00069 #include "MagickCore/list.h" 00070 #include "MagickCore/locale_.h" 00071 #include "MagickCore/log.h" 00072 #include "MagickCore/magic.h" 00073 #include "MagickCore/magick.h" 00074 #include "MagickCore/memory_.h" 00075 #include "MagickCore/module.h" 00076 #include "MagickCore/monitor.h" 00077 #include "MagickCore/montage.h" 00078 #include "MagickCore/option.h" 00079 #include "MagickCore/pixel-accessor.h" 00080 #include "MagickCore/prepress.h" 00081 #include "MagickCore/profile.h" 00082 #include "MagickCore/property.h" 00083 #include "MagickCore/quantize.h" 00084 #include "MagickCore/quantum.h" 00085 #include "MagickCore/random_.h" 00086 #include "MagickCore/registry.h" 00087 #include "MagickCore/resize.h" 00088 #include "MagickCore/resource_.h" 00089 #include "MagickCore/signature.h" 00090 #include "MagickCore/statistic.h" 00091 #include "MagickCore/string_.h" 00092 #include "MagickCore/string-private.h" 00093 #include "MagickCore/timer.h" 00094 #include "MagickCore/utility.h" 00095 #include "MagickCore/utility-private.h" 00096 #include "MagickCore/version.h" 00097 #if defined(MAGICKCORE_LCMS_DELEGATE) 00098 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H) 00099 #include <lcms/lcms2.h> 00100 #elif defined(MAGICKCORE_HAVE_LCMS2_H) 00101 #include "lcms2.h" 00102 #elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H) 00103 #include <lcms/lcms.h> 00104 #else 00105 #include "lcms.h" 00106 #endif 00107 #endif 00108 00109 /* 00110 Define declarations. 00111 */ 00112 #if defined(MAGICKCORE_LCMS_DELEGATE) 00113 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000) 00114 #define cmsUInt32Number DWORD 00115 #endif 00116 #endif 00117 00118 /* 00119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00120 % % 00121 % % 00122 % % 00123 % I d e n t i f y I m a g e % 00124 % % 00125 % % 00126 % % 00127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00128 % 00129 % IdentifyImage() identifies an image by printing its attributes to the file. 00130 % Attributes include the image width, height, size, and others. 00131 % 00132 % The format of the IdentifyImage method is: 00133 % 00134 % MagickBooleanType IdentifyImage(Image *image,FILE *file, 00135 % const MagickBooleanType verbose,ExceptionInfo *exception) 00136 % 00137 % A description of each parameter follows: 00138 % 00139 % o image: the image. 00140 % 00141 % o file: the file, typically stdout. 00142 % 00143 % o verbose: A value other than zero prints more detailed information 00144 % about the image. 00145 % 00146 % o exception: return any errors or warnings in this structure. 00147 % 00148 */ 00149 00150 static ssize_t PrintChannelFeatures(FILE *file,const PixelChannel channel, 00151 const char *name,const ChannelFeatures *channel_features) 00152 { 00153 #define PrintFeature(feature) \ 00154 GetMagickPrecision(),(feature)[0], \ 00155 GetMagickPrecision(),(feature)[1], \ 00156 GetMagickPrecision(),(feature)[2], \ 00157 GetMagickPrecision(),(feature)[3], \ 00158 GetMagickPrecision(),((feature)[0]+(feature)[1]+(feature)[2]+(feature)[3])/4.0 \ 00159 00160 #define FeaturesFormat " %s:\n" \ 00161 " Angular Second Moment:\n" \ 00162 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00163 " Contrast:\n" \ 00164 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00165 " Correlation:\n" \ 00166 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00167 " Sum of Squares: Variance:\n" \ 00168 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00169 " Inverse Difference Moment:\n" \ 00170 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00171 " Sum Average:\n" \ 00172 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00173 " Sum Variance:\n" \ 00174 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00175 " Sum Entropy:\n" \ 00176 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00177 " Entropy:\n" \ 00178 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00179 " Difference Variance:\n" \ 00180 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00181 " Difference Entropy:\n" \ 00182 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00183 " Information Measure of Correlation 1:\n" \ 00184 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00185 " Information Measure of Correlation 2:\n" \ 00186 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \ 00187 " Maximum Correlation Coefficient:\n" \ 00188 " %.*g, %.*g, %.*g, %.*g, %.*g\n" 00189 00190 ssize_t 00191 n; 00192 00193 n=FormatLocaleFile(file,FeaturesFormat,name, 00194 PrintFeature(channel_features[channel].angular_second_moment), 00195 PrintFeature(channel_features[channel].contrast), 00196 PrintFeature(channel_features[channel].correlation), 00197 PrintFeature(channel_features[channel].variance_sum_of_squares), 00198 PrintFeature(channel_features[channel].inverse_difference_moment), 00199 PrintFeature(channel_features[channel].sum_average), 00200 PrintFeature(channel_features[channel].sum_variance), 00201 PrintFeature(channel_features[channel].sum_entropy), 00202 PrintFeature(channel_features[channel].entropy), 00203 PrintFeature(channel_features[channel].difference_variance), 00204 PrintFeature(channel_features[channel].difference_entropy), 00205 PrintFeature(channel_features[channel].measure_of_correlation_1), 00206 PrintFeature(channel_features[channel].measure_of_correlation_2), 00207 PrintFeature(channel_features[channel].maximum_correlation_coefficient)); 00208 return(n); 00209 } 00210 00211 static ssize_t PrintChannelStatistics(FILE *file,const PixelChannel channel, 00212 const char *name,const double scale, 00213 const ChannelStatistics *channel_statistics) 00214 { 00215 #define StatisticsFormat " %s:\n min: " QuantumFormat \ 00216 " (%g)\n max: " QuantumFormat " (%g)\n" \ 00217 " mean: %g (%g)\n standard deviation: %g (%g)\n" \ 00218 " kurtosis: %g\n skewness: %g\n" 00219 00220 ssize_t 00221 n; 00222 00223 n=FormatLocaleFile(file,StatisticsFormat,name,ClampToQuantum(scale* 00224 channel_statistics[channel].minima),channel_statistics[channel].minima/ 00225 (double) QuantumRange,ClampToQuantum(scale* 00226 channel_statistics[channel].maxima),channel_statistics[channel].maxima/ 00227 (double) QuantumRange,scale*channel_statistics[channel].mean, 00228 channel_statistics[channel].mean/(double) QuantumRange,scale* 00229 channel_statistics[channel].standard_deviation, 00230 channel_statistics[channel].standard_deviation/(double) QuantumRange, 00231 channel_statistics[channel].kurtosis,channel_statistics[channel].skewness); 00232 return(n); 00233 } 00234 00235 MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file, 00236 const MagickBooleanType verbose,ExceptionInfo *exception) 00237 { 00238 char 00239 color[MaxTextExtent], 00240 format[MaxTextExtent], 00241 key[MaxTextExtent]; 00242 00243 ChannelFeatures 00244 *channel_features; 00245 00246 ChannelStatistics 00247 *channel_statistics; 00248 00249 ColorspaceType 00250 colorspace; 00251 00252 const char 00253 *artifact, 00254 *name, 00255 *property, 00256 *registry, 00257 *value; 00258 00259 const MagickInfo 00260 *magick_info; 00261 00262 double 00263 elapsed_time, 00264 user_time; 00265 00266 ImageType 00267 type; 00268 00269 MagickBooleanType 00270 ping; 00271 00272 register const Quantum 00273 *p; 00274 00275 register ssize_t 00276 i, 00277 x; 00278 00279 size_t 00280 distance, 00281 scale; 00282 00283 ssize_t 00284 y; 00285 00286 assert(image != (Image *) NULL); 00287 assert(image->signature == MagickSignature); 00288 if (image->debug != MagickFalse) 00289 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00290 if (file == (FILE *) NULL) 00291 file=stdout; 00292 *format='\0'; 00293 elapsed_time=GetElapsedTime(&image->timer); 00294 user_time=GetUserTime(&image->timer); 00295 GetTimerInfo(&image->timer); 00296 if (verbose == MagickFalse) 00297 { 00298 /* 00299 Display summary info about the image. 00300 */ 00301 if (*image->magick_filename != '\0') 00302 if (LocaleCompare(image->magick_filename,image->filename) != 0) 00303 (void) FormatLocaleFile(file,"%s=>",image->magick_filename); 00304 if ((GetPreviousImageInList(image) == (Image *) NULL) && 00305 (GetNextImageInList(image) == (Image *) NULL) && 00306 (image->scene == 0)) 00307 (void) FormatLocaleFile(file,"%s ",image->filename); 00308 else 00309 (void) FormatLocaleFile(file,"%s[%.20g] ",image->filename,(double) 00310 image->scene); 00311 (void) FormatLocaleFile(file,"%s ",image->magick); 00312 if ((image->magick_columns != 0) || (image->magick_rows != 0)) 00313 if ((image->magick_columns != image->columns) || 00314 (image->magick_rows != image->rows)) 00315 (void) FormatLocaleFile(file,"%.20gx%.20g=>",(double) 00316 image->magick_columns,(double) image->magick_rows); 00317 (void) FormatLocaleFile(file,"%.20gx%.20g ",(double) image->columns, 00318 (double) image->rows); 00319 if ((image->page.width != 0) || (image->page.height != 0) || 00320 (image->page.x != 0) || (image->page.y != 0)) 00321 (void) FormatLocaleFile(file,"%.20gx%.20g%+.20g%+.20g ",(double) 00322 image->page.width,(double) image->page.height,(double) image->page.x, 00323 (double) image->page.y); 00324 (void) FormatLocaleFile(file,"%.20g-bit ",(double) image->depth); 00325 if (image->type != UndefinedType) 00326 (void) FormatLocaleFile(file,"%s ",CommandOptionToMnemonic( 00327 MagickTypeOptions,(ssize_t) image->type)); 00328 if (image->storage_class == DirectClass) 00329 { 00330 (void) FormatLocaleFile(file,"DirectClass "); 00331 if (image->total_colors != 0) 00332 { 00333 (void) FormatMagickSize(image->total_colors,MagickFalse,format); 00334 (void) FormatLocaleFile(file,"%s ",format); 00335 } 00336 } 00337 else 00338 if (image->total_colors <= image->colors) 00339 (void) FormatLocaleFile(file,"PseudoClass %.20gc ",(double) 00340 image->colors); 00341 else 00342 (void) FormatLocaleFile(file,"PseudoClass %.20g=>%.20gc ",(double) 00343 image->total_colors,(double) image->colors); 00344 if (image->error.mean_error_per_pixel != 0.0) 00345 (void) FormatLocaleFile(file,"%.20g/%f/%fdb ",(double) 00346 (image->error.mean_error_per_pixel+0.5), 00347 image->error.normalized_mean_error, 00348 image->error.normalized_maximum_error); 00349 if (GetBlobSize(image) != 0) 00350 { 00351 (void) FormatMagickSize(GetBlobSize(image),MagickFalse,format); 00352 (void) FormatLocaleFile(file,"%s ",format); 00353 } 00354 (void) FormatLocaleFile(file,"%0.3fu %lu:%02lu.%03lu",user_time, 00355 (unsigned long) (elapsed_time/60.0),(unsigned long) floor(fmod( 00356 elapsed_time,60.0)),(unsigned long) (1000.0*(elapsed_time- 00357 floor(elapsed_time)))); 00358 (void) FormatLocaleFile(file,"\n"); 00359 (void) fflush(file); 00360 return(ferror(file) != 0 ? MagickFalse : MagickTrue); 00361 } 00362 /* 00363 Display verbose info about the image. 00364 */ 00365 p=GetVirtualPixels(image,0,0,1,1,exception); 00366 ping=p == (const Quantum *) NULL ? MagickTrue : MagickFalse; 00367 type=GetImageType(image,exception); 00368 (void) SignatureImage(image,exception); 00369 (void) FormatLocaleFile(file,"Image: %s\n",image->filename); 00370 if (*image->magick_filename != '\0') 00371 if (LocaleCompare(image->magick_filename,image->filename) != 0) 00372 { 00373 char 00374 filename[MaxTextExtent]; 00375 00376 GetPathComponent(image->magick_filename,TailPath,filename); 00377 (void) FormatLocaleFile(file," Base filename: %s\n",filename); 00378 } 00379 magick_info=GetMagickInfo(image->magick,exception); 00380 if ((magick_info == (const MagickInfo *) NULL) || 00381 (*GetMagickDescription(magick_info) == '\0')) 00382 (void) FormatLocaleFile(file," Format: %s\n",image->magick); 00383 else 00384 (void) FormatLocaleFile(file," Format: %s (%s)\n",image->magick, 00385 GetMagickDescription(magick_info)); 00386 (void) FormatLocaleFile(file," Class: %s\n",CommandOptionToMnemonic( 00387 MagickClassOptions,(ssize_t) image->storage_class)); 00388 (void) FormatLocaleFile(file," Geometry: %.20gx%.20g%+.20g%+.20g\n",(double) 00389 image->columns,(double) image->rows,(double) image->tile_offset.x,(double) 00390 image->tile_offset.y); 00391 if ((image->magick_columns != 0) || (image->magick_rows != 0)) 00392 if ((image->magick_columns != image->columns) || 00393 (image->magick_rows != image->rows)) 00394 (void) FormatLocaleFile(file," Base geometry: %.20gx%.20g\n",(double) 00395 image->magick_columns,(double) image->magick_rows); 00396 if ((image->resolution.x != 0.0) && (image->resolution.y != 0.0)) 00397 { 00398 (void) FormatLocaleFile(file," Resolution: %gx%g\n",image->resolution.x, 00399 image->resolution.y); 00400 (void) FormatLocaleFile(file," Print size: %gx%g\n",(double) 00401 image->columns/image->resolution.x,(double) image->rows/ 00402 image->resolution.y); 00403 } 00404 (void) FormatLocaleFile(file," Units: %s\n",CommandOptionToMnemonic( 00405 MagickResolutionOptions,(ssize_t) image->units)); 00406 (void) FormatLocaleFile(file," Type: %s\n",CommandOptionToMnemonic( 00407 MagickTypeOptions,(ssize_t) type)); 00408 if (image->type != UndefinedType) 00409 (void) FormatLocaleFile(file," Base type: %s\n",CommandOptionToMnemonic( 00410 MagickTypeOptions,(ssize_t) image->type)); 00411 (void) FormatLocaleFile(file," Endianess: %s\n",CommandOptionToMnemonic( 00412 MagickEndianOptions,(ssize_t) image->endian)); 00413 /* 00414 Detail channel depth and extrema. 00415 */ 00416 (void) FormatLocaleFile(file," Colorspace: %s\n",CommandOptionToMnemonic( 00417 MagickColorspaceOptions,(ssize_t) image->colorspace)); 00418 channel_statistics=(ChannelStatistics *) NULL; 00419 channel_features=(ChannelFeatures *) NULL; 00420 colorspace=image->colorspace; 00421 scale=1; 00422 if (ping == MagickFalse) 00423 { 00424 size_t 00425 depth; 00426 00427 channel_statistics=GetImageStatistics(image,exception); 00428 artifact=GetImageArtifact(image,"identify:features"); 00429 if (artifact != (const char *) NULL) 00430 { 00431 distance=StringToUnsignedLong(artifact); 00432 channel_features=GetImageFeatures(image,distance,exception); 00433 } 00434 depth=GetImageDepth(image,exception); 00435 if (image->depth == depth) 00436 (void) FormatLocaleFile(file," Depth: %.20g-bit\n",(double) 00437 image->depth); 00438 else 00439 (void) FormatLocaleFile(file," Depth: %.20g/%.20g-bit\n",(double) 00440 image->depth,(double) depth); 00441 (void) FormatLocaleFile(file," Channel depth:\n"); 00442 if (IsImageGray(image,exception) != MagickFalse) 00443 colorspace=GRAYColorspace; 00444 switch (colorspace) 00445 { 00446 case RGBColorspace: 00447 default: 00448 { 00449 (void) FormatLocaleFile(file," red: %.20g-bit\n",(double) 00450 channel_statistics[RedPixelChannel].depth); 00451 (void) FormatLocaleFile(file," green: %.20g-bit\n",(double) 00452 channel_statistics[GreenPixelChannel].depth); 00453 (void) FormatLocaleFile(file," blue: %.20g-bit\n",(double) 00454 channel_statistics[BluePixelChannel].depth); 00455 break; 00456 } 00457 case CMYKColorspace: 00458 { 00459 (void) FormatLocaleFile(file," cyan: %.20g-bit\n",(double) 00460 channel_statistics[CyanPixelChannel].depth); 00461 (void) FormatLocaleFile(file," magenta: %.20g-bit\n",(double) 00462 channel_statistics[MagentaPixelChannel].depth); 00463 (void) FormatLocaleFile(file," yellow: %.20g-bit\n",(double) 00464 channel_statistics[YellowPixelChannel].depth); 00465 (void) FormatLocaleFile(file," black: %.20g-bit\n",(double) 00466 channel_statistics[BlackPixelChannel].depth); 00467 break; 00468 } 00469 case GRAYColorspace: 00470 { 00471 (void) FormatLocaleFile(file," gray: %.20g-bit\n",(double) 00472 channel_statistics[GrayPixelChannel].depth); 00473 break; 00474 } 00475 } 00476 if (image->matte != MagickFalse) 00477 (void) FormatLocaleFile(file," alpha: %.20g-bit\n",(double) 00478 channel_statistics[AlphaPixelChannel].depth); 00479 scale=1; 00480 if (image->depth <= MAGICKCORE_QUANTUM_DEPTH) 00481 scale=QuantumRange/((size_t) QuantumRange >> ((size_t) 00482 MAGICKCORE_QUANTUM_DEPTH-image->depth)); 00483 } 00484 if (channel_statistics != (ChannelStatistics *) NULL) 00485 { 00486 (void) FormatLocaleFile(file," Channel statistics:\n"); 00487 switch (colorspace) 00488 { 00489 case RGBColorspace: 00490 default: 00491 { 00492 (void) PrintChannelStatistics(file,RedPixelChannel,"Red",1.0/ 00493 scale,channel_statistics); 00494 (void) PrintChannelStatistics(file,GreenPixelChannel,"Green",1.0/ 00495 scale,channel_statistics); 00496 (void) PrintChannelStatistics(file,BluePixelChannel,"Blue",1.0/ 00497 scale,channel_statistics); 00498 break; 00499 } 00500 case CMYKColorspace: 00501 { 00502 (void) PrintChannelStatistics(file,CyanPixelChannel,"Cyan",1.0/ 00503 scale,channel_statistics); 00504 (void) PrintChannelStatistics(file,MagentaPixelChannel,"Magenta",1.0/ 00505 scale,channel_statistics); 00506 (void) PrintChannelStatistics(file,YellowPixelChannel,"Yellow",1.0/ 00507 scale,channel_statistics); 00508 (void) PrintChannelStatistics(file,BlackPixelChannel,"Black",1.0/ 00509 scale,channel_statistics); 00510 break; 00511 } 00512 case GRAYColorspace: 00513 { 00514 (void) PrintChannelStatistics(file,GrayPixelChannel,"Gray",1.0/ 00515 scale,channel_statistics); 00516 break; 00517 } 00518 } 00519 if (image->matte != MagickFalse) 00520 (void) PrintChannelStatistics(file,AlphaPixelChannel,"Alpha",1.0/ 00521 scale,channel_statistics); 00522 if (colorspace != GRAYColorspace) 00523 { 00524 (void) FormatLocaleFile(file," Image statistics:\n"); 00525 (void) PrintChannelStatistics(file,(PixelChannel) MaxPixelChannels, 00526 "Overall",1.0/scale,channel_statistics); 00527 } 00528 channel_statistics=(ChannelStatistics *) RelinquishMagickMemory( 00529 channel_statistics); 00530 } 00531 if (channel_features != (ChannelFeatures *) NULL) 00532 { 00533 (void) FormatLocaleFile(file," Channel features (horizontal, vertical, " 00534 "left and right diagonals, average):\n"); 00535 switch (colorspace) 00536 { 00537 case RGBColorspace: 00538 default: 00539 { 00540 (void) PrintChannelFeatures(file,RedPixelChannel,"Red", 00541 channel_features); 00542 (void) PrintChannelFeatures(file,GreenPixelChannel,"Green", 00543 channel_features); 00544 (void) PrintChannelFeatures(file,BluePixelChannel,"Blue", 00545 channel_features); 00546 break; 00547 } 00548 case CMYKColorspace: 00549 { 00550 (void) PrintChannelFeatures(file,CyanPixelChannel,"Cyan", 00551 channel_features); 00552 (void) PrintChannelFeatures(file,MagentaPixelChannel,"Magenta", 00553 channel_features); 00554 (void) PrintChannelFeatures(file,YellowPixelChannel,"Yellow", 00555 channel_features); 00556 (void) PrintChannelFeatures(file,BlackPixelChannel,"Black", 00557 channel_features); 00558 break; 00559 } 00560 case GRAYColorspace: 00561 { 00562 (void) PrintChannelFeatures(file,GrayPixelChannel,"Gray", 00563 channel_features); 00564 break; 00565 } 00566 } 00567 if (image->matte != MagickFalse) 00568 (void) PrintChannelFeatures(file,AlphaPixelChannel,"Alpha", 00569 channel_features); 00570 channel_features=(ChannelFeatures *) RelinquishMagickMemory( 00571 channel_features); 00572 } 00573 if (ping == MagickFalse) 00574 { 00575 if (image->colorspace == CMYKColorspace) 00576 (void) FormatLocaleFile(file," Total ink density: %.0f%%\n",100.0* 00577 GetImageTotalInkDensity(image,exception)/(double) QuantumRange); 00578 x=0; 00579 if (image->matte != MagickFalse) 00580 { 00581 register const Quantum 00582 *p; 00583 00584 p=(const Quantum *) NULL; 00585 for (y=0; y < (ssize_t) image->rows; y++) 00586 { 00587 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 00588 if (p == (const Quantum *) NULL) 00589 break; 00590 for (x=0; x < (ssize_t) image->columns; x++) 00591 { 00592 if (GetPixelAlpha(image,p) == (Quantum) TransparentAlpha) 00593 break; 00594 p+=GetPixelChannels(image); 00595 } 00596 if (x < (ssize_t) image->columns) 00597 break; 00598 } 00599 if ((x < (ssize_t) image->columns) || (y < (ssize_t) image->rows)) 00600 { 00601 char 00602 tuple[MaxTextExtent]; 00603 00604 PixelInfo 00605 pixel; 00606 00607 GetPixelInfo(image,&pixel); 00608 GetPixelInfoPixel(image,p,&pixel); 00609 (void) QueryColorname(image,&pixel,SVGCompliance,tuple, 00610 exception); 00611 (void) FormatLocaleFile(file," Alpha: %s ",tuple); 00612 GetColorTuple(&pixel,MagickTrue,tuple); 00613 (void) FormatLocaleFile(file," %s\n",tuple); 00614 } 00615 } 00616 artifact=GetImageArtifact(image,"identify:unique-colors"); 00617 if (IsHistogramImage(image,exception) != MagickFalse) 00618 { 00619 (void) FormatLocaleFile(file," Colors: %.20g\n",(double) 00620 GetNumberColors(image,(FILE *) NULL,exception)); 00621 (void) FormatLocaleFile(file," Histogram:\n"); 00622 (void) GetNumberColors(image,file,exception); 00623 } 00624 else 00625 if ((artifact != (const char *) NULL) && 00626 (IsMagickTrue(artifact) != MagickFalse)) 00627 (void) FormatLocaleFile(file," Colors: %.20g\n",(double) 00628 GetNumberColors(image,(FILE *) NULL,exception)); 00629 } 00630 if (image->storage_class == PseudoClass) 00631 { 00632 (void) FormatLocaleFile(file," Colormap: %.20g\n",(double) 00633 image->colors); 00634 if (image->colors <= 1024) 00635 { 00636 char 00637 color[MaxTextExtent], 00638 hex[MaxTextExtent], 00639 tuple[MaxTextExtent]; 00640 00641 PixelInfo 00642 pixel; 00643 00644 register PixelInfo 00645 *restrict p; 00646 00647 GetPixelInfo(image,&pixel); 00648 p=image->colormap; 00649 for (i=0; i < (ssize_t) image->colors; i++) 00650 { 00651 pixel=(*p); 00652 (void) CopyMagickString(tuple,"(",MaxTextExtent); 00653 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance, 00654 tuple); 00655 (void) ConcatenateMagickString(tuple,",",MaxTextExtent); 00656 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance, 00657 tuple); 00658 (void) ConcatenateMagickString(tuple,",",MaxTextExtent); 00659 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance, 00660 tuple); 00661 if (pixel.colorspace == CMYKColorspace) 00662 { 00663 (void) ConcatenateMagickString(tuple,",",MaxTextExtent); 00664 ConcatenateColorComponent(&pixel,BlackPixelChannel, 00665 X11Compliance,tuple); 00666 } 00667 if (pixel.matte != MagickFalse) 00668 { 00669 (void) ConcatenateMagickString(tuple,",",MaxTextExtent); 00670 ConcatenateColorComponent(&pixel,AlphaPixelChannel, 00671 X11Compliance,tuple); 00672 } 00673 (void) ConcatenateMagickString(tuple,")",MaxTextExtent); 00674 (void) QueryColorname(image,&pixel,SVGCompliance,color, 00675 exception); 00676 GetColorTuple(&pixel,MagickTrue,hex); 00677 (void) FormatLocaleFile(file," %8ld: %s %s %s\n",(long) i,tuple, 00678 hex,color); 00679 p++; 00680 } 00681 } 00682 } 00683 if (image->error.mean_error_per_pixel != 0.0) 00684 (void) FormatLocaleFile(file," Mean error per pixel: %g\n", 00685 image->error.mean_error_per_pixel); 00686 if (image->error.normalized_mean_error != 0.0) 00687 (void) FormatLocaleFile(file," Normalized mean error: %g\n", 00688 image->error.normalized_mean_error); 00689 if (image->error.normalized_maximum_error != 0.0) 00690 (void) FormatLocaleFile(file," Normalized maximum error: %g\n", 00691 image->error.normalized_maximum_error); 00692 (void) FormatLocaleFile(file," Rendering intent: %s\n", 00693 CommandOptionToMnemonic(MagickIntentOptions,(ssize_t) 00694 image->rendering_intent)); 00695 if (image->gamma != 0.0) 00696 (void) FormatLocaleFile(file," Gamma: %g\n",image->gamma); 00697 if ((image->chromaticity.red_primary.x != 0.0) || 00698 (image->chromaticity.green_primary.x != 0.0) || 00699 (image->chromaticity.blue_primary.x != 0.0) || 00700 (image->chromaticity.white_point.x != 0.0)) 00701 { 00702 /* 00703 Display image chromaticity. 00704 */ 00705 (void) FormatLocaleFile(file," Chromaticity:\n"); 00706 (void) FormatLocaleFile(file," red primary: (%g,%g)\n", 00707 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y); 00708 (void) FormatLocaleFile(file," green primary: (%g,%g)\n", 00709 image->chromaticity.green_primary.x, 00710 image->chromaticity.green_primary.y); 00711 (void) FormatLocaleFile(file," blue primary: (%g,%g)\n", 00712 image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y); 00713 (void) FormatLocaleFile(file," white point: (%g,%g)\n", 00714 image->chromaticity.white_point.x,image->chromaticity.white_point.y); 00715 } 00716 if ((image->extract_info.width*image->extract_info.height) != 0) 00717 (void) FormatLocaleFile(file," Tile geometry: %.20gx%.20g%+.20g%+.20g\n", 00718 (double) image->extract_info.width,(double) image->extract_info.height, 00719 (double) image->extract_info.x,(double) image->extract_info.y); 00720 (void) FormatLocaleFile(file," Interlace: %s\n",CommandOptionToMnemonic( 00721 MagickInterlaceOptions,(ssize_t) image->interlace)); 00722 (void) QueryColorname(image,&image->background_color,SVGCompliance,color, 00723 exception); 00724 (void) FormatLocaleFile(file," Background color: %s\n",color); 00725 (void) QueryColorname(image,&image->border_color,SVGCompliance,color, 00726 exception); 00727 (void) FormatLocaleFile(file," Border color: %s\n",color); 00728 (void) QueryColorname(image,&image->matte_color,SVGCompliance,color, 00729 exception); 00730 (void) FormatLocaleFile(file," Matte color: %s\n",color); 00731 (void) QueryColorname(image,&image->transparent_color,SVGCompliance,color, 00732 exception); 00733 (void) FormatLocaleFile(file," Transparent color: %s\n",color); 00734 (void) FormatLocaleFile(file," Compose: %s\n",CommandOptionToMnemonic( 00735 MagickComposeOptions,(ssize_t) image->compose)); 00736 if ((image->page.width != 0) || (image->page.height != 0) || 00737 (image->page.x != 0) || (image->page.y != 0)) 00738 (void) FormatLocaleFile(file," Page geometry: %.20gx%.20g%+.20g%+.20g\n", 00739 (double) image->page.width,(double) image->page.height,(double) 00740 image->page.x,(double) image->page.y); 00741 if ((image->page.x != 0) || (image->page.y != 0)) 00742 (void) FormatLocaleFile(file," Origin geometry: %+.20g%+.20g\n",(double) 00743 image->page.x,(double) image->page.y); 00744 (void) FormatLocaleFile(file," Dispose: %s\n",CommandOptionToMnemonic( 00745 MagickDisposeOptions,(ssize_t) image->dispose)); 00746 if (image->delay != 0) 00747 (void) FormatLocaleFile(file," Delay: %.20gx%.20g\n",(double) image->delay, 00748 (double) image->ticks_per_second); 00749 if (image->iterations != 1) 00750 (void) FormatLocaleFile(file," Iterations: %.20g\n",(double) 00751 image->iterations); 00752 if ((image->next != (Image *) NULL) || (image->previous != (Image *) NULL)) 00753 (void) FormatLocaleFile(file," Scene: %.20g of %.20g\n",(double) 00754 image->scene,(double) GetImageListLength(image)); 00755 else 00756 if (image->scene != 0) 00757 (void) FormatLocaleFile(file," Scene: %.20g\n",(double) image->scene); 00758 (void) FormatLocaleFile(file," Compression: %s\n",CommandOptionToMnemonic( 00759 MagickCompressOptions,(ssize_t) image->compression)); 00760 if (image->quality != UndefinedCompressionQuality) 00761 (void) FormatLocaleFile(file," Quality: %.20g\n",(double) image->quality); 00762 (void) FormatLocaleFile(file," Orientation: %s\n",CommandOptionToMnemonic( 00763 MagickOrientationOptions,(ssize_t) image->orientation)); 00764 if (image->montage != (char *) NULL) 00765 (void) FormatLocaleFile(file," Montage: %s\n",image->montage); 00766 if (image->directory != (char *) NULL) 00767 { 00768 Image 00769 *tile; 00770 00771 ImageInfo 00772 *image_info; 00773 00774 register char 00775 *p, 00776 *q; 00777 00778 WarningHandler 00779 handler; 00780 00781 /* 00782 Display visual image directory. 00783 */ 00784 image_info=AcquireImageInfo(); 00785 (void) CloneString(&image_info->size,"64x64"); 00786 (void) FormatLocaleFile(file," Directory:\n"); 00787 for (p=image->directory; *p != '\0'; p++) 00788 { 00789 q=p; 00790 while ((*q != '\n') && (*q != '\0')) 00791 q++; 00792 (void) CopyMagickString(image_info->filename,p,(size_t) (q-p+1)); 00793 p=q; 00794 (void) FormatLocaleFile(file," %s",image_info->filename); 00795 handler=SetWarningHandler((WarningHandler) NULL); 00796 tile=ReadImage(image_info,exception); 00797 (void) SetWarningHandler(handler); 00798 if (tile == (Image *) NULL) 00799 { 00800 (void) FormatLocaleFile(file,"\n"); 00801 continue; 00802 } 00803 (void) FormatLocaleFile(file," %.20gx%.20g %s\n",(double) 00804 tile->magick_columns,(double) tile->magick_rows,tile->magick); 00805 (void) SignatureImage(tile,exception); 00806 ResetImagePropertyIterator(tile); 00807 property=GetNextImageProperty(tile); 00808 while (property != (const char *) NULL) 00809 { 00810 (void) FormatLocaleFile(file," %s:\n",property); 00811 value=GetImageProperty(tile,property,exception); 00812 if (value != (const char *) NULL) 00813 (void) FormatLocaleFile(file,"%s\n",value); 00814 property=GetNextImageProperty(tile); 00815 } 00816 tile=DestroyImage(tile); 00817 } 00818 image_info=DestroyImageInfo(image_info); 00819 } 00820 (void) GetImageProperty(image,"exif:*",exception); 00821 ResetImagePropertyIterator(image); 00822 property=GetNextImageProperty(image); 00823 if (property != (const char *) NULL) 00824 { 00825 /* 00826 Display image properties. 00827 */ 00828 (void) FormatLocaleFile(file," Properties:\n"); 00829 while (property != (const char *) NULL) 00830 { 00831 (void) FormatLocaleFile(file," %s: ",property); 00832 value=GetImageProperty(image,property,exception); 00833 if (value != (const char *) NULL) 00834 (void) FormatLocaleFile(file,"%s\n",value); 00835 property=GetNextImageProperty(image); 00836 } 00837 } 00838 (void) FormatLocaleString(key,MaxTextExtent,"8BIM:1999,2998:#1"); 00839 value=GetImageProperty(image,key,exception); 00840 if (value != (const char *) NULL) 00841 { 00842 /* 00843 Display clipping path. 00844 */ 00845 (void) FormatLocaleFile(file," Clipping path: "); 00846 if (strlen(value) > 80) 00847 (void) fputc('\n',file); 00848 (void) FormatLocaleFile(file,"%s\n",value); 00849 } 00850 ResetImageProfileIterator(image); 00851 name=GetNextImageProfile(image); 00852 if (name != (char *) NULL) 00853 { 00854 const StringInfo 00855 *profile; 00856 00857 /* 00858 Identify image profiles. 00859 */ 00860 (void) FormatLocaleFile(file," Profiles:\n"); 00861 while (name != (char *) NULL) 00862 { 00863 profile=GetImageProfile(image,name); 00864 if (profile == (StringInfo *) NULL) 00865 continue; 00866 (void) FormatLocaleFile(file," Profile-%s: %.20g bytes\n",name, 00867 (double) GetStringInfoLength(profile)); 00868 #if defined(MAGICKCORE_LCMS_DELEGATE) 00869 if ((LocaleCompare(name,"icc") == 0) || 00870 (LocaleCompare(name,"icm") == 0)) 00871 { 00872 cmsHPROFILE 00873 icc_profile; 00874 00875 icc_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile), 00876 (cmsUInt32Number) GetStringInfoLength(profile)); 00877 if (icc_profile != (cmsHPROFILE *) NULL) 00878 { 00879 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000) 00880 const char 00881 *name; 00882 00883 name=cmsTakeProductName(icc_profile); 00884 if (name != (const char *) NULL) 00885 (void) FormatLocaleFile(file," %s\n",name); 00886 #else 00887 char 00888 info[MaxTextExtent]; 00889 00890 (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoDescription, 00891 "en","US",info,MaxTextExtent); 00892 (void) FormatLocaleFile(file," Description: %s\n",info); 00893 (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoManufacturer, 00894 "en","US",info,MaxTextExtent); 00895 (void) FormatLocaleFile(file," Manufacturer: %s\n",info); 00896 (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoModel,"en", 00897 "US",info,MaxTextExtent); 00898 (void) FormatLocaleFile(file," Model: %s\n",info); 00899 (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoCopyright, 00900 "en","US",info,MaxTextExtent); 00901 (void) FormatLocaleFile(file," Copyright: %s\n",info); 00902 #endif 00903 (void) cmsCloseProfile(icc_profile); 00904 } 00905 } 00906 #endif 00907 if (LocaleCompare(name,"iptc") == 0) 00908 { 00909 char 00910 *attribute, 00911 **attribute_list; 00912 00913 const char 00914 *tag; 00915 00916 long 00917 dataset, 00918 record, 00919 sentinel; 00920 00921 register ssize_t 00922 j; 00923 00924 size_t 00925 length, 00926 profile_length; 00927 00928 profile_length=GetStringInfoLength(profile); 00929 for (i=0; i < (ssize_t) profile_length; i+=(ssize_t) length) 00930 { 00931 length=1; 00932 sentinel=GetStringInfoDatum(profile)[i++]; 00933 if (sentinel != 0x1c) 00934 continue; 00935 dataset=GetStringInfoDatum(profile)[i++]; 00936 record=GetStringInfoDatum(profile)[i++]; 00937 switch (record) 00938 { 00939 case 5: tag="Image Name"; break; 00940 case 7: tag="Edit Status"; break; 00941 case 10: tag="Priority"; break; 00942 case 15: tag="Category"; break; 00943 case 20: tag="Supplemental Category"; break; 00944 case 22: tag="Fixture Identifier"; break; 00945 case 25: tag="Keyword"; break; 00946 case 30: tag="Release Date"; break; 00947 case 35: tag="Release Time"; break; 00948 case 40: tag="Special Instructions"; break; 00949 case 45: tag="Reference Service"; break; 00950 case 47: tag="Reference Date"; break; 00951 case 50: tag="Reference Number"; break; 00952 case 55: tag="Created Date"; break; 00953 case 60: tag="Created Time"; break; 00954 case 65: tag="Originating Program"; break; 00955 case 70: tag="Program Version"; break; 00956 case 75: tag="Object Cycle"; break; 00957 case 80: tag="Byline"; break; 00958 case 85: tag="Byline Title"; break; 00959 case 90: tag="City"; break; 00960 case 95: tag="Province State"; break; 00961 case 100: tag="Country Code"; break; 00962 case 101: tag="Country"; break; 00963 case 103: tag="Original Transmission Reference"; break; 00964 case 105: tag="Headline"; break; 00965 case 110: tag="Credit"; break; 00966 case 115: tag="Src"; break; 00967 case 116: tag="Copyright String"; break; 00968 case 120: tag="Caption"; break; 00969 case 121: tag="Local Caption"; break; 00970 case 122: tag="Caption Writer"; break; 00971 case 200: tag="Custom Field 1"; break; 00972 case 201: tag="Custom Field 2"; break; 00973 case 202: tag="Custom Field 3"; break; 00974 case 203: tag="Custom Field 4"; break; 00975 case 204: tag="Custom Field 5"; break; 00976 case 205: tag="Custom Field 6"; break; 00977 case 206: tag="Custom Field 7"; break; 00978 case 207: tag="Custom Field 8"; break; 00979 case 208: tag="Custom Field 9"; break; 00980 case 209: tag="Custom Field 10"; break; 00981 case 210: tag="Custom Field 11"; break; 00982 case 211: tag="Custom Field 12"; break; 00983 case 212: tag="Custom Field 13"; break; 00984 case 213: tag="Custom Field 14"; break; 00985 case 214: tag="Custom Field 15"; break; 00986 case 215: tag="Custom Field 16"; break; 00987 case 216: tag="Custom Field 17"; break; 00988 case 217: tag="Custom Field 18"; break; 00989 case 218: tag="Custom Field 19"; break; 00990 case 219: tag="Custom Field 20"; break; 00991 default: tag="unknown"; break; 00992 } 00993 (void) FormatLocaleFile(file," %s[%.20g,%.20g]: ",tag, 00994 (double) dataset,(double) record); 00995 length=(size_t) (GetStringInfoDatum(profile)[i++] << 8); 00996 length|=GetStringInfoDatum(profile)[i++]; 00997 attribute=(char *) NULL; 00998 if (~length >= (MaxTextExtent-1)) 00999 attribute=(char *) AcquireQuantumMemory(length+MaxTextExtent, 01000 sizeof(*attribute)); 01001 if (attribute != (char *) NULL) 01002 { 01003 (void) CopyMagickString(attribute,(char *) 01004 GetStringInfoDatum(profile)+i,length+1); 01005 attribute_list=StringToList(attribute); 01006 if (attribute_list != (char **) NULL) 01007 { 01008 for (j=0; attribute_list[j] != (char *) NULL; j++) 01009 { 01010 (void) fputs(attribute_list[j],file); 01011 (void) fputs("\n",file); 01012 attribute_list[j]=(char *) RelinquishMagickMemory( 01013 attribute_list[j]); 01014 } 01015 attribute_list=(char **) RelinquishMagickMemory( 01016 attribute_list); 01017 } 01018 attribute=DestroyString(attribute); 01019 } 01020 } 01021 } 01022 if (image->debug != MagickFalse) 01023 PrintStringInfo(file,name,profile); 01024 name=GetNextImageProfile(image); 01025 } 01026 } 01027 ResetImageArtifactIterator(image); 01028 artifact=GetNextImageArtifact(image); 01029 if (artifact != (const char *) NULL) 01030 { 01031 /* 01032 Display image artifacts. 01033 */ 01034 (void) FormatLocaleFile(file," Artifacts:\n"); 01035 while (artifact != (const char *) NULL) 01036 { 01037 (void) FormatLocaleFile(file," %s: ",artifact); 01038 value=GetImageArtifact(image,artifact); 01039 if (value != (const char *) NULL) 01040 (void) FormatLocaleFile(file,"%s\n",value); 01041 artifact=GetNextImageArtifact(image); 01042 } 01043 } 01044 ResetImageRegistryIterator(); 01045 registry=GetNextImageRegistry(); 01046 if (registry != (const char *) NULL) 01047 { 01048 /* 01049 Display image registry. 01050 */ 01051 (void) FormatLocaleFile(file," Registry:\n"); 01052 while (registry != (const char *) NULL) 01053 { 01054 (void) FormatLocaleFile(file," %s: ",registry); 01055 value=(const char *) GetImageRegistry(StringRegistryType,registry, 01056 exception); 01057 if (value != (const char *) NULL) 01058 (void) FormatLocaleFile(file,"%s\n",value); 01059 registry=GetNextImageRegistry(); 01060 } 01061 } 01062 (void) FormatLocaleFile(file," Tainted: %s\n",CommandOptionToMnemonic( 01063 MagickBooleanOptions,(ssize_t) image->taint)); 01064 (void) FormatMagickSize(GetBlobSize(image),MagickFalse,format); 01065 (void) FormatLocaleFile(file," Filesize: %s\n",format); 01066 (void) FormatMagickSize((MagickSizeType) image->columns*image->rows, 01067 MagickFalse,format); 01068 if (strlen(format) > 1) 01069 format[strlen(format)-1]='\0'; 01070 (void) FormatLocaleFile(file," Number pixels: %s\n",format); 01071 (void) FormatMagickSize((MagickSizeType) ((double) image->columns*image->rows/ 01072 elapsed_time+0.5),MagickFalse,format); 01073 (void) FormatLocaleFile(file," Pixels per second: %s\n",format); 01074 (void) FormatLocaleFile(file," User time: %0.3fu\n",user_time); 01075 (void) FormatLocaleFile(file," Elapsed time: %lu:%02lu.%03lu\n", 01076 (unsigned long) (elapsed_time/60.0),(unsigned long) ceil(fmod(elapsed_time, 01077 60.0)),(unsigned long) (1000.0*(elapsed_time-floor(elapsed_time)))); 01078 (void) FormatLocaleFile(file," Version: %s\n",GetMagickVersion((size_t *) 01079 NULL)); 01080 (void) fflush(file); 01081 return(ferror(file) != 0 ? MagickFalse : MagickTrue); 01082 }