Powered by Pair ImageMagick logo
Image Magick
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals | Related Pages

ImageMagick-6.1.1/coders/avi.c

Go to the documentation of this file.
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % AAA V V IIIII % 00007 % A A V V I % 00008 % AAAAA V V I % 00009 % A A V V I % 00010 % A A V IIIII % 00011 % % 00012 % % 00013 % Read Microsoft Audio/Visual Interleaved Image Format. % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % Nathan Brown % 00018 % March 2004 % 00019 % % 00020 % % 00021 % Copyright 1999-2004 ImageMagick Studio LLC, a non-profit organization % 00022 % dedicated to making software imaging solutions freely available. % 00023 % % 00024 % You may not use this file except in compliance with the License. You may % 00025 % obtain a copy of the License at % 00026 % % 00027 % http://www.imagemagick.org/www/Copyright.html % 00028 % % 00029 % Unless required by applicable law or agreed to in writing, software % 00030 % distributed under the License is distributed on an "AS IS" BASIS, % 00031 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00032 % See the License for the specific language governing permissions and % 00033 % limitations under the License. % 00034 % % 00035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00036 % 00037 % 00038 */ 00039 00040 /* 00041 Include declarations. 00042 */ 00043 #include <setjmp.h> 00044 #include "magick/studio.h" 00045 #include "magick/attribute.h" 00046 #include "magick/blob.h" 00047 #include "magick/blob_private.h" 00048 #include "magick/color_private.h" 00049 #include "magick/color_private.h" 00050 #include "magick/colorspace.h" 00051 #include "magick/constitute.h" 00052 #include "magick/error.h" 00053 #include "magick/error_private.h" 00054 #include "magick/geometry.h" 00055 #include "magick/image.h" 00056 #include "magick/image_private.h" 00057 #include "magick/list.h" 00058 #include "magick/log.h" 00059 #include "magick/magick.h" 00060 #include "magick/memory_.h" 00061 #include "magick/monitor.h" 00062 #include "magick/profile.h" 00063 #include "magick/static.h" 00064 #include "magick/string_.h" 00065 #include "magick/utility.h" 00066 00067 #if defined(HasJPEG) 00068 #define JPEG_INTERNAL_OPTIONS 00069 #if defined(__MINGW32__) 00070 # define XMD_H 1 /* Avoid conflicting typedef for INT32 */ 00071 #endif 00072 #undef HAVE_STDLIB_H 00073 #include "jpeglib.h" 00074 #include "jerror.h" 00075 #endif 00076 00077 /* 00078 Define declarations. 00079 */ 00080 #define ICC_MARKER (JPEG_APP0+2) 00081 #define ICC_PROFILE "ICC_PROFILE" 00082 #define IPTC_MARKER (JPEG_APP0+13) 00083 #define XML_MARKER (JPEG_APP0+1) 00084 #define MaxBufferExtent 8192 00085 00086 /* 00087 Typedef declarations. 00088 */ 00089 #if defined(HasJPEG) 00090 00091 typedef struct _ErrorManager 00092 { 00093 Image 00094 *image; 00095 00096 jmp_buf 00097 error_recovery; 00098 00099 boolean 00100 verbose; 00101 } ErrorManager; 00102 00103 typedef struct _SourceManager 00104 { 00105 struct jpeg_source_mgr 00106 manager; 00107 00108 Image 00109 *image; 00110 00111 unsigned char 00112 *source_data; 00113 00114 size_t 00115 source_length; 00116 00117 JOCTET 00118 *buffer; 00119 00120 boolean 00121 start_of_blob; 00122 } SourceManager; 00123 #endif 00124 00125 00126 /* 00127 Typedef declaractions. 00128 */ 00129 typedef struct _AVIInfo 00130 { 00131 unsigned long 00132 delay, 00133 max_data_rate, 00134 pad_granularity, 00135 flags, 00136 total_frames, 00137 initial_frames, 00138 number_streams, 00139 buffer_size, 00140 width, 00141 height, 00142 time_scale, 00143 data_rate, 00144 start_time, 00145 data_length; 00146 } AVIInfo; 00147 00148 typedef struct _BMPInfo 00149 { 00150 unsigned long 00151 size, 00152 width, 00153 height, 00154 planes, 00155 bits_per_pixel; 00156 00157 char 00158 compression[5]; 00159 00160 unsigned long 00161 image_size, 00162 x_pixels, 00163 y_pixels, 00164 number_colors, 00165 important_colors; 00166 } BMPInfo; 00167 00168 typedef struct _StreamInfo 00169 { 00170 char 00171 data_type[5], 00172 data_handler[5]; 00173 00174 unsigned long 00175 flags, 00176 priority, 00177 initial_frames, 00178 time_scale, 00179 data_rate, 00180 start_time, 00181 data_length, 00182 buffer_size, 00183 quality, 00184 sample_size; 00185 } StreamInfo; 00186 00187 /* 00188 MJPEG Information from Microsoft SDK 00189 */ 00190 #if defined(HasJPEG) 00191 #ifndef NOJPEGDIB 00192 00193 /* New DIB Compression Defines */ 00194 #define JPEG_DIB mmioFOURCC('J','P','E','G') /* Still image JPEG DIB biCompression */ 00195 #define MJPG_DIB mmioFOURCC('M','J','P','G') /* Motion JPEG DIB biCompression */ 00196 00197 /* JPEGColorSpaceID Definitions */ 00198 #define JPEG_Y 1 /* Y only component of YCbCr */ 00199 #define JPEG_YCbCr 2 /* YCbCr as define by CCIR 601 */ 00200 #define JPEG_RGB 3 /* 3 component RGB */ 00201 00202 /* Structure definitions */ 00203 00204 #if defined(MAGICK_FUTURE) 00205 typedef struct tagJPEGINFOHEADER { 00206 /* compression-specific fields */ 00207 /* these fields are defined for 'JPEG' and 'MJPG' */ 00208 DWORD JPEGSize; 00209 DWORD JPEGProcess; 00210 00211 /* Process specific fields */ 00212 DWORD JPEGColorSpaceID; 00213 DWORD JPEGBitsPerSample; 00214 DWORD JPEGHSubSampling; 00215 DWORD JPEGVSubSampling; 00216 } JPEGINFOHEADER; 00217 #endif 00218 00219 /* Default DHT Segment */ 00220 00221 static const unsigned char MJPGDHTSeg[0x1A8] = { 00222 /* JPEG DHT Segment for YCrCb omitted from MJPG data */ 00223 0xFF,0xD8,0xFF,0xC4,0x01,0xA2, 00224 0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 00225 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01, 00226 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 00227 0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00, 00228 0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61, 00229 0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24, 00230 0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34, 00231 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56, 00232 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78, 00233 0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99, 00234 0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9, 00235 0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, 00236 0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7, 00237 0xF8,0xF9,0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01, 00238 0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, 00239 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62, 00240 0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A, 00241 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56, 00242 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78, 00243 0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98, 00244 0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8, 00245 0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8, 00246 0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8, 00247 0xF9,0xFA,0xFF,0xD9 00248 }; 00249 00250 /* End DHT default */ 00251 00252 /* End JPEG */ 00253 #endif 00254 #endif 00255 00256 00257 00258 #if defined(HasJPEG) 00259 /* 00260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00261 % % 00262 % % 00263 % % 00264 % R e a d J P E G I m a g e % 00265 % % 00266 % % 00267 % % 00268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00269 % 00270 % ReadJPEGImage() reads a JPEG image file and returns it. It allocates 00271 % the memory necessary for the new Image structure and returns a pointer to 00272 % the new image. 00273 % 00274 % The format of the ReadJPEGImage method is: 00275 % 00276 % Image *ReadJPEGImage(const ImageInfo *image_info, 00277 % ExceptionInfo *exception) 00278 % 00279 % A description of each parameter follows: 00280 % 00281 % o image_info: The image info. 00282 % 00283 % o exception: return any errors or warnings in this structure. 00284 % 00285 % 00286 */ 00287 00288 static MagickBooleanType EmitMessage(j_common_ptr jpeg_info,int level) 00289 { 00290 char 00291 message[JMSG_LENGTH_MAX]; 00292 00293 ErrorManager 00294 *error_manager; 00295 00296 Image 00297 *image; 00298 00299 (jpeg_info->err->format_message)(jpeg_info,message); 00300 error_manager=(ErrorManager *) jpeg_info->client_data; 00301 image=error_manager->image; 00302 if (error_manager->verbose != MagickFalse) 00303 (void) fprintf(stdout,"%s\n",message); 00304 if (level < 0) 00305 { 00306 if ((jpeg_info->err->num_warnings == 0) || 00307 (jpeg_info->err->trace_level >= 3)) 00308 ThrowBinaryException(CorruptImageError,(char *) message, 00309 image->filename); 00310 jpeg_info->err->num_warnings++; 00311 } 00312 else 00313 if (jpeg_info->err->trace_level >= level) 00314 ThrowBinaryException(CoderError,(char *) message,image->filename); 00315 return(MagickTrue); 00316 } 00317 00318 static boolean FillInputBuffer(j_decompress_ptr cinfo) 00319 { 00320 SourceManager 00321 *source; 00322 00323 source=(SourceManager *) cinfo->src; 00324 if (source->image) 00325 source->manager.bytes_in_buffer=(size_t) ReadBlob(source->image, 00326 Min(source->source_length,MaxBufferExtent),source->buffer); 00327 else 00328 { 00329 source->manager.bytes_in_buffer=(size_t) 00330 Min(source->source_length,MaxBufferExtent); 00331 (void) CopyMagickMemory(source->buffer,source->source_data, 00332 source->manager.bytes_in_buffer); 00333 source->source_data += source->manager.bytes_in_buffer; 00334 } 00335 source->source_length-=source->manager.bytes_in_buffer; 00336 if (source->manager.bytes_in_buffer == 0) 00337 { 00338 if (source->start_of_blob != 0) 00339 ERREXIT(cinfo,JERR_INPUT_EMPTY); 00340 WARNMS(cinfo,JWRN_JPEG_EOF); 00341 source->buffer[0]=(JOCTET) 0xff; 00342 source->buffer[1]=(JOCTET) JPEG_EOI; 00343 source->manager.bytes_in_buffer=2; 00344 } 00345 source->manager.next_input_byte=source->buffer; 00346 source->start_of_blob=FALSE; 00347 return(TRUE); 00348 } 00349 00350 static int GetCharacter(j_decompress_ptr jpeg_info) 00351 { 00352 if (jpeg_info->src->bytes_in_buffer == 0) 00353 (void) (*jpeg_info->src->fill_input_buffer)(jpeg_info); 00354 jpeg_info->src->bytes_in_buffer--; 00355 return((int) GETJOCTET(*jpeg_info->src->next_input_byte++)); 00356 } 00357 00358 static void InitializeSource(j_decompress_ptr cinfo) 00359 { 00360 SourceManager 00361 *source; 00362 00363 source=(SourceManager *) cinfo->src; 00364 source->start_of_blob=TRUE; 00365 } 00366 00367 static void JPEGErrorHandler(j_common_ptr jpeg_info) 00368 { 00369 ErrorManager 00370 *error_manager; 00371 00372 (void) EmitMessage(jpeg_info,0); 00373 error_manager=(ErrorManager *) jpeg_info->client_data; 00374 longjmp(error_manager->error_recovery,1); 00375 } 00376 00377 static boolean ReadComment(j_decompress_ptr jpeg_info) 00378 { 00379 char 00380 *comment; 00381 00382 ErrorManager 00383 *error_manager; 00384 00385 Image 00386 *image; 00387 00388 register char 00389 *p; 00390 00391 register long 00392 i; 00393 00394 size_t 00395 length; 00396 00397 /* 00398 Determine length of comment. 00399 */ 00400 error_manager=(ErrorManager *) jpeg_info->client_data; 00401 image=error_manager->image; 00402 length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8); 00403 length+=GetCharacter(jpeg_info); 00404 length-=2; 00405 if (length <= 0) 00406 return(MagickTrue); 00407 comment=(char *) AcquireMagickMemory(length+MaxTextExtent); 00408 if (comment == (char *) NULL) 00409 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00410 image->filename); 00411 /* 00412 Read comment. 00413 */ 00414 i=(long) length-1; 00415 for (p=comment; i-- >= 0; p++) 00416 *p=(char) GetCharacter(jpeg_info); 00417 *p='\0'; 00418 (void) SetImageAttribute(image,"Comment",comment); 00419 comment=(char *) RelinquishMagickMemory(comment); 00420 return(MagickTrue); 00421 } 00422 00423 static boolean ReadICCProfile(j_decompress_ptr jpeg_info) 00424 { 00425 char 00426 magick[12]; 00427 00428 ErrorManager 00429 *error_manager; 00430 00431 Image 00432 *image; 00433 00434 MagickBooleanType 00435 status; 00436 00437 register long 00438 i; 00439 00440 register unsigned char 00441 *p; 00442 00443 size_t 00444 length; 00445 00446 StringInfo 00447 *icc_profile, 00448 *profile; 00449 00450 /* 00451 Read color profile. 00452 */ 00453 length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8); 00454 length+=(size_t) GetCharacter(jpeg_info); 00455 length-=2; 00456 if (length <= 14) 00457 { 00458 while (length-- >= 0) 00459 (void) GetCharacter(jpeg_info); 00460 return(MagickTrue); 00461 } 00462 for (i=0; i < 12; i++) 00463 magick[i]=(char) GetCharacter(jpeg_info); 00464 if (LocaleCompare(magick,ICC_PROFILE) != 0) 00465 { 00466 /* 00467 Not a ICC profile, return. 00468 */ 00469 for (i=0; i < (long) (length-12); i++) 00470 (void) GetCharacter(jpeg_info); 00471 return(MagickTrue); 00472 } 00473 (void) GetCharacter(jpeg_info); /* id */ 00474 (void) GetCharacter(jpeg_info); /* markers */ 00475 length-=14; 00476 error_manager=(ErrorManager *) jpeg_info->client_data; 00477 image=error_manager->image; 00478 profile=AcquireStringInfo(length); 00479 if (profile == (StringInfo *) NULL) 00480 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00481 image->filename); 00482 p=profile->datum; 00483 for (i=(long) profile->length-1; i >= 0; i--) 00484 *p++=(unsigned char) GetCharacter(jpeg_info); 00485 icc_profile=GetImageProfile(image,"icc"); 00486 if (icc_profile != (StringInfo *) NULL) 00487 ConcatenateStringInfo(icc_profile,profile); 00488 else 00489 { 00490 status=SetImageProfile(image,"icc",profile); 00491 if (status == MagickFalse) 00492 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00493 image->filename); 00494 } 00495 if (image->debug != MagickFalse) 00496 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00497 "Profile: ICC, %lu bytes",(unsigned long) length); 00498 return(MagickTrue); 00499 } 00500 00501 static boolean ReadIPTCProfile(j_decompress_ptr jpeg_info) 00502 { 00503 char 00504 magick[MaxTextExtent]; 00505 00506 ErrorManager 00507 *error_manager; 00508 00509 Image 00510 *image; 00511 00512 MagickBooleanType 00513 status; 00514 00515 register long 00516 i; 00517 00518 register unsigned char 00519 *p; 00520 00521 size_t 00522 length, 00523 tag_length; 00524 00525 StringInfo 00526 *iptc_profile, 00527 *profile; 00528 00529 #ifdef GET_ONLY_IPTC_DATA 00530 unsigned char 00531 tag[MaxTextExtent]; 00532 #endif 00533 00534 /* 00535 Determine length of binary data stored here. 00536 */ 00537 length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8); 00538 length+=(size_t) GetCharacter(jpeg_info); 00539 if (length <= 2) 00540 return(MagickTrue); 00541 length-=2; 00542 tag_length=0; 00543 #ifdef GET_ONLY_IPTC_DATA 00544 *tag='\0'; 00545 #endif 00546 error_manager=(ErrorManager *) jpeg_info->client_data; 00547 image=error_manager->image; 00548 iptc_profile=GetImageProfile(image,"iptc"); 00549 if (iptc_profile == (StringInfo *) NULL) 00550 { 00551 #ifdef GET_ONLY_IPTC_DATA 00552 /* 00553 Find the beginning of the iptc portion of the binary data. 00554 */ 00555 for (*tag='\0'; length > 0; ) 00556 { 00557 *tag=GetCharacter(jpeg_info); 00558 *(tag+1)=GetCharacter(jpeg_info); 00559 length-=2; 00560 if ((*tag == 0x1c) && (*(tag+1) == 0x02)) 00561 break; 00562 } 00563 tag_length=2; 00564 #else 00565 /* 00566 Validate that this was written as a Photoshop resource format slug. 00567 */ 00568 for (i=0; i < 10; i++) 00569 magick[i]=(char) GetCharacter(jpeg_info); 00570 magick[10]='\0'; 00571 if (length <= 10) 00572 return(MagickTrue); 00573 length-=10; 00574 if (LocaleCompare(magick,"Photoshop ") != 0) 00575 { 00576 /* 00577 Not a ICC profile, return. 00578 */ 00579 for (i=0; i < (long) length; i++) 00580 (void) GetCharacter(jpeg_info); 00581 return(MagickTrue); 00582 } 00583 /* 00584 Remove the version number. 00585 */ 00586 for (i=0; i < 4; i++) 00587 (void) GetCharacter(jpeg_info); 00588 if (length <= 4) 00589 return(MagickTrue); 00590 length-=4; 00591 tag_length=0; 00592 #endif 00593 } 00594 if (length == 0) 00595 return(MagickTrue); 00596 profile=AcquireStringInfo(length); 00597 if (profile == (StringInfo *) NULL) 00598 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00599 image->filename); 00600 p=profile->datum; 00601 for (i=(long) profile->length-1; i >= 0; i--) 00602 *p++=(unsigned char) GetCharacter(jpeg_info); 00603 iptc_profile=GetImageProfile(image,"iptc"); 00604 if (iptc_profile != (StringInfo *) NULL) 00605 ConcatenateStringInfo(iptc_profile,profile); 00606 else 00607 { 00608 status=SetImageProfile(image,"iptc",profile); 00609 if (status == MagickFalse) 00610 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00611 image->filename); 00612 } 00613 if (image->debug != MagickFalse) 00614 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00615 "Profile: iptc, %lu bytes",(unsigned long) length); 00616 return(MagickTrue); 00617 } 00618 00619 static boolean ReadProfile(j_decompress_ptr jpeg_info) 00620 { 00621 char 00622 name[MaxTextExtent]; 00623 00624 ErrorManager 00625 *error_manager; 00626 00627 Image 00628 *image; 00629 00630 int 00631 marker; 00632 00633 MagickBooleanType 00634 status; 00635 00636 register long 00637 i; 00638 00639 register unsigned char 00640 *p; 00641 00642 size_t 00643 length; 00644 00645 StringInfo 00646 *profile; 00647 00648 /* 00649 Read generic profile. 00650 */ 00651 length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8); 00652 length+=(size_t) GetCharacter(jpeg_info); 00653 if (length <= 2) 00654 return(MagickTrue); 00655 length-=2; 00656 marker=jpeg_info->unread_marker-JPEG_APP0; 00657 error_manager=(ErrorManager *) jpeg_info->client_data; 00658 image=error_manager->image; 00659 (void) FormatMagickString(name,MaxTextExtent,"APP%d",marker); 00660 profile=AcquireStringInfo(length); 00661 if (profile == (StringInfo *) NULL) 00662 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00663 image->filename); 00664 p=profile->datum; 00665 for (i=(long) profile->length-1; i >= 0; i--) 00666 *p++=(unsigned char) GetCharacter(jpeg_info); 00667 if (marker == 1) 00668 { 00669 p=profile->datum; 00670 if ((length > 4) && (LocaleNCompare((char *) p,"exif",4) == 0)) 00671 (void) CopyMagickString(name,"iptc",MaxTextExtent); 00672 if ((length > 5) && (LocaleNCompare((char *) p,"http:",5) == 0)) 00673 (void) CopyMagickString(name,"xmp",MaxTextExtent); 00674 } 00675 status=SetImageProfile(image,name,profile); 00676 if (status == MagickFalse) 00677 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00678 image->filename); 00679 if (image->debug != MagickFalse) 00680 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00681 "Profile: %s, %lu bytes",name,(unsigned long) length); 00682 return(MagickTrue); 00683 } 00684 00685 static void SkipInputData(j_decompress_ptr cinfo,long number_bytes) 00686 { 00687 SourceManager 00688 *source; 00689 00690 if (number_bytes <= 0) 00691 return; 00692 source=(SourceManager *) cinfo->src; 00693 while (number_bytes > (long) source->manager.bytes_in_buffer) 00694 { 00695 number_bytes-=(long) source->manager.bytes_in_buffer; 00696 (void) FillInputBuffer(cinfo); 00697 } 00698 source->manager.next_input_byte+=(size_t) number_bytes; 00699 source->manager.bytes_in_buffer-=(size_t) number_bytes; 00700 } 00701 00702 static void TerminateSource(j_decompress_ptr cinfo) 00703 { 00704 cinfo=cinfo; 00705 } 00706 00707 static void JPEGSourceManagerMemory(j_decompress_ptr cinfo,unsigned char *source_data, unsigned long source_length) 00708 { 00709 SourceManager 00710 *source; 00711 00712 cinfo->src=(struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) 00713 ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(SourceManager)); 00714 source=(SourceManager *) cinfo->src; 00715 source->buffer=(JOCTET *) (*cinfo->mem->alloc_small) 00716 ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET)); 00717 source=(SourceManager *) cinfo->src; 00718 source->manager.init_source=InitializeSource; 00719 source->manager.fill_input_buffer=FillInputBuffer; 00720 source->manager.skip_input_data=SkipInputData; 00721 source->manager.resync_to_restart=jpeg_resync_to_restart; 00722 source->manager.term_source=TerminateSource; 00723 source->manager.bytes_in_buffer=0; 00724 source->manager.next_input_byte=NULL; 00725 source->image=0; 00726 source->source_data=source_data; 00727 source->source_length=source_length; 00728 } 00729 00730 static void JPEGSourceManagerBLOB(j_decompress_ptr cinfo,Image *image, unsigned long source_length) 00731 { 00732 SourceManager 00733 *source; 00734 00735 cinfo->src=(struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) 00736 ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(SourceManager)); 00737 source=(SourceManager *) cinfo->src; 00738 source->buffer=(JOCTET *) (*cinfo->mem->alloc_small) 00739 ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET)); 00740 source=(SourceManager *) cinfo->src; 00741 source->manager.init_source=InitializeSource; 00742 source->manager.fill_input_buffer=FillInputBuffer; 00743 source->manager.skip_input_data=SkipInputData; 00744 source->manager.resync_to_restart=jpeg_resync_to_restart; 00745 source->manager.term_source=TerminateSource; 00746 source->manager.bytes_in_buffer=0; 00747 source->manager.next_input_byte=NULL; 00748 source->image=image; 00749 source->source_data=0; 00750 source->source_length=source_length; 00751 } 00752 00753 00754 #endif 00755 00756 /* 00757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00758 % % 00759 % % 00760 % % 00761 % D e c o d e I m a g e % 00762 % % 00763 % % 00764 % % 00765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00766 % 00767 % DecodeImage unpacks the packed image pixels into runlength-encoded 00768 % pixel packets. 00769 % 00770 % The format of the DecodeImage method is: 00771 % 00772 % MagickBooleanType DecodeImage(Image *image, 00773 % const MagickBooleanType compression,unsigned char *pixels) 00774 % 00775 % A description of each parameter follows: 00776 % 00777 % o image: The address of a structure of type Image. 00778 % 00779 % o compression: A value of 1 means the compressed pixels are runlength 00780 % encoded for a 256-color bitmap. A value of 2 means a 16-color bitmap. 00781 % 00782 % o pixels: The address of a byte (8 bits) array of pixel data created by 00783 % the decoding process. 00784 % 00785 % 00786 */ 00787 static MagickBooleanType DecodeImage(Image *image, 00788 const MagickBooleanType compression,unsigned char *pixels) 00789 { 00790 #if !defined(__WINDOWS__) || defined(__MINGW32__) 00791 #define BI_RLE8 1 00792 #endif 00793 00794 int 00795 count; 00796 00797 long 00798 y; 00799 00800 MagickBooleanType 00801 status; 00802 00803 register long 00804 i, 00805 x; 00806 00807 register unsigned char 00808 *p, 00809 *q; 00810 00811 unsigned char 00812 byte; 00813 00814 assert(image != (Image *) NULL); 00815 assert(image->signature == MagickSignature); 00816 if (image->debug != MagickFalse) 00817 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00818 assert(pixels != (unsigned char *) NULL); 00819 (void) ResetMagickMemory(pixels,0,(size_t) image->columns*image->rows* 00820 sizeof(pixels)); 00821 byte=0; 00822 x=0; 00823 p=pixels; 00824 q=pixels+(size_t) image->columns*image->rows; 00825 for (y=0; y < (long) image->rows; ) 00826 { 00827 if ((p < pixels) || (p >= q)) 00828 break; 00829 count=ReadBlobByte(image); 00830 if (count == EOF) 00831 break; 00832 if (count != 0) 00833 { 00834 count=Min((unsigned long) count,q-p); 00835 /* 00836 Encoded mode. 00837 */ 00838 byte=(unsigned char) ReadBlobByte(image); 00839 if (compression == BI_RLE8) 00840 { 00841 for (i=0; i < count; i++) 00842 *p++=(unsigned char) byte; 00843 } 00844 else 00845 { 00846 for (i=0; i < count; i++) 00847 *p++=(unsigned char) 00848 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f)); 00849 } 00850 x+=count; 00851 } 00852 else 00853 { 00854 /* 00855 Escape mode. 00856 */ 00857 count=ReadBlobByte(image); 00858 if (count == 0x01) 00859 return(MagickTrue); 00860 switch (count) 00861 { 00862 case 0x00: 00863 { 00864 /* 00865 End of line. 00866 */ 00867 x=0; 00868 y++; 00869 p=pixels+y*image->columns; 00870 break; 00871 } 00872 case 0x02: 00873 { 00874 /* 00875 Delta mode. 00876 */ 00877 x+=ReadBlobByte(image); 00878 y+=ReadBlobByte(image); 00879 p=pixels+y*image->columns+x; 00880 break; 00881 } 00882 default: 00883 { 00884 /* 00885 Absolute mode. 00886 */ 00887 count=Min((unsigned long) count,q-p); 00888 if (compression == BI_RLE8) 00889 for (i=0; i < count; i++) 00890 *p++=(unsigned char) ReadBlobByte(image); 00891 else 00892 for (i=0; i < count; i++) 00893 { 00894 if ((i & 0x01) == 0) 00895 byte=(unsigned char) ReadBlobByte(image); 00896 *p++=(unsigned char) 00897 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f)); 00898 } 00899 x+=count; 00900 /* 00901 Read pad byte. 00902 */ 00903 if (compression == BI_RLE8) 00904 { 00905 if ((count & 0x01) != 0) 00906 (void) ReadBlobByte(image); 00907 } 00908 else 00909 if (((count & 0x03) == 1) || ((count & 0x03) == 2)) 00910 (void) ReadBlobByte(image); 00911 break; 00912 } 00913 } 00914 } 00915 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 00916 (QuantumTick(y,image->rows) != MagickFalse)) 00917 { 00918 status=image->progress_monitor(LoadImageTag,y,image->rows, 00919 image->client_data); 00920 if (status == MagickFalse) 00921 break; 00922 } 00923 } 00924 (void) ReadBlobByte(image); /* end of line */ 00925 (void) ReadBlobByte(image); 00926 return(MagickTrue); 00927 } 00928 00929 /* 00930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00931 % % 00932 % % 00933 % % 00934 % I s A V I % 00935 % % 00936 % % 00937 % % 00938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00939 % 00940 % IsAVI() returns MagickTrue if the image format type, identified by the 00941 % magick string, is Audio/Video Interleaved file format. 00942 % 00943 % The format of the IsAVI method is: 00944 % 00945 % unsigned long IsAVI(const unsigned char *magick,const size_t length) 00946 % 00947 % A description of each parameter follows: 00948 % 00949 % o magick: This string is generally the first few bytes of an image file 00950 % or blob. 00951 % 00952 % o length: Specifies the length of the magick string. 00953 % 00954 % 00955 */ 00956 static MagickBooleanType IsAVI(const unsigned char *magick,const size_t length) 00957 { 00958 if (length < 4) 00959 return(MagickFalse); 00960 if (memcmp(magick,"RIFF",4) == 0) 00961 return(MagickTrue); 00962 return(MagickFalse); 00963 } 00964 00965 /* 00966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00967 % % 00968 % % 00969 % % 00970 % R e a d A V I I m a g e % 00971 % % 00972 % % 00973 % % 00974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00975 % 00976 % ReadAVIImage() reads an Audio Video Interleave image file and returns 00977 % it. It allocates the memory necessary for the new Image structure and 00978 % returns a pointer to the new image. 00979 % 00980 % The format of the ReadAVIImage method is: 00981 % 00982 % Image *ReadAVIImage(const ImageInfo *image_info,ExceptionInfo *exception) 00983 % 00984 % A description of each parameter follows: 00985 % 00986 % o image: Method ReadAVIImage returns a pointer to the image after 00987 % reading. A null image is returned if there is a memory shortage or if 00988 % the image cannot be read. 00989 % 00990 % o image_info: The image info. 00991 % 00992 % o exception: return any errors or warnings in this structure. 00993 % 00994 % 00995 */ 00996 static Image *ReadAVIImage(const ImageInfo *image_info,ExceptionInfo *exception) 00997 { 00998 AVIInfo 00999 avi_info; 01000 01001 BMPInfo 01002 bmp_info; 01003 01004 char 01005 id[MaxTextExtent], 01006 message[MaxTextExtent]; 01007 01008 Image 01009 *image; 01010 01011 IndexPacket 01012 index; 01013 01014 long 01015 y; 01016 01017 MagickBooleanType 01018 status; 01019 01020 PixelPacket 01021 *colormap; 01022 01023 register IndexPacket 01024 *indexes; 01025 01026 register long 01027 x; 01028 01029 register PixelPacket 01030 *q; 01031 01032 register long 01033 i; 01034 01035 register unsigned char 01036 *p; 01037 01038 ssize_t 01039 count; 01040 01041 StreamInfo 01042 stream_info; 01043 01044 unsigned char 01045 *pixels; 01046 01047 unsigned long 01048 bit, 01049 bytes_per_line, 01050 chunk_size, 01051 number_colors; 01052 01053 #if defined(HasJPEG) 01054 const ImageAttribute 01055 *attribute; 01056 01057 ErrorManager 01058 error_manager; 01059 01060 GeometryInfo 01061 geometry_info; 01062 01063 JSAMPLE 01064 *jpeg_pixels; 01065 01066 JSAMPROW 01067 scanline[1]; 01068 01069 struct jpeg_decompress_struct 01070 jpeg_info; 01071 01072 struct jpeg_error_mgr 01073 jpeg_error; 01074 01075 unsigned long 01076 number_pixels, 01077 units; 01078 #endif 01079 01080 /* 01081 Open image file. 01082 */ 01083 assert(image_info != (const ImageInfo *) NULL); 01084 assert(image_info->signature == MagickSignature); 01085 if (image_info->debug != MagickFalse) 01086 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image_info->filename); 01087 assert(exception != (ExceptionInfo *) NULL); 01088 assert(exception->signature == MagickSignature); 01089 image=AllocateImage(image_info); 01090 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 01091 if (status == MagickFalse) 01092 { 01093 DestroyImageList(image); 01094 return((Image *) NULL); 01095 } 01096 (void) ResetMagickMemory(&avi_info,0,sizeof(AVIInfo)); 01097 (void) ResetMagickMemory(&bmp_info,0,sizeof(BMPInfo)); 01098 colormap=(PixelPacket *) NULL; 01099 number_colors=0; 01100 01101 #if defined(HasJPEG) 01102 /* 01103 Initialize JPEG image structure. 01104 */ 01105 jpeg_info.err=jpeg_std_error(&jpeg_error); 01106 jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) EmitMessage; 01107 jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler; 01108 jpeg_pixels=(JSAMPLE *) NULL; 01109 error_manager.image=image; 01110 error_manager.verbose=(int) image_info->verbose; 01111 if (setjmp(error_manager.error_recovery) != 0) 01112 { 01113 if (jpeg_pixels != (JSAMPLE *) NULL) 01114 jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels); 01115 jpeg_destroy_decompress(&jpeg_info); 01116 InheritException(exception,&image->exception); 01117 number_pixels=image->columns*image->rows; 01118 if (number_pixels != 0) 01119 return(GetFirstImageInList(image)); 01120 image=DestroyImage(image); 01121 return((Image *) NULL); 01122 } 01123 jpeg_info.client_data=(void *) &error_manager; 01124 jpeg_create_decompress(&jpeg_info); 01125 01126 JPEGSourceManagerMemory(&jpeg_info, (unsigned char *) &MJPGDHTSeg, 0x1A8); 01127 jpeg_read_header(&jpeg_info, FALSE); 01128 #endif 01129 01130 for ( ; ; ) 01131 { 01132 count=ReadBlob(image,4,(unsigned char *) id); 01133 if (count == 0) 01134 break; 01135 id[4]='\0'; 01136 chunk_size=ReadBlobLSBLong(image); 01137 if (chunk_size == 0) 01138 break; 01139 if ((chunk_size & 0x01) != 0) 01140 chunk_size++; 01141 if (image_info->verbose != MagickFalse) 01142 { 01143 (void) fprintf(stdout,"AVI cid %s\n",id); 01144 (void) fprintf(stdout," chunk size %lu\n",chunk_size); 01145 } 01146 if ((LocaleCompare(id,"00db") == 0) || (LocaleCompare(id,"00dc") == 0)) 01147 { 01148 01149 /* 01150 Read JPG compressed image, uses only YCbCr color space encoding 01151 and does not include the JPEG Huffman table, as it is pre-defined. 01152 */ 01153 if (LocaleCompare(bmp_info.compression,"MJPG") == 0) 01154 { 01155 #if defined(HasJPEG) 01156 JPEGSourceManagerBLOB(&jpeg_info,image,chunk_size); 01157 jpeg_set_marker_processor(&jpeg_info,JPEG_COM,ReadComment); 01158 jpeg_set_marker_processor(&jpeg_info,ICC_MARKER,ReadICCProfile); 01159 jpeg_set_marker_processor(&jpeg_info,IPTC_MARKER,ReadIPTCProfile); 01160 for (i=1; i < 16; i++) 01161 if ((i != 2) && (i != 13) && (i != 14)) 01162 jpeg_set_marker_processor(&jpeg_info,(int) i+JPEG_APP0,ReadProfile); 01163 i=jpeg_read_header(&jpeg_info,MagickTrue); 01164 if (jpeg_info.out_color_space == JCS_CMYK) 01165 image->colorspace=CMYKColorspace; 01166 /* 01167 Set image resolution. 01168 */ 01169 units=0; 01170 if ((jpeg_info.saw_JFIF_marker != 0) && (jpeg_info.X_density != 1) && 01171 (jpeg_info.Y_density != 1)) 01172 { 01173 image->x_resolution=(double) jpeg_info.X_density; 01174 image->y_resolution=(double) jpeg_info.Y_density; 01175 units=(unsigned long) jpeg_info.density_unit; 01176 } 01177 attribute=GetImageAttribute(image,"EXIF:XResolution"); 01178 if ((attribute != (const ImageAttribute *) NULL) && 01179 (attribute->value != (char *) NULL)) 01180 { 01181 (void) ParseGeometry(attribute->value,&geometry_info); 01182 if (geometry_info.sigma != 0) 01183 image->x_resolution=geometry_info.rho/geometry_info.sigma; 01184 (void) SetImageAttribute(image,"EXIF:XResolution",(char *) NULL); 01185 } 01186 attribute=GetImageAttribute(image,"EXIF:YResolution"); 01187 if ((attribute != (const ImageAttribute *) NULL) && 01188 (attribute->value != (char *) NULL)) 01189 { 01190 (void) ParseGeometry(attribute->value,&geometry_info); 01191 if (geometry_info.sigma != 0) 01192 image->y_resolution=geometry_info.rho/geometry_info.sigma; 01193 (void) SetImageAttribute(image,"EXIF:YResolution",(char *) NULL); 01194 } 01195 if (units == 1) 01196 image->units=PixelsPerInchResolution; 01197 if (units == 2) 01198 image->units=PixelsPerCentimeterResolution; 01199 number_pixels=image->columns*image->rows; 01200 if (number_pixels != 0) 01201 { 01202 double 01203 scale_factor; 01204 01205 /* 01206 Let the JPEG library subsample for us. 01207 */ 01208 jpeg_calc_output_dimensions(&jpeg_info); 01209 image->magick_columns=jpeg_info.output_width; 01210 image->magick_rows=jpeg_info.output_height; 01211 scale_factor=(double) jpeg_info.output_width/image->columns; 01212 if (scale_factor > ((double) jpeg_info.output_height/image->rows)) 01213 scale_factor=(double) jpeg_info.output_height/image->rows; 01214 jpeg_info.scale_denom=(unsigned int) scale_factor; 01215 jpeg_calc_output_dimensions(&jpeg_info); 01216 if (image->debug != MagickFalse) 01217 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Scale factor: %ld", 01218 (long) scale_factor); 01219 } 01220 if (image_info->subrange != 0) 01221 { 01222 jpeg_info.scale_denom=(unsigned int) image_info->subrange; 01223 jpeg_calc_output_dimensions(&jpeg_info); 01224 } 01225 #if (JPEG_LIB_VERSION >= 61) && defined(D_PROGRESSIVE_SUPPORTED) 01226 #ifdef D_LOSSLESS_SUPPORTED 01227 image->interlace= 01228 jpeg_info.process == JPROC_PROGRESSIVE ? PlaneInterlace : NoInterlace; 01229 image->compression=jpeg_info.process == JPROC_LOSSLESS ? 01230 LosslessJPEGCompression : JPEGCompression; 01231 if (jpeg_info.data_precision > 8) 01232 (void) ThrowMagickException(exception,GetMagickModule(),OptionError, 01233 "12-bit JPEG not supported. Reducing pixel data to 8 bits", 01234 image->filename); 01235 #else 01236 image->interlace=jpeg_info.progressive_mode != 0 ? PlaneInterlace : 01237 NoInterlace; 01238 image->compression=JPEGCompression; 01239 #endif 01240 #else 01241 image->compression=JPEGCompression; 01242 image->interlace=PlaneInterlace; 01243 #endif 01244 if ((image_info->colors != 0) && (image_info->colors <= 256)) 01245 { 01246 /* 01247 Let the JPEG library quantize for us. 01248 */ 01249 jpeg_info.quantize_colors=MagickTrue; 01250 jpeg_info.desired_number_of_colors=(int) image_info->colors; 01251 if (AllocateImageColormap(image,image_info->colors) == MagickFalse) 01252 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 01253 } 01254 (void) jpeg_start_decompress(&jpeg_info); 01255 image->columns=jpeg_info.output_width; 01256 image->rows=jpeg_info.output_height; 01257 image->depth=(unsigned long) jpeg_info.data_precision; 01258 if ((jpeg_info.output_components == 1) && 01259 (jpeg_info.quantize_colors == MagickFalse)) 01260 { 01261 if (AllocateImageColormap(image,1UL << image->depth) == MagickFalse) 01262 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 01263 } 01264 if (image->debug != MagickFalse) 01265 { 01266 if (image->interlace == PlaneInterlace) 01267 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01268 "Interlace: progressive"); 01269 else 01270 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01271 "Interlace: nonprogressive"); 01272 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Data precision: %d", 01273 (int) jpeg_info.data_precision); 01274 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %dx%d", 01275 (int) jpeg_info.output_width,(int) jpeg_info.output_height); 01276 #ifdef D_LOSSLESS_SUPPORTED 01277 if (image->compression==LosslessJPEGCompression) 01278 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01279 "Quality: 100 (lossless)"); 01280 else 01281 #endif 01282 { 01283 long 01284 hashval, 01285 sum; 01286 01287 /* 01288 Log the JPEG quality that was used for compression. 01289 */ 01290 sum=0; 01291 for (i=0; i < NUM_QUANT_TBLS; i++) 01292 { 01293 int 01294 j; 01295 01296 if (jpeg_info.quant_tbl_ptrs[i] != NULL) 01297 for (j=0; j < DCTSIZE2; j++) 01298 { 01299 UINT16 01300 *c; 01301 01302 c=jpeg_info.quant_tbl_ptrs[i]->quantval; 01303 sum+=c[j]; 01304 } 01305 } 01306 if ((jpeg_info.quant_tbl_ptrs[0] != NULL) && 01307 (jpeg_info.quant_tbl_ptrs[1] != NULL)) 01308 { 01309 int 01310 hash[]= 01311 { 01312 1020, 1015, 932, 848, 780, 735, 702, 679, 660, 645, 01313 632, 623, 613, 607, 600, 594, 589, 585, 581, 571, 01314 555, 542, 529, 514, 494, 474, 457, 439, 424, 410, 01315 397, 386, 373, 364, 351, 341, 334, 324, 317, 309, 01316 299, 294, 287, 279, 274, 267, 262, 257, 251, 247, 01317 243, 237, 232, 227, 222, 217, 213, 207, 202, 198, 01318 192, 188, 183, 177, 173, 168, 163, 157, 153, 148, 01319 143, 139, 132, 128, 125, 119, 115, 108, 104, 99, 01320 94, 90, 84, 79, 74, 70, 64, 59, 55, 49, 01321 45, 40, 34, 30, 25, 20, 15, 11, 6, 4, 01322 0 01323 }, 01324 sums[]= 01325 { 01326 32640,32635,32266,31495,30665,29804,29146,28599,28104,27670, 01327 27225,26725,26210,25716,25240,24789,24373,23946,23572,22846, 01328 21801,20842,19949,19121,18386,17651,16998,16349,15800,15247, 01329 14783,14321,13859,13535,13081,12702,12423,12056,11779,11513, 01330 11135,10955,10676,10392,10208, 9928, 9747, 9564, 9369, 9193, 01331 9017, 8822, 8639, 8458, 8270, 8084, 7896, 7710, 7527, 7347, 01332 7156, 6977, 6788, 6607, 6422, 6236, 6054, 5867, 5684, 5495, 01333 5305, 5128, 4945, 4751, 4638, 4442, 4248, 4065, 3888, 3698, 01334 3509, 3326, 3139, 2957, 2775, 2586, 2405, 2216, 2037, 1846, 01335 1666, 1483, 1297, 1109, 927, 735, 554, 375, 201, 128, 01336 0 01337 }; 01338 01339 hashval=(long) ((jpeg_info.quant_tbl_ptrs[0]->quantval[2]+ 01340 jpeg_info.quant_tbl_ptrs[0]->quantval[53]+ 01341 jpeg_info.quant_tbl_ptrs[1]->quantval[0]+ 01342 jpeg_info.quant_tbl_ptrs[1]->quantval[DCTSIZE2-1])); 01343 for (i=0; i < 100; i++) 01344 { 01345 if ((hashval >= hash[i]) || (sum >= sums[i])) 01346 { 01347 if ((hashval > hash[i]) || (sum > sums[i])) 01348 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01349 "Quality: %ld (approximate)",i+1); 01350 else 01351 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01352 "Quality: %ld",i+1); 01353 break; 01354 } 01355 } 01356 } 01357 else 01358 if (jpeg_info.quant_tbl_ptrs[0] != NULL) 01359 { 01360 int 01361 bwhash[]= 01362 { 01363 510, 505, 422, 380, 355, 338, 326, 318, 311, 305, 01364 300, 297, 293, 291, 288, 286, 284, 283, 281, 280, 01365 279, 278, 277, 273, 262, 251, 243, 233, 225, 218, 01366 211, 205, 198, 193, 186, 181, 177, 172, 168, 164, 01367 158, 156, 152, 148, 145, 142, 139, 136, 133, 131, 01368 129, 126, 123, 120, 118, 115, 113, 110, 107, 105, 01369 102, 100, 97, 94, 92, 89, 87, 83, 81, 79, 01370 76, 74, 70, 68, 66, 63, 61, 57, 55, 52, 01371 50, 48, 44, 42, 39, 37, 34, 31, 29, 26, 01372 24, 21, 18, 16, 13, 11, 8, 6, 3, 2, 01373 0 01374 }, 01375 bwsum[]= 01376 { 01377 16320,16315,15946,15277,14655,14073,13623,13230,12859,12560, 01378 12240,11861,11456,11081,10714,10360,10027, 9679, 9368, 9056, 01379 8680, 8331, 7995, 7668, 7376, 7084, 6823, 6562, 6345, 6125, 01380 5939, 5756, 5571, 5421, 5240, 5086, 4976, 4829, 4719, 4616, 01381 4463, 4393, 4280, 4166, 4092, 3980, 3909, 3835, 3755, 3688, 01382 3621, 3541, 3467, 3396, 3323, 3247, 3170, 3096, 3021, 2952, 01383 2874, 2804, 2727, 2657, 2583, 2509, 2437, 2362, 2290, 2211, 01384 2136, 2068, 1996, 1915, 1858, 1773, 1692, 1620, 1552, 1477, 01385 1398, 1326, 1251, 1179, 1109, 1031, 961, 884, 814, 736, 01386 667, 592, 518, 441, 369, 292, 221, 151, 86, 64, 01387 0 01388 }; 01389 01390 hashval=(long) ((jpeg_info.quant_tbl_ptrs[0]->quantval[2]+ 01391 jpeg_info.quant_tbl_ptrs[0]->quantval[53])); 01392 for (i=0; i < 100; i++) 01393 { 01394 if ((hashval >= bwhash[i]) || (sum >= bwsum[i])) 01395 { 01396 if ((hashval > bwhash[i]) || (sum > bwsum[i])) 01397 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01398 "Quality: %ld (approximate)",i+1); 01399 else 01400 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01401 "Quality: %ld",i+1); 01402 break; 01403 } 01404 } 01405 } 01406 } 01407 switch (jpeg_info.out_color_space) 01408 { 01409 case JCS_CMYK: 01410 { 01411 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01412 "Colorspace: CMYK"); 01413 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01414 "Sampling factors: (%d,%d),(%d,%d),(%d,%d),(%d,%d)", 01415 jpeg_info.comp_info[0].h_samp_factor, 01416 jpeg_info.comp_info[0].v_samp_factor, 01417 jpeg_info.comp_info[1].h_samp_factor, 01418 jpeg_info.comp_info[1].v_samp_factor, 01419 jpeg_info.comp_info[2].h_samp_factor, 01420 jpeg_info.comp_info[2].v_samp_factor, 01421 jpeg_info.comp_info[3].h_samp_factor, 01422 jpeg_info.comp_info[3].v_samp_factor); 01423 break; 01424 } 01425 case JCS_GRAYSCALE: 01426 { 01427 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01428 "Colorspace: GRAYSCALE"); 01429 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01430 "Sampling factors: (%d,%d)",jpeg_info.comp_info[0].h_samp_factor, 01431 jpeg_info.comp_info[0].v_samp_factor); 01432 break; 01433 } 01434 case JCS_RGB: 01435 { 01436 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: RGB"); 01437 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01438 "Sampling factors: (%d,%d),(%d,%d),(%d,%d)", 01439 jpeg_info.comp_info[0].h_samp_factor, 01440 jpeg_info.comp_info[0].v_samp_factor, 01441 jpeg_info.comp_info[1].h_samp_factor, 01442 jpeg_info.comp_info[1].v_samp_factor, 01443 jpeg_info.comp_info[2].h_samp_factor, 01444 jpeg_info.comp_info[2].v_samp_factor); 01445 break; 01446 } 01447 default: 01448 { 01449 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d", 01450 jpeg_info.out_color_space); 01451 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01452 "Sampling factors: (%d,%d),(%d,%d),(%d,%d),(%d,%d)", 01453 jpeg_info.comp_info[0].h_samp_factor, 01454 jpeg_info.comp_info[0].v_samp_factor, 01455 jpeg_info.comp_info[1].h_samp_factor, 01456 jpeg_info.comp_info[1].v_samp_factor, 01457 jpeg_info.comp_info[2].h_samp_factor, 01458 jpeg_info.comp_info[2].v_samp_factor, 01459 jpeg_info.comp_info[3].h_samp_factor, 01460 jpeg_info.comp_info[3].v_samp_factor); 01461 break; 01462 } 01463 } 01464 } 01465 if (image_info->ping != MagickFalse) 01466 { 01467 jpeg_destroy_decompress(&jpeg_info); 01468 CloseBlob(image); 01469 return(GetFirstImageInList(image)); 01470 } 01471 jpeg_pixels=(JSAMPLE *) AcquireMagickMemory((size_t) 01472 jpeg_info.output_components*image->columns*sizeof(JSAMPLE)); 01473 if (jpeg_pixels == (JSAMPLE *) NULL) 01474 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 01475 /* 01476 Convert JPEG pixels to pixel packets. 01477 */ 01478 scanline[0]=(JSAMPROW) jpeg_pixels; 01479 for (y=0; y < (long) image->rows; y++) 01480 { 01481 (void) jpeg_read_scanlines(&jpeg_info,scanline,1); 01482 p=jpeg_pixels; 01483 q=SetImagePixels(image,0,y,image->columns,1); 01484 if (q == (PixelPacket *) NULL) 01485 break; 01486 indexes=GetIndexes(image); 01487 if (jpeg_info.data_precision > 8) 01488 { 01489 if (jpeg_info.output_components == 1) 01490 for (x=0; x < (long) image->columns; x++) 01491 { 01492 index=ConstrainColormapIndex(image,16*(unsigned long) 01493 GETJSAMPLE(*p)); 01494 indexes[x]=(IndexPacket) index; 01495 *q++=image->colormap[index]; 01496 p++; 01497 } 01498 else 01499 for (x=0; x < (long) image->columns; x++) 01500 { 01501 q->red=ScaleShortToQuantum(16*GETJSAMPLE(*p++)); 01502 q->green=ScaleShortToQuantum(16*GETJSAMPLE(*p++)); 01503 q->blue=ScaleShortToQuantum(16*GETJSAMPLE(*p++)); 01504 if (image->colorspace == CMYKColorspace) 01505 indexes[x]=ScaleShortToQuantum(16*GETJSAMPLE(*p++)); 01506 q++; 01507 } 01508 } 01509 else 01510 if (jpeg_info.output_components == 1) 01511 for (x=0; x < (long) image->columns; x++) 01512 { 01513 index=ConstrainColormapIndex(image,(unsigned long) 01514 GETJSAMPLE(*p)); 01515 indexes[x]=(IndexPacket) index; 01516 *q++=image->colormap[index]; 01517 p++; 01518 } 01519 else 01520 for (x=0; x < (long) image->columns; x++) 01521 { 01522 q->red=ScaleCharToQuantum(GETJSAMPLE(*p++)); 01523 q->green=ScaleCharToQuantum(GETJSAMPLE(*p++)); 01524 q->blue=ScaleCharToQuantum(GETJSAMPLE(*p++)); 01525 if (image->colorspace == CMYKColorspace) 01526 indexes[x]=ScaleCharToQuantum(GETJSAMPLE(*p++)); 01527 q++; 01528 } 01529 if (SyncImagePixels(image) == MagickFalse) 01530 break; 01531 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01532 (QuantumTick(y,image->rows) != MagickFalse)) 01533 { 01534 status=image->progress_monitor(LoadImageTag,y,image->rows, 01535 image->client_data); 01536 if (status == MagickFalse) 01537 break; 01538 } 01539 } 01540 if (jpeg_info.quantize_colors != MagickFalse) 01541 for (i=0; i < jpeg_info.actual_number_of_colors; i++) 01542 { 01543 image->colormap[i].red=ScaleCharToQuantum(jpeg_info.colormap[0][i]); 01544 image->colormap[i].green=ScaleCharToQuantum(jpeg_info.colormap[1][i]); 01545 image->colormap[i].blue=ScaleCharToQuantum(jpeg_info.colormap[2][i]); 01546 } 01547 if (image->colorspace == CMYKColorspace) 01548 { 01549 /* 01550 Correct CMYK levels. 01551 */ 01552 for (y=0; y < (long) image->rows; y++) 01553 { 01554 q=GetImagePixels(image,0,y,image->columns,1); 01555 if (q == (PixelPacket *) NULL) 01556 break; 01557 indexes=GetIndexes(image); 01558 for (x=0; x < (long) image->columns; x++) 01559 { 01560 q->red=(Quantum) (MaxRGB-q->red); 01561 q->green=(Quantum) (MaxRGB-q->green); 01562 q->blue=(Quantum) (MaxRGB-q->blue); 01563 indexes[x]=(IndexPacket) (MaxRGB-indexes[x]); 01564 q++; 01565 } 01566 if (SyncImagePixels(image) == MagickFalse) 01567 break; 01568 } 01569 } 01570 /* 01571 Consume Buffer. 01572 */ 01573 chunk_size = ((SourceManager *) jpeg_info.src)->source_length; 01574 for ( ; chunk_size != 0; chunk_size--) 01575 (void) ReadBlobByte(image); 01576 /* 01577 Free jpeg resources. 01578 */ 01579 (void) jpeg_finish_decompress(&jpeg_info); 01580 jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels); 01581 #else 01582 (void) FormatMagickString(message,MaxTextExtent, 01583 "AVI compression %s not yet supported",bmp_info.compression); 01584 (void) ThrowMagickException(exception,GetMagickModule(), 01585 CorruptImageError,message,image->filename); 01586 for ( ; chunk_size != 0; chunk_size--) 01587 (void) ReadBlobByte(image); 01588 continue; 01589 #endif 01590 } 01591 01592 /* 01593 Read BMP image 01594 */ 01595 else 01596 { 01597 /* 01598 Initialize image structure. 01599 */ 01600 image->columns=avi_info.width; 01601 image->rows=avi_info.height; 01602 image->depth=8; 01603 image->units=PixelsPerCentimeterResolution; 01604 image->x_resolution=(double) bmp_info.x_pixels/100.0; 01605 image->y_resolution=(double) bmp_info.y_pixels/1