diff -r 59758314f811 -r d4524d6a4472 Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/imgexam_8c_source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/imgexam_8c_source.html Fri Jun 11 15:24:34 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1060 +0,0 @@ - - -
- -00001 /* -00002 * imgexam.c -00003 * Copyright (C) 2000-2004 A.J. van Os; Released under GNU GPL -00004 * -00005 * Description: -00006 * Functions to examine image headers -00007 * -00008 *================================================================ -00009 * Part of this software is based on: -00010 * jpeg2ps - convert JPEG compressed images to PostScript Level 2 -00011 * Copyright (C) 1994-99 Thomas Merz (tm@muc.de) -00012 *================================================================ -00013 * The credit should go to him, but all the bugs are mine. -00014 */ -00015 -00016 #include <stdio.h> -00017 #include <string.h> -00018 #include <ctype.h> -00019 #include "antiword.h" -00020 -00021 /* BMP compression types */ -00022 #define BI_RGB 0 -00023 #define BI_RLE8 1 -00024 #define BI_RLE4 2 -00025 -00026 /* PNG colortype bits */ -00027 #define PNG_CB_PALETTE 0x01 -00028 #define PNG_CB_COLOR 0x02 -00029 #define PNG_CB_ALPHA 0x04 -00030 -00031 /* Instance signature */ -00032 #define MSOBI_WMF 0x0216 -00033 #define MSOBI_EMF 0x03d4 -00034 #define MSOBI_PICT 0x0542 -00035 #define MSOBI_PNG 0x06e0 -00036 #define MSOBI_JPEG 0x046a -00037 #define MSOBI_DIB 0x07a8 -00038 -00039 /* The following enum is stolen from the IJG JPEG library */ -00040 typedef enum { /* JPEG marker codes */ -00041 M_SOF0 = 0xc0, /* baseline DCT */ -00042 M_SOF1 = 0xc1, /* extended sequential DCT */ -00043 M_SOF2 = 0xc2, /* progressive DCT */ -00044 M_SOF3 = 0xc3, /* lossless (sequential) */ -00045 -00046 M_SOF5 = 0xc5, /* differential sequential DCT */ -00047 M_SOF6 = 0xc6, /* differential progressive DCT */ -00048 M_SOF7 = 0xc7, /* differential lossless */ -00049 -00050 M_JPG = 0xc8, /* JPEG extensions */ -00051 M_SOF9 = 0xc9, /* extended sequential DCT */ -00052 M_SOF10 = 0xca, /* progressive DCT */ -00053 M_SOF11 = 0xcb, /* lossless (sequential) */ -00054 -00055 M_SOF13 = 0xcd, /* differential sequential DCT */ -00056 M_SOF14 = 0xce, /* differential progressive DCT */ -00057 M_SOF15 = 0xcf, /* differential lossless */ -00058 -00059 M_DHT = 0xc4, /* define Huffman tables */ -00060 -00061 M_DAC = 0xcc, /* define arithmetic conditioning table */ -00062 -00063 M_RST0 = 0xd0, /* restart */ -00064 M_RST1 = 0xd1, /* restart */ -00065 M_RST2 = 0xd2, /* restart */ -00066 M_RST3 = 0xd3, /* restart */ -00067 M_RST4 = 0xd4, /* restart */ -00068 M_RST5 = 0xd5, /* restart */ -00069 M_RST6 = 0xd6, /* restart */ -00070 M_RST7 = 0xd7, /* restart */ -00071 -00072 M_SOI = 0xd8, /* start of image */ -00073 M_EOI = 0xd9, /* end of image */ -00074 M_SOS = 0xda, /* start of scan */ -00075 M_DQT = 0xdb, /* define quantization tables */ -00076 M_DNL = 0xdc, /* define number of lines */ -00077 M_DRI = 0xdd, /* define restart interval */ -00078 M_DHP = 0xde, /* define hierarchical progression */ -00079 M_EXP = 0xdf, /* expand reference image(s) */ -00080 -00081 M_APP0 = 0xe0, /* application marker, used for JFIF */ -00082 M_APP1 = 0xe1, /* application marker */ -00083 M_APP2 = 0xe2, /* application marker */ -00084 M_APP3 = 0xe3, /* application marker */ -00085 M_APP4 = 0xe4, /* application marker */ -00086 M_APP5 = 0xe5, /* application marker */ -00087 M_APP6 = 0xe6, /* application marker */ -00088 M_APP7 = 0xe7, /* application marker */ -00089 M_APP8 = 0xe8, /* application marker */ -00090 M_APP9 = 0xe9, /* application marker */ -00091 M_APP10 = 0xea, /* application marker */ -00092 M_APP11 = 0xeb, /* application marker */ -00093 M_APP12 = 0xec, /* application marker */ -00094 M_APP13 = 0xed, /* application marker */ -00095 M_APP14 = 0xee, /* application marker, used by Adobe */ -00096 M_APP15 = 0xef, /* application marker */ -00097 -00098 M_JPG0 = 0xf0, /* reserved for JPEG extensions */ -00099 M_JPG13 = 0xfd, /* reserved for JPEG extensions */ -00100 M_COM = 0xfe, /* comment */ -00101 -00102 M_TEM = 0x01 /* temporary use */ -00103 } JPEG_MARKER; -00104 -00105 -00106 /* -00107 * bFillPaletteDIB - fill the palette part of the imagesdata -00108 * -00109 * returns TRUE if the images must be a color image, otherwise FALSE; -00110 */ -00111 static BOOL -00112 bFillPaletteDIB(FILE *pFile, imagedata_type *pImg, BOOL bNewFormat) -00113 { -00114 int iIndex; -00115 BOOL bIsColorPalette; -00116 -00117 fail(pFile == NULL); -00118 fail(pImg == NULL); -00119 -00120 if (pImg->uiBitsPerComponent > 8) { -00121 /* No palette, image uses more than 256 colors */ -00122 return TRUE; -00123 } -00124 -00125 if (pImg->iColorsUsed <= 0) { -00126 /* Not specified, so compute the number of colors used */ -00127 pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent; -00128 } -00129 -00130 fail(pImg->iColorsUsed > 256); -00131 if (pImg->iColorsUsed > 256) { -00132 pImg->iColorsUsed = 256; -00133 } -00134 -00135 bIsColorPalette = FALSE; -00136 for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) { -00137 /* From BGR order to RGB order */ -00138 pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile); -00139 pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile); -00140 pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile); -00141 if (bNewFormat) { -00142 (void)iNextByte(pFile); -00143 } -00144 NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3); -00145 if (pImg->aucPalette[iIndex][0] != -00146 pImg->aucPalette[iIndex][1] || -00147 pImg->aucPalette[iIndex][1] != -00148 pImg->aucPalette[iIndex][2]) { -00149 bIsColorPalette = TRUE; -00150 } -00151 } -00152 -00153 return bIsColorPalette; -00154 } /* end of bFillPaletteDIB */ -00155 -00156 /* -00157 * bExamineDIB - Examine a DIB header -00158 * -00159 * return TRUE if successful, otherwise FALSE -00160 */ -00161 static BOOL -00162 bExamineDIB(FILE *pFile, imagedata_type *pImg) -00163 { -00164 size_t tHeaderSize; -00165 int iPlanes, iCompression; -00166 -00167 tHeaderSize = (size_t)ulNextLong(pFile); -00168 switch (tHeaderSize) { -00169 case 12: -00170 pImg->iWidth = (int)usNextWord(pFile); -00171 pImg->iHeight = (int)usNextWord(pFile); -00172 iPlanes = (int)usNextWord(pFile); -00173 pImg->uiBitsPerComponent = (UINT)usNextWord(pFile); -00174 iCompression = BI_RGB; -00175 pImg->iColorsUsed = 0; -00176 break; -00177 case 40: -00178 case 64: -00179 pImg->iWidth = (int)ulNextLong(pFile); -00180 pImg->iHeight = (int)ulNextLong(pFile); -00181 iPlanes = (int)usNextWord(pFile); -00182 pImg->uiBitsPerComponent = (UINT)usNextWord(pFile); -00183 iCompression = (int)ulNextLong(pFile); -00184 (void)tSkipBytes(pFile, 12); -00185 pImg->iColorsUsed = (int)ulNextLong(pFile); -00186 (void)tSkipBytes(pFile, tHeaderSize - 36); -00187 break; -00188 default: -00189 DBG_DEC(tHeaderSize); -00190 return FALSE; -00191 } -00192 DBG_DEC(pImg->iWidth); -00193 DBG_DEC(pImg->iHeight); -00194 DBG_DEC(pImg->uiBitsPerComponent); -00195 DBG_DEC(iCompression); -00196 DBG_DEC(pImg->iColorsUsed); -00197 -00198 /* Do some sanity checks with the parameters */ -00199 if (iPlanes != 1) { -00200 DBG_DEC(iPlanes); -00201 return FALSE; -00202 } -00203 if (pImg->iWidth <= 0 || pImg->iHeight <= 0) { -00204 DBG_DEC(pImg->iWidth); -00205 DBG_DEC(pImg->iHeight); -00206 return FALSE; -00207 } -00208 if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 4 && -00209 pImg->uiBitsPerComponent != 8 && pImg->uiBitsPerComponent != 24) { -00210 DBG_DEC(pImg->uiBitsPerComponent); -00211 return FALSE; -00212 } -00213 if (iCompression != BI_RGB && -00214 (pImg->uiBitsPerComponent == 1 || pImg->uiBitsPerComponent == 24)) { -00215 return FALSE; -00216 } -00217 if (iCompression == BI_RLE8 && pImg->uiBitsPerComponent == 4) { -00218 return FALSE; -00219 } -00220 if (iCompression == BI_RLE4 && pImg->uiBitsPerComponent == 8) { -00221 return FALSE; -00222 } -00223 -00224 switch (iCompression) { -00225 case BI_RGB: -00226 pImg->eCompression = compression_none; -00227 break; -00228 case BI_RLE4: -00229 pImg->eCompression = compression_rle4; -00230 break; -00231 case BI_RLE8: -00232 pImg->eCompression = compression_rle8; -00233 break; -00234 default: -00235 DBG_DEC(iCompression); -00236 return FALSE; -00237 } -00238 -00239 pImg->bColorImage = bFillPaletteDIB(pFile, pImg, tHeaderSize > 12); -00240 -00241 if (pImg->uiBitsPerComponent <= 8) { -00242 pImg->iComponents = 1; -00243 } else { -00244 pImg->iComponents = (int)(pImg->uiBitsPerComponent / 8); -00245 } -00246 -00247 return TRUE; -00248 } /* end of bExamineDIB */ -00249 -00250 /* -00251 * iNextMarker - read the next JPEG marker -00252 */ -00253 static int -00254 iNextMarker(FILE *pFile) -00255 { -00256 int iMarker; -00257 -00258 do { -00259 do { -00260 iMarker = iNextByte(pFile); -00261 } while (iMarker != 0xff && iMarker != EOF); -00262 if (iMarker == EOF) { -00263 return EOF; -00264 } -00265 do { -00266 iMarker = iNextByte(pFile); -00267 } while (iMarker == 0xff); -00268 } while (iMarker == 0x00); /* repeat if ff/00 */ -00269 -00270 return iMarker; -00271 } /* end of iNextMarker */ -00272 -00273 /* -00274 * bExamineJPEG - Examine a JPEG header -00275 * -00276 * return TRUE if successful, otherwise FALSE -00277 */ -00278 static BOOL -00279 bExamineJPEG(FILE *pFile, imagedata_type *pImg) -00280 { -00281 size_t tLength; -00282 int iMarker, iIndex; -00283 char appstring[10]; -00284 BOOL bSOFDone; -00285 -00286 tLength = 0; -00287 bSOFDone = FALSE; -00288 -00289 /* process JPEG markers */ -00290 while (!bSOFDone && (iMarker = iNextMarker(pFile)) != (int)M_EOI) { -00291 switch (iMarker) { -00292 case EOF: -00293 DBG_MSG("Error: unexpected end of JPEG file"); -00294 return FALSE; -00295 /* The following are not officially supported in PostScript level 2 */ -00296 case M_SOF2: -00297 case M_SOF3: -00298 case M_SOF5: -00299 case M_SOF6: -00300 case M_SOF7: -00301 case M_SOF9: -00302 case M_SOF10: -00303 case M_SOF11: -00304 case M_SOF13: -00305 case M_SOF14: -00306 case M_SOF15: -00307 DBG_HEX(iMarker); -00308 return FALSE; -00309 case M_SOF0: -00310 case M_SOF1: -00311 tLength = (size_t)usNextWordBE(pFile); -00312 pImg->uiBitsPerComponent = (UINT)iNextByte(pFile); -00313 pImg->iHeight = (int)usNextWordBE(pFile); -00314 pImg->iWidth = (int)usNextWordBE(pFile); -00315 pImg->iComponents = iNextByte(pFile); -00316 bSOFDone = TRUE; -00317 break; -00318 case M_APP14: -00319 /* -00320 * Check for Adobe application marker. It is known (per Adobe's -00321 * TN5116) to contain the string "Adobe" at the start of the -00322 * APP14 marker. -00323 */ -00324 tLength = (size_t)usNextWordBE(pFile); -00325 if (tLength < 12) { -00326 (void)tSkipBytes(pFile, tLength - 2); -00327 } else { -00328 for (iIndex = 0; iIndex < 5; iIndex++) { -00329 appstring[iIndex] = -00330 (char)iNextByte(pFile); -00331 } -00332 appstring[5] = '\0'; -00333 if (STREQ(appstring, "Adobe")) { -00334 pImg->bAdobe = TRUE; -00335 } -00336 (void)tSkipBytes(pFile, tLength - 7); -00337 } -00338 break; -00339 case M_SOI: /* ignore markers without parameters */ -00340 case M_EOI: -00341 case M_TEM: -00342 case M_RST0: -00343 case M_RST1: -00344 case M_RST2: -00345 case M_RST3: -00346 case M_RST4: -00347 case M_RST5: -00348 case M_RST6: -00349 case M_RST7: -00350 break; -00351 default: /* skip variable length markers */ -00352 tLength = (size_t)usNextWordBE(pFile); -00353 (void)tSkipBytes(pFile, tLength - 2); -00354 break; -00355 } -00356 } -00357 -00358 DBG_DEC(pImg->iWidth); -00359 DBG_DEC(pImg->iHeight); -00360 DBG_DEC(pImg->uiBitsPerComponent); -00361 DBG_DEC(pImg->iComponents); -00362 -00363 /* Do some sanity checks with the parameters */ -00364 if (pImg->iHeight <= 0 || -00365 pImg->iWidth <= 0 || -00366 pImg->iComponents <= 0) { -00367 DBG_DEC(pImg->iHeight); -00368 DBG_DEC(pImg->iWidth); -00369 DBG_DEC(pImg->iComponents); -00370 return FALSE; -00371 } -00372 -00373 /* Some broken JPEG files have this but they print anyway... */ -00374 if (pImg->iComponents * 3 + 8 != (int)tLength) { -00375 DBG_MSG("Warning: SOF marker has incorrect length - ignored"); -00376 } -00377 -00378 if (pImg->uiBitsPerComponent != 8) { -00379 DBG_DEC(pImg->uiBitsPerComponent); -00380 DBG_MSG("Not supported in PostScript level 2"); -00381 return FALSE; -00382 } -00383 -00384 if (pImg->iComponents != 1 && -00385 pImg->iComponents != 3 && -00386 pImg->iComponents != 4) { -00387 DBG_DEC(pImg->iComponents); -00388 return FALSE; -00389 } -00390 -00391 pImg->bColorImage = pImg->iComponents >= 3; -00392 pImg->iColorsUsed = 0; -00393 pImg->eCompression = compression_jpeg; -00394 -00395 return TRUE; -00396 } /* end of bExamineJPEG */ -00397 -00398 /* -00399 * bFillPalettePNG - fill the palette part of the imagesdata -00400 * -00401 * returns TRUE if sucessful, otherwise FALSE; -00402 */ -00403 static BOOL -00404 bFillPalettePNG(FILE *pFile, imagedata_type *pImg, size_t tLength) -00405 { -00406 int iIndex, iEntries; -00407 -00408 fail(pFile == NULL); -00409 fail(pImg == NULL); -00410 -00411 if (pImg->uiBitsPerComponent > 8) { -00412 /* No palette, image uses more than 256 colors */ -00413 return TRUE; -00414 } -00415 -00416 if (!pImg->bColorImage) { -00417 /* Only color images can have a palette */ -00418 return FALSE; -00419 } -00420 -00421 if (tLength % 3 != 0) { -00422 /* Each palette entry takes three bytes */ -00423 DBG_DEC(tLength); -00424 return FALSE; -00425 } -00426 -00427 iEntries = (int)(tLength / 3); -00428 DBG_DEC(iEntries); -00429 pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent; -00430 DBG_DEC(pImg->iColorsUsed); -00431 -00432 if (iEntries > 256) { -00433 DBG_DEC(iEntries); -00434 return FALSE; -00435 } -00436 -00437 for (iIndex = 0; iIndex < iEntries; iIndex++) { -00438 pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile); -00439 pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile); -00440 pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile); -00441 NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3); -00442 } -00443 for (;iIndex < pImg->iColorsUsed; iIndex++) { -00444 pImg->aucPalette[iIndex][0] = 0; -00445 pImg->aucPalette[iIndex][1] = 0; -00446 pImg->aucPalette[iIndex][2] = 0; -00447 } -00448 -00449 return TRUE; -00450 } /* end of bFillPalettePNG */ -00451 -00452 /* -00453 * bExaminePNG - Examine a PNG header -00454 * -00455 * return TRUE if successful, otherwise FALSE -00456 */ -00457 static BOOL -00458 bExaminePNG(FILE *pFile, imagedata_type *pImg) -00459 { -00460 size_t tLength; -00461 ULONG ulLong1, ulLong2, ulName; -00462 int iIndex, iTmp; -00463 int iCompressionMethod, iFilterMethod, iInterlaceMethod; -00464 int iColor, iIncrement; -00465 BOOL bHasPalette, bHasAlpha; -00466 UCHAR aucBuf[4]; -00467 -00468 /* Check signature */ -00469 ulLong1 = ulNextLongBE(pFile); -00470 ulLong2 = ulNextLongBE(pFile); -00471 if (ulLong1 != 0x89504e47UL || ulLong2 != 0x0d0a1a0aUL) { -00472 DBG_HEX(ulLong1); -00473 DBG_HEX(ulLong2); -00474 return FALSE; -00475 } -00476 -00477 ulName = 0x00; -00478 bHasPalette = FALSE; -00479 -00480 /* Examine chunks */ -00481 while (ulName != PNG_CN_IEND) { -00482 tLength = (size_t)ulNextLongBE(pFile); -00483 ulName = 0x00; -00484 for (iIndex = 0; iIndex < (int)elementsof(aucBuf); iIndex++) { -00485 aucBuf[iIndex] = (UCHAR)iNextByte(pFile); -00486 if (!isalpha(aucBuf[iIndex])) { -00487 DBG_HEX(aucBuf[iIndex]); -00488 return FALSE; -00489 } -00490 ulName <<= 8; -00491 ulName |= aucBuf[iIndex]; -00492 } -00493 -00494 switch (ulName) { -00495 case PNG_CN_IHDR: -00496 /* Header chunck */ -00497 if (tLength < 13) { -00498 DBG_DEC(tLength); -00499 return FALSE; -00500 } -00501 pImg->iWidth = (int)ulNextLongBE(pFile); -00502 pImg->iHeight = (int)ulNextLongBE(pFile); -00503 pImg->uiBitsPerComponent = (UINT)iNextByte(pFile); -00504 iTmp = iNextByte(pFile); -00505 NO_DBG_HEX(iTmp); -00506 pImg->bColorImage = (iTmp & PNG_CB_COLOR) != 0; -00507 bHasPalette = (iTmp & PNG_CB_PALETTE) != 0; -00508 bHasAlpha = (iTmp & PNG_CB_ALPHA) != 0; -00509 if (bHasPalette && pImg->uiBitsPerComponent > 8) { -00510 /* This should not happen */ -00511 return FALSE; -00512 } -00513 pImg->iComponents = -00514 (bHasPalette || !pImg->bColorImage) ? 1 : 3; -00515 if (bHasAlpha) { -00516 pImg->iComponents++; -00517 } -00518 iCompressionMethod = iNextByte(pFile); -00519 if (iCompressionMethod != 0) { -00520 DBG_DEC(iCompressionMethod); -00521 return FALSE; -00522 } -00523 iFilterMethod = iNextByte(pFile); -00524 if (iFilterMethod != 0) { -00525 DBG_DEC(iFilterMethod); -00526 return FALSE; -00527 } -00528 iInterlaceMethod = iNextByte(pFile); -00529 if (iInterlaceMethod != 0) { -00530 DBG_DEC(iInterlaceMethod); -00531 return FALSE; -00532 } -00533 pImg->iColorsUsed = 0; -00534 (void)tSkipBytes(pFile, tLength - 13 + 4); -00535 break; -00536 case PNG_CN_PLTE: -00537 if (!bHasPalette) { -00538 return FALSE; -00539 } -00540 if (!bFillPalettePNG(pFile, pImg, tLength)) { -00541 return FALSE; -00542 } -00543 (void)tSkipBytes(pFile, 4); -00544 break; -00545 default: -00546 (void)tSkipBytes(pFile, tLength + 4); -00547 break; -00548 } -00549 } -00550 -00551 DBG_DEC(pImg->iWidth); -00552 DBG_DEC(pImg->iHeight); -00553 DBG_DEC(pImg->uiBitsPerComponent); -00554 DBG_DEC(pImg->iColorsUsed); -00555 DBG_DEC(pImg->iComponents); -00556 -00557 /* Do some sanity checks with the parameters */ -00558 if (pImg->iWidth <= 0 || pImg->iHeight <= 0) { -00559 return FALSE; -00560 } -00561 -00562 if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 2 && -00563 pImg->uiBitsPerComponent != 4 && pImg->uiBitsPerComponent != 8 && -00564 pImg->uiBitsPerComponent != 16) { -00565 DBG_DEC(pImg->uiBitsPerComponent); -00566 return FALSE; -00567 } -00568 -00569 if (pImg->iComponents != 1 && pImg->iComponents != 3) { -00570 /* Not supported */ -00571 DBG_DEC(pImg->iComponents); -00572 return FALSE; -00573 } -00574 -00575 if (pImg->uiBitsPerComponent > 8) { -00576 /* Not supported */ -00577 DBG_DEC(pImg->uiBitsPerComponent); -00578 return FALSE; -00579 } -00580 -00581 if (pImg->iColorsUsed == 0 && -00582 pImg->iComponents == 1 && -00583 pImg->uiBitsPerComponent <= 4) { -00584 /* -00585 * No palette is supplied, but PostScript needs one in these -00586 * cases, so we add a default palette here -00587 */ -00588 pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent; -00589 iIncrement = 0xff / (pImg->iColorsUsed - 1); -00590 for (iIndex = 0, iColor = 0x00; -00591 iIndex < pImg->iColorsUsed; -00592 iIndex++, iColor += iIncrement) { -00593 pImg->aucPalette[iIndex][0] = (UCHAR)iColor; -00594 pImg->aucPalette[iIndex][1] = (UCHAR)iColor; -00595 pImg->aucPalette[iIndex][2] = (UCHAR)iColor; -00596 } -00597 /* Just to be sure */ -00598 pImg->bColorImage = FALSE; -00599 } -00600 -00601 pImg->eCompression = compression_zlib; -00602 -00603 return TRUE; -00604 } /* end of bExaminePNG */ -00605 -00606 /* -00607 * bExamineWMF - Examine a WMF header -00608 * -00609 * return TRUE if successful, otherwise FALSE -00610 */ -00611 static BOOL -00612 bExamineWMF(FILE *pFile, imagedata_type *pImg) -00613 { -00614 ULONG ulFileSize, ulMaxRecord, ulMagic; -00615 USHORT usType, usHeaderSize, usVersion, usNoObjects; -00616 -00617 usType = usNextWord(pFile); -00618 usHeaderSize = usNextWord(pFile); -00619 ulMagic = ((ULONG)usHeaderSize << 16) | (ULONG)usType; -00620 usVersion = usNextWord(pFile); -00621 ulFileSize = ulNextLong(pFile); -00622 usNoObjects = usNextWord(pFile); -00623 ulMaxRecord = ulNextLong(pFile); -00624 -00625 DBG_HEX(ulMagic); -00626 DBG_DEC(usType); -00627 DBG_DEC(usHeaderSize); -00628 DBG_HEX(usVersion); -00629 DBG_DEC(ulFileSize); -00630 DBG_DEC(usNoObjects); -00631 DBG_DEC(ulMaxRecord); -00632 -00633 return FALSE; -00634 } /* end of bExamineWMF */ -00635 -00636 #if !defined(__riscos) -00637 /* -00638 * vImage2Papersize - make sure the image fits on the paper -00639 * -00640 * This function should not be needed if Word would do a proper job -00641 */ -00642 static void -00643 vImage2Papersize(imagedata_type *pImg) -00644 { -00645 static int iNetPageHeight = -1; -00646 static int iNetPageWidth = -1; -00647 options_type tOptions; -00648 double dVerFactor, dHorFactor, dFactor; -00649 -00650 DBG_MSG("vImage2Papersize"); -00651 -00652 fail(pImg == NULL); -00653 -00654 if (iNetPageHeight < 0 || iNetPageWidth < 0) { -00655 /* Get the page dimensions from the options */ -00656 vGetOptions(&tOptions); -00657 /* Add 999 to err on the save side */ -00658 iNetPageHeight = tOptions.iPageHeight - -00659 (lDrawUnits2MilliPoints( -00660 PS_TOP_MARGIN + PS_BOTTOM_MARGIN) + -00661 999) / 1000; -00662 iNetPageWidth = tOptions.iPageWidth - -00663 (lDrawUnits2MilliPoints( -00664 PS_LEFT_MARGIN + PS_RIGHT_MARGIN) + -00665 999) / 1000; -00666 DBG_DEC(iNetPageHeight); -00667 DBG_DEC(iNetPageWidth); -00668 } -00669 -00670 if (pImg->iVerSizeScaled < iNetPageHeight && -00671 pImg->iHorSizeScaled < iNetPageWidth) { -00672 /* The image fits on the paper */ -00673 return; -00674 } -00675 -00676 dVerFactor = (double)iNetPageHeight / (double)pImg->iVerSizeScaled; -00677 dHorFactor = (double)iNetPageWidth / (double)pImg->iHorSizeScaled; -00678 dFactor = min(dVerFactor, dHorFactor); -00679 DBG_FLT(dFactor); -00680 /* Round down, just to be on the save side */ -00681 pImg->iVerSizeScaled = (int)(pImg->iVerSizeScaled * dFactor); -00682 pImg->iHorSizeScaled = (int)(pImg->iHorSizeScaled * dFactor); -00683 } /* end of vImage2Papersize */ -00684 #endif /* !__riscos */ -00685 -00686 /* -00687 * tFind6Image - skip until the image is found -00688 * -00689 * Find the image in Word 6/7 files -00690 * -00691 * returns the new position when a image is found, otherwise -1 -00692 */ -00693 static size_t -00694 tFind6Image(FILE *pFile, size_t tPosition, size_t tLength, -00695 imagetype_enum *peImageType) -00696 { -00697 ULONG ulMarker; -00698 size_t tRecordLength, tToSkip; -00699 USHORT usMarker; -00700 -00701 fail(pFile == NULL); -00702 fail(peImageType == NULL); -00703 -00704 *peImageType = imagetype_is_unknown; -00705 if (tPosition + 18 >= tLength) { -00706 return (size_t)-1; -00707 } -00708 -00709 ulMarker = ulNextLong(pFile); -00710 if (ulMarker != 0x00090001) { -00711 DBG_HEX(ulMarker); -00712 return (size_t)-1; -00713 } -00714 usMarker = usNextWord(pFile); -00715 if (usMarker != 0x0300) { -00716 DBG_HEX(usMarker); -00717 return (size_t)-1; -00718 } -00719 (void)tSkipBytes(pFile, 10); -00720 usMarker = usNextWord(pFile); -00721 if (usMarker != 0x0000) { -00722 DBG_HEX(usMarker); -00723 return (size_t)-1; -00724 } -00725 tPosition += 18; -00726 -00727 while (tPosition + 6 <= tLength) { -00728 tRecordLength = (size_t)ulNextLong(pFile); -00729 usMarker = usNextWord(pFile); -00730 tPosition += 6; -00731 NO_DBG_DEC(tRecordLength); -00732 NO_DBG_HEX(usMarker); -00733 switch (usMarker) { -00734 case 0x0000: -00735 DBG_HEX(ulGetDataOffset(pFile)); -00736 return (size_t)-1; -00737 case 0x0b41: -00738 DBG_MSG("DIB"); -00739 *peImageType = imagetype_is_dib; -00740 tPosition += tSkipBytes(pFile, 20); -00741 return tPosition; -00742 case 0x0f43: -00743 DBG_MSG("DIB"); -00744 *peImageType = imagetype_is_dib; -00745 tPosition += tSkipBytes(pFile, 22); -00746 return tPosition; -00747 default: -00748 if (tRecordLength < 3) { -00749 break; -00750 } -00751 if (tRecordLength > SIZE_T_MAX / 2) { -00752 /* -00753 * No need to compute the number of bytes -00754 * to skip -00755 */ -00756 DBG_DEC(tRecordLength); -00757 DBG_HEX(tRecordLength); -00758 DBG_FIXME(); -00759 return (size_t)-1; -00760 } -00761 tToSkip = tRecordLength * 2 - 6; -00762 if (tToSkip > tLength - tPosition) { -00763 /* You can't skip this number of bytes */ -00764 DBG_DEC(tToSkip); -00765 DBG_DEC(tLength - tPosition); -00766 return (size_t)-1; -00767 } -00768 tPosition += tSkipBytes(pFile, tToSkip); -00769 break; -00770 } -00771 } -00772 -00773 return (size_t)-1; -00774 } /* end of tFind6Image */ -00775 -00776 /* -00777 * tFind8Image - skip until the image is found -00778 * -00779 * Find the image in Word 8/9/10 files -00780 * -00781 * returns the new position when a image is found, otherwise -1 -00782 */ -00783 static size_t -00784 tFind8Image(FILE *pFile, size_t tPosition, size_t tLength, -00785 imagetype_enum *peImageType) -00786 { -00787 size_t tRecordLength, tNameLen; -00788 USHORT usRecordVersion, usRecordType, usRecordInstance; -00789 USHORT usTmp; -00790 -00791 fail(pFile == NULL); -00792 fail(peImageType == NULL); -00793 -00794 *peImageType = imagetype_is_unknown; -00795 while (tPosition + 8 <= tLength) { -00796 usTmp = usNextWord(pFile); -00797 usRecordVersion = usTmp & 0x000f; -00798 usRecordInstance = usTmp >> 4; -00799 usRecordType = usNextWord(pFile); -00800 tRecordLength = (size_t)ulNextLong(pFile); -00801 tPosition += 8; -00802 NO_DBG_HEX(usRecordVersion); -00803 NO_DBG_HEX(usRecordInstance); -00804 NO_DBG_HEX(usRecordType); -00805 NO_DBG_DEC(tRecordLength); -00806 switch (usRecordType) { -00807 case 0xf000: case 0xf001: case 0xf002: case 0xf003: -00808 case 0xf004: case 0xf005: -00809 break; -00810 case 0xf007: -00811 tPosition += tSkipBytes(pFile, 33); -00812 tNameLen = (size_t)iNextByte(pFile); -00813 tPosition++; -00814 DBG_DEC_C(tNameLen != 0, tNameLen); -00815 tPosition += tSkipBytes(pFile, 2 + tNameLen * 2); -00816 break; -00817 case 0xf008: -00818 tPosition += tSkipBytes(pFile, 8); -00819 break; -00820 case 0xf009: -00821 tPosition += tSkipBytes(pFile, 16); -00822 break; -00823 case 0xf006: case 0xf00a: case 0xf00b: case 0xf00d: -00824 case 0xf00e: case 0xf00f: case 0xf010: case 0xf011: -00825 case 0xf122: -00826 tPosition += tSkipBytes(pFile, tRecordLength); -00827 break; -00828 case 0xf01a: -00829 DBG_MSG("EMF"); -00830 *peImageType = imagetype_is_emf; -00831 tPosition += tSkipBytes(pFile, 50); -00832 if ((usRecordInstance ^ MSOBI_EMF) == 1) { -00833 tPosition += tSkipBytes(pFile, 16); -00834 } -00835 return tPosition; -00836 case 0xf01b: -00837 DBG_MSG("WMF"); -00838 *peImageType = imagetype_is_wmf; -00839 tPosition += tSkipBytes(pFile, 50); -00840 if ((usRecordInstance ^ MSOBI_WMF) == 1) { -00841 tPosition += tSkipBytes(pFile, 16); -00842 } -00843 return tPosition; -00844 case 0xf01c: -00845 DBG_MSG("PICT"); -00846 *peImageType = imagetype_is_pict; -00847 tPosition += tSkipBytes(pFile, 50); -00848 if ((usRecordInstance ^ MSOBI_PICT) == 1) { -00849 tPosition += tSkipBytes(pFile, 16); -00850 } -00851 return tPosition; -00852 case 0xf01d: -00853 DBG_MSG("JPEG"); -00854 *peImageType = imagetype_is_jpeg; -00855 tPosition += tSkipBytes(pFile, 17); -00856 if ((usRecordInstance ^ MSOBI_JPEG) == 1) { -00857 tPosition += tSkipBytes(pFile, 16); -00858 } -00859 return tPosition; -00860 case 0xf01e: -00861 DBG_MSG("PNG"); -00862 *peImageType = imagetype_is_png; -00863 tPosition += tSkipBytes(pFile, 17); -00864 if ((usRecordInstance ^ MSOBI_PNG) == 1) { -00865 tPosition += tSkipBytes(pFile, 16); -00866 } -00867 return tPosition; -00868 case 0xf01f: -00869 DBG_MSG("DIB"); -00870 /* DIB is a BMP minus its 14 byte header */ -00871 *peImageType = imagetype_is_dib; -00872 tPosition += tSkipBytes(pFile, 17); -00873 if ((usRecordInstance ^ MSOBI_DIB) == 1) { -00874 tPosition += tSkipBytes(pFile, 16); -00875 } -00876 return tPosition; -00877 case 0xf00c: -00878 default: -00879 DBG_HEX(usRecordType); -00880 DBG_DEC_C(tRecordLength % 4 != 0, tRecordLength); -00881 DBG_FIXME(); -00882 return (size_t)-1; -00883 } -00884 } -00885 -00886 return (size_t)-1; -00887 } /* end of tFind8Image */ -00888 -00889 /* -00890 * eExamineImage - Examine the image -00891 * -00892 * Returns an indication of the amount of information found -00893 */ -00894 image_info_enum -00895 eExamineImage(FILE *pFile, ULONG ulFileOffsetImage, imagedata_type *pImg) -00896 { -00897 long lTmp; -00898 size_t tWordHeaderLen, tLength, tPos; -00899 int iType, iHorSize, iVerSize; -00900 USHORT usHorScalingFactor, usVerScalingFactor; -00901 -00902 if (ulFileOffsetImage == FC_INVALID) { -00903 return image_no_information; -00904 } -00905 DBG_HEX(ulFileOffsetImage); -00906 -00907 if (!bSetDataOffset(pFile, ulFileOffsetImage)) { -00908 return image_no_information; -00909 } -00910 -00911 tLength = (size_t)ulNextLong(pFile); -00912 DBG_DEC(tLength); -00913 if (tLength < 46) { -00914 /* Smaller than the smallest known header */ -00915 DBG_FIXME(); -00916 return image_no_information; -00917 } -00918 tWordHeaderLen = (size_t)usNextWord(pFile); -00919 DBG_DEC(tWordHeaderLen); -00920 fail(tWordHeaderLen != 46 && -00921 tWordHeaderLen != 58 && -00922 tWordHeaderLen != 68); -00923 -00924 if (tLength < tWordHeaderLen) { -00925 /* Smaller than the current header */ -00926 return image_no_information; -00927 } -00928 iType = (int)usNextWord(pFile); -00929 DBG_DEC(iType); -00930 (void)tSkipBytes(pFile, 28 - 8); -00931 -00932 lTmp = lTwips2MilliPoints(usNextWord(pFile)); -00933 iHorSize = (int)(lTmp / 1000); -00934 if (lTmp % 1000 != 0) { -00935 iHorSize++; -00936 } -00937 DBG_DEC(iHorSize); -00938 lTmp = lTwips2MilliPoints(usNextWord(pFile)); -00939 iVerSize = (int)(lTmp / 1000); -00940 if (lTmp % 1000 != 0) { -00941 iVerSize++; -00942 } -00943 DBG_DEC(iVerSize); -00944 -00945 usHorScalingFactor = usNextWord(pFile); -00946 DBG_DEC(usHorScalingFactor); -00947 usVerScalingFactor = usNextWord(pFile); -00948 DBG_DEC(usVerScalingFactor); -00949 -00950 /* Sanity checks */ -00951 lTmp = (long)iHorSize * (long)usHorScalingFactor; -00952 if (lTmp < 2835) { -00953 /* This image would be less than 1 millimeter wide */ -00954 DBG_DEC(lTmp); -00955 return image_no_information; -00956 } -00957 lTmp = (long)iVerSize * (long)usVerScalingFactor; -00958 if (lTmp < 2835) { -00959 /* This image would be less than 1 millimeter high */ -00960 DBG_DEC(lTmp); -00961 return image_no_information; -00962 } -00963 -00964 /* Skip the rest of the header */ -00965 (void)tSkipBytes(pFile, tWordHeaderLen - 36); -00966 tPos = tWordHeaderLen; -00967 -00968 (void)memset(pImg, 0, sizeof(*pImg)); -00969 -00970 switch (iType) { -00971 case 7: -00972 case 8: -00973 tPos = tFind6Image(pFile, tPos, tLength, &pImg->eImageType); -00974 if (tPos == (size_t)-1) { -00975 /* No image found */ -00976 return image_no_information; -00977 } -00978 DBG_HEX(tPos); -00979 break; -00980 case 94: /* Word 6/7, no image just a pathname */ -00981 pImg->eImageType = imagetype_is_external; -00982 DBG_HEX(ulFileOffsetImage + tPos); -00983 break; -00984 case 100: -00985 tPos = tFind8Image(pFile, tPos, tLength, &pImg->eImageType); -00986 if (tPos == (size_t)-1) { -00987 /* No image found */ -00988 return image_no_information; -00989 } -00990 DBG_HEX(tPos); -00991 break; -00992 case 102: /* Word 8/9/10, no image just a pathname or URL */ -00993 pImg->eImageType = imagetype_is_external; -00994 DBG_HEX(ulFileOffsetImage + tPos); -00995 break; -00996 default: -00997 DBG_DEC(iType); -00998 DBG_HEX(ulFileOffsetImage + tPos); -00999 DBG_FIXME(); -01000 return image_no_information; -01001 } -01002 -01003 /* Minimal information is now available */ -01004 pImg->tLength = tLength; -01005 pImg->tPosition = tPos; -01006 pImg->iHorSizeScaled = -01007 (int)(((long)iHorSize * (long)usHorScalingFactor + 500) / 1000); -01008 pImg->iVerSizeScaled = -01009 (int)(((long)iVerSize * (long)usVerScalingFactor + 500) / 1000); -01010 #if !defined(__riscos) -01011 vImage2Papersize(pImg); -01012 #endif /* !__riscos */ -01013 -01014 /* Image type specific examinations */ -01015 switch (pImg->eImageType) { -01016 case imagetype_is_dib: -01017 if (bExamineDIB(pFile, pImg)) { -01018 return image_full_information; -01019 } -01020 return image_minimal_information; -01021 case imagetype_is_jpeg: -01022 if (bExamineJPEG(pFile, pImg)) { -01023 return image_full_information; -01024 } -01025 return image_minimal_information; -01026 case imagetype_is_png: -01027 if (bExaminePNG(pFile, pImg)) { -01028 return image_full_information; -01029 } -01030 return image_minimal_information; -01031 case imagetype_is_wmf: -01032 if (bExamineWMF(pFile, pImg)) { -01033 return image_full_information; -01034 } -01035 return image_minimal_information; -01036 case imagetype_is_emf: -01037 case imagetype_is_pict: -01038 case imagetype_is_external: -01039 return image_minimal_information; -01040 case imagetype_is_unknown: -01041 default: -01042 return image_no_information; -01043 } -01044 } /* end of eExamineImage */ -