diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/imgexam_8c_source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/imgexam_8c_source.html Tue Mar 30 16:16:55 2010 +0100 @@ -0,0 +1,1060 @@ + + +
+ +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 */ +