1 /* 2 * imgexam.c 3 * Copyright (C) 2000-2004 A.J. van Os; Released under GNU GPL 4 * 5 * Description: 6 * Functions to examine image headers 7 * 8 *================================================================ 9 * Part of this software is based on: 10 * jpeg2ps - convert JPEG compressed images to PostScript Level 2 11 * Copyright (C) 1994-99 Thomas Merz (tm@muc.de) 12 *================================================================ 13 * The credit should go to him, but all the bugs are mine. 14 */ 15 16 #include <stdio.h> 17 #include <string.h> 18 #include <ctype.h> 19 #include "antiword.h" 20 21 /* BMP compression types */ 22 #define BI_RGB 0 23 #define BI_RLE8 1 24 #define BI_RLE4 2 25 26 /* PNG colortype bits */ 27 #define PNG_CB_PALETTE 0x01 28 #define PNG_CB_COLOR 0x02 29 #define PNG_CB_ALPHA 0x04 30 31 /* Instance signature */ 32 #define MSOBI_WMF 0x0216 33 #define MSOBI_EMF 0x03d4 34 #define MSOBI_PICT 0x0542 35 #define MSOBI_PNG 0x06e0 36 #define MSOBI_JPEG 0x046a 37 #define MSOBI_DIB 0x07a8 38 39 /* The following enum is stolen from the IJG JPEG library */ 40 typedef enum { /* JPEG marker codes */ 41 M_SOF0 = 0xc0, /* baseline DCT */ 42 M_SOF1 = 0xc1, /* extended sequential DCT */ 43 M_SOF2 = 0xc2, /* progressive DCT */ 44 M_SOF3 = 0xc3, /* lossless (sequential) */ 45 46 M_SOF5 = 0xc5, /* differential sequential DCT */ 47 M_SOF6 = 0xc6, /* differential progressive DCT */ 48 M_SOF7 = 0xc7, /* differential lossless */ 49 50 M_JPG = 0xc8, /* JPEG extensions */ 51 M_SOF9 = 0xc9, /* extended sequential DCT */ 52 M_SOF10 = 0xca, /* progressive DCT */ 53 M_SOF11 = 0xcb, /* lossless (sequential) */ 54 55 M_SOF13 = 0xcd, /* differential sequential DCT */ 56 M_SOF14 = 0xce, /* differential progressive DCT */ 57 M_SOF15 = 0xcf, /* differential lossless */ 58 59 M_DHT = 0xc4, /* define Huffman tables */ 60 61 M_DAC = 0xcc, /* define arithmetic conditioning table */ 62 63 M_RST0 = 0xd0, /* restart */ 64 M_RST1 = 0xd1, /* restart */ 65 M_RST2 = 0xd2, /* restart */ 66 M_RST3 = 0xd3, /* restart */ 67 M_RST4 = 0xd4, /* restart */ 68 M_RST5 = 0xd5, /* restart */ 69 M_RST6 = 0xd6, /* restart */ 70 M_RST7 = 0xd7, /* restart */ 71 72 M_SOI = 0xd8, /* start of image */ 73 M_EOI = 0xd9, /* end of image */ 74 M_SOS = 0xda, /* start of scan */ 75 M_DQT = 0xdb, /* define quantization tables */ 76 M_DNL = 0xdc, /* define number of lines */ 77 M_DRI = 0xdd, /* define restart interval */ 78 M_DHP = 0xde, /* define hierarchical progression */ 79 M_EXP = 0xdf, /* expand reference image(s) */ 80 81 M_APP0 = 0xe0, /* application marker, used for JFIF */ 82 M_APP1 = 0xe1, /* application marker */ 83 M_APP2 = 0xe2, /* application marker */ 84 M_APP3 = 0xe3, /* application marker */ 85 M_APP4 = 0xe4, /* application marker */ 86 M_APP5 = 0xe5, /* application marker */ 87 M_APP6 = 0xe6, /* application marker */ 88 M_APP7 = 0xe7, /* application marker */ 89 M_APP8 = 0xe8, /* application marker */ 90 M_APP9 = 0xe9, /* application marker */ 91 M_APP10 = 0xea, /* application marker */ 92 M_APP11 = 0xeb, /* application marker */ 93 M_APP12 = 0xec, /* application marker */ 94 M_APP13 = 0xed, /* application marker */ 95 M_APP14 = 0xee, /* application marker, used by Adobe */ 96 M_APP15 = 0xef, /* application marker */ 97 98 M_JPG0 = 0xf0, /* reserved for JPEG extensions */ 99 M_JPG13 = 0xfd, /* reserved for JPEG extensions */ 100 M_COM = 0xfe, /* comment */ 101 102 M_TEM = 0x01 /* temporary use */ 103 } JPEG_MARKER; 104 105 106 /* 107 * bFillPaletteDIB - fill the palette part of the imagesdata 108 * 109 * returns TRUE if the images must be a color image, otherwise FALSE; 110 */ 111 static BOOL 112 bFillPaletteDIB(FILE *pFile, imagedata_type *pImg, BOOL bNewFormat) 113 { 114 int iIndex; 115 BOOL bIsColorPalette; 116 117 fail(pFile == NULL); 118 fail(pImg == NULL); 119 120 if (pImg->uiBitsPerComponent > 8) { 121 /* No palette, image uses more than 256 colors */ 122 return TRUE; 123 } 124 125 if (pImg->iColorsUsed <= 0) { 126 /* Not specified, so compute the number of colors used */ 127 pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent; 128 } 129 130 fail(pImg->iColorsUsed > 256); 131 if (pImg->iColorsUsed > 256) { 132 pImg->iColorsUsed = 256; 133 } 134 135 bIsColorPalette = FALSE; 136 for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) { 137 /* From BGR order to RGB order */ 138 pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile); 139 pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile); 140 pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile); 141 if (bNewFormat) { 142 (void)iNextByte(pFile); 143 } 144 NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3); 145 if (pImg->aucPalette[iIndex][0] != 146 pImg->aucPalette[iIndex][1] || 147 pImg->aucPalette[iIndex][1] != 148 pImg->aucPalette[iIndex][2]) { 149 bIsColorPalette = TRUE; 150 } 151 } 152 153 return bIsColorPalette; 154 } /* end of bFillPaletteDIB */ 155 156 /* 157 * bExamineDIB - Examine a DIB header 158 * 159 * return TRUE if successful, otherwise FALSE 160 */ 161 static BOOL 162 bExamineDIB(FILE *pFile, imagedata_type *pImg) 163 { 164 size_t tHeaderSize; 165 int iPlanes, iCompression; 166 167 tHeaderSize = (size_t)ulNextLong(pFile); 168 switch (tHeaderSize) { 169 case 12: 170 pImg->iWidth = (int)usNextWord(pFile); 171 pImg->iHeight = (int)usNextWord(pFile); 172 iPlanes = (int)usNextWord(pFile); 173 pImg->uiBitsPerComponent = (UINT)usNextWord(pFile); 174 iCompression = BI_RGB; 175 pImg->iColorsUsed = 0; 176 break; 177 case 40: 178 case 64: 179 pImg->iWidth = (int)ulNextLong(pFile); 180 pImg->iHeight = (int)ulNextLong(pFile); 181 iPlanes = (int)usNextWord(pFile); 182 pImg->uiBitsPerComponent = (UINT)usNextWord(pFile); 183 iCompression = (int)ulNextLong(pFile); 184 (void)tSkipBytes(pFile, 12); 185 pImg->iColorsUsed = (int)ulNextLong(pFile); 186 (void)tSkipBytes(pFile, tHeaderSize - 36); 187 break; 188 default: 189 DBG_DEC(tHeaderSize); 190 return FALSE; 191 } 192 DBG_DEC(pImg->iWidth); 193 DBG_DEC(pImg->iHeight); 194 DBG_DEC(pImg->uiBitsPerComponent); 195 DBG_DEC(iCompression); 196 DBG_DEC(pImg->iColorsUsed); 197 198 /* Do some sanity checks with the parameters */ 199 if (iPlanes != 1) { 200 DBG_DEC(iPlanes); 201 return FALSE; 202 } 203 if (pImg->iWidth <= 0 || pImg->iHeight <= 0) { 204 DBG_DEC(pImg->iWidth); 205 DBG_DEC(pImg->iHeight); 206 return FALSE; 207 } 208 if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 4 && 209 pImg->uiBitsPerComponent != 8 && pImg->uiBitsPerComponent != 24) { 210 DBG_DEC(pImg->uiBitsPerComponent); 211 return FALSE; 212 } 213 if (iCompression != BI_RGB && 214 (pImg->uiBitsPerComponent == 1 || pImg->uiBitsPerComponent == 24)) { 215 return FALSE; 216 } 217 if (iCompression == BI_RLE8 && pImg->uiBitsPerComponent == 4) { 218 return FALSE; 219 } 220 if (iCompression == BI_RLE4 && pImg->uiBitsPerComponent == 8) { 221 return FALSE; 222 } 223 224 switch (iCompression) { 225 case BI_RGB: 226 pImg->eCompression = compression_none; 227 break; 228 case BI_RLE4: 229 pImg->eCompression = compression_rle4; 230 break; 231 case BI_RLE8: 232 pImg->eCompression = compression_rle8; 233 break; 234 default: 235 DBG_DEC(iCompression); 236 return FALSE; 237 } 238 239 pImg->bColorImage = bFillPaletteDIB(pFile, pImg, tHeaderSize > 12); 240 241 if (pImg->uiBitsPerComponent <= 8) { 242 pImg->iComponents = 1; 243 } else { 244 pImg->iComponents = (int)(pImg->uiBitsPerComponent / 8); 245 } 246 247 return TRUE; 248 } /* end of bExamineDIB */ 249 250 /* 251 * iNextMarker - read the next JPEG marker 252 */ 253 static int 254 iNextMarker(FILE *pFile) 255 { 256 int iMarker; 257 258 do { 259 do { 260 iMarker = iNextByte(pFile); 261 } while (iMarker != 0xff && iMarker != EOF); 262 if (iMarker == EOF) { 263 return EOF; 264 } 265 do { 266 iMarker = iNextByte(pFile); 267 } while (iMarker == 0xff); 268 } while (iMarker == 0x00); /* repeat if ff/00 */ 269 270 return iMarker; 271 } /* end of iNextMarker */ 272 273 /* 274 * bExamineJPEG - Examine a JPEG header 275 * 276 * return TRUE if successful, otherwise FALSE 277 */ 278 static BOOL 279 bExamineJPEG(FILE *pFile, imagedata_type *pImg) 280 { 281 size_t tLength; 282 int iMarker, iIndex; 283 char appstring[10]; 284 BOOL bSOFDone; 285 286 tLength = 0; 287 bSOFDone = FALSE; 288 289 /* process JPEG markers */ 290 while (!bSOFDone && (iMarker = iNextMarker(pFile)) != (int)M_EOI) { 291 switch (iMarker) { 292 case EOF: 293 DBG_MSG("Error: unexpected end of JPEG file"); 294 return FALSE; 295 /* The following are not officially supported in PostScript level 2 */ 296 case M_SOF2: 297 case M_SOF3: 298 case M_SOF5: 299 case M_SOF6: 300 case M_SOF7: 301 case M_SOF9: 302 case M_SOF10: 303 case M_SOF11: 304 case M_SOF13: 305 case M_SOF14: 306 case M_SOF15: 307 DBG_HEX(iMarker); 308 return FALSE; 309 case M_SOF0: 310 case M_SOF1: 311 tLength = (size_t)usNextWordBE(pFile); 312 pImg->uiBitsPerComponent = (UINT)iNextByte(pFile); 313 pImg->iHeight = (int)usNextWordBE(pFile); 314 pImg->iWidth = (int)usNextWordBE(pFile); 315 pImg->iComponents = iNextByte(pFile); 316 bSOFDone = TRUE; 317 break; 318 case M_APP14: 319 /* 320 * Check for Adobe application marker. It is known (per Adobe's 321 * TN5116) to contain the string "Adobe" at the start of the 322 * APP14 marker. 323 */ 324 tLength = (size_t)usNextWordBE(pFile); 325 if (tLength < 12) { 326 (void)tSkipBytes(pFile, tLength - 2); 327 } else { 328 for (iIndex = 0; iIndex < 5; iIndex++) { 329 appstring[iIndex] = 330 (char)iNextByte(pFile); 331 } 332 appstring[5] = '\0'; 333 if (STREQ(appstring, "Adobe")) { 334 pImg->bAdobe = TRUE; 335 } 336 (void)tSkipBytes(pFile, tLength - 7); 337 } 338 break; 339 case M_SOI: /* ignore markers without parameters */ 340 case M_EOI: 341 case M_TEM: 342 case M_RST0: 343 case M_RST1: 344 case M_RST2: 345 case M_RST3: 346 case M_RST4: 347 case M_RST5: 348 case M_RST6: 349 case M_RST7: 350 break; 351 default: /* skip variable length markers */ 352 tLength = (size_t)usNextWordBE(pFile); 353 (void)tSkipBytes(pFile, tLength - 2); 354 break; 355 } 356 } 357 358 DBG_DEC(pImg->iWidth); 359 DBG_DEC(pImg->iHeight); 360 DBG_DEC(pImg->uiBitsPerComponent); 361 DBG_DEC(pImg->iComponents); 362 363 /* Do some sanity checks with the parameters */ 364 if (pImg->iHeight <= 0 || 365 pImg->iWidth <= 0 || 366 pImg->iComponents <= 0) { 367 DBG_DEC(pImg->iHeight); 368 DBG_DEC(pImg->iWidth); 369 DBG_DEC(pImg->iComponents); 370 return FALSE; 371 } 372 373 /* Some broken JPEG files have this but they print anyway... */ 374 if (pImg->iComponents * 3 + 8 != (int)tLength) { 375 DBG_MSG("Warning: SOF marker has incorrect length - ignored"); 376 } 377 378 if (pImg->uiBitsPerComponent != 8) { 379 DBG_DEC(pImg->uiBitsPerComponent); 380 DBG_MSG("Not supported in PostScript level 2"); 381 return FALSE; 382 } 383 384 if (pImg->iComponents != 1 && 385 pImg->iComponents != 3 && 386 pImg->iComponents != 4) { 387 DBG_DEC(pImg->iComponents); 388 return FALSE; 389 } 390 391 pImg->bColorImage = pImg->iComponents >= 3; 392 pImg->iColorsUsed = 0; 393 pImg->eCompression = compression_jpeg; 394 395 return TRUE; 396 } /* end of bExamineJPEG */ 397 398 /* 399 * bFillPalettePNG - fill the palette part of the imagesdata 400 * 401 * returns TRUE if sucessful, otherwise FALSE; 402 */ 403 static BOOL 404 bFillPalettePNG(FILE *pFile, imagedata_type *pImg, size_t tLength) 405 { 406 int iIndex, iEntries; 407 408 fail(pFile == NULL); 409 fail(pImg == NULL); 410 411 if (pImg->uiBitsPerComponent > 8) { 412 /* No palette, image uses more than 256 colors */ 413 return TRUE; 414 } 415 416 if (!pImg->bColorImage) { 417 /* Only color images can have a palette */ 418 return FALSE; 419 } 420 421 if (tLength % 3 != 0) { 422 /* Each palette entry takes three bytes */ 423 DBG_DEC(tLength); 424 return FALSE; 425 } 426 427 iEntries = (int)(tLength / 3); 428 DBG_DEC(iEntries); 429 pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent; 430 DBG_DEC(pImg->iColorsUsed); 431 432 if (iEntries > 256) { 433 DBG_DEC(iEntries); 434 return FALSE; 435 } 436 437 for (iIndex = 0; iIndex < iEntries; iIndex++) { 438 pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile); 439 pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile); 440 pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile); 441 NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3); 442 } 443 for (;iIndex < pImg->iColorsUsed; iIndex++) { 444 pImg->aucPalette[iIndex][0] = 0; 445 pImg->aucPalette[iIndex][1] = 0; 446 pImg->aucPalette[iIndex][2] = 0; 447 } 448 449 return TRUE; 450 } /* end of bFillPalettePNG */ 451 452 /* 453 * bExaminePNG - Examine a PNG header 454 * 455 * return TRUE if successful, otherwise FALSE 456 */ 457 static BOOL 458 bExaminePNG(FILE *pFile, imagedata_type *pImg) 459 { 460 size_t tLength; 461 ULONG ulLong1, ulLong2, ulName; 462 int iIndex, iTmp; 463 int iCompressionMethod, iFilterMethod, iInterlaceMethod; 464 int iColor, iIncrement; 465 BOOL bHasPalette, bHasAlpha; 466 UCHAR aucBuf[4]; 467 468 /* Check signature */ 469 ulLong1 = ulNextLongBE(pFile); 470 ulLong2 = ulNextLongBE(pFile); 471 if (ulLong1 != 0x89504e47UL || ulLong2 != 0x0d0a1a0aUL) { 472 DBG_HEX(ulLong1); 473 DBG_HEX(ulLong2); 474 return FALSE; 475 } 476 477 ulName = 0x00; 478 bHasPalette = FALSE; 479 480 /* Examine chunks */ 481 while (ulName != PNG_CN_IEND) { 482 tLength = (size_t)ulNextLongBE(pFile); 483 ulName = 0x00; 484 for (iIndex = 0; iIndex < (int)elementsof(aucBuf); iIndex++) { 485 aucBuf[iIndex] = (UCHAR)iNextByte(pFile); 486 if (!isalpha(aucBuf[iIndex])) { 487 DBG_HEX(aucBuf[iIndex]); 488 return FALSE; 489 } 490 ulName <<= 8; 491 ulName |= aucBuf[iIndex]; 492 } 493 494 switch (ulName) { 495 case PNG_CN_IHDR: 496 /* Header chunck */ 497 if (tLength < 13) { 498 DBG_DEC(tLength); 499 return FALSE; 500 } 501 pImg->iWidth = (int)ulNextLongBE(pFile); 502 pImg->iHeight = (int)ulNextLongBE(pFile); 503 pImg->uiBitsPerComponent = (UINT)iNextByte(pFile); 504 iTmp = iNextByte(pFile); 505 NO_DBG_HEX(iTmp); 506 pImg->bColorImage = (iTmp & PNG_CB_COLOR) != 0; 507 bHasPalette = (iTmp & PNG_CB_PALETTE) != 0; 508 bHasAlpha = (iTmp & PNG_CB_ALPHA) != 0; 509 if (bHasPalette && pImg->uiBitsPerComponent > 8) { 510 /* This should not happen */ 511 return FALSE; 512 } 513 pImg->iComponents = 514 (bHasPalette || !pImg->bColorImage) ? 1 : 3; 515 if (bHasAlpha) { 516 pImg->iComponents++; 517 } 518 iCompressionMethod = iNextByte(pFile); 519 if (iCompressionMethod != 0) { 520 DBG_DEC(iCompressionMethod); 521 return FALSE; 522 } 523 iFilterMethod = iNextByte(pFile); 524 if (iFilterMethod != 0) { 525 DBG_DEC(iFilterMethod); 526 return FALSE; 527 } 528 iInterlaceMethod = iNextByte(pFile); 529 if (iInterlaceMethod != 0) { 530 DBG_DEC(iInterlaceMethod); 531 return FALSE; 532 } 533 pImg->iColorsUsed = 0; 534 (void)tSkipBytes(pFile, tLength - 13 + 4); 535 break; 536 case PNG_CN_PLTE: 537 if (!bHasPalette) { 538 return FALSE; 539 } 540 if (!bFillPalettePNG(pFile, pImg, tLength)) { 541 return FALSE; 542 } 543 (void)tSkipBytes(pFile, 4); 544 break; 545 default: 546 (void)tSkipBytes(pFile, tLength + 4); 547 break; 548 } 549 } 550 551 DBG_DEC(pImg->iWidth); 552 DBG_DEC(pImg->iHeight); 553 DBG_DEC(pImg->uiBitsPerComponent); 554 DBG_DEC(pImg->iColorsUsed); 555 DBG_DEC(pImg->iComponents); 556 557 /* Do some sanity checks with the parameters */ 558 if (pImg->iWidth <= 0 || pImg->iHeight <= 0) { 559 return FALSE; 560 } 561 562 if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 2 && 563 pImg->uiBitsPerComponent != 4 && pImg->uiBitsPerComponent != 8 && 564 pImg->uiBitsPerComponent != 16) { 565 DBG_DEC(pImg->uiBitsPerComponent); 566 return FALSE; 567 } 568 569 if (pImg->iComponents != 1 && pImg->iComponents != 3) { 570 /* Not supported */ 571 DBG_DEC(pImg->iComponents); 572 return FALSE; 573 } 574 575 if (pImg->uiBitsPerComponent > 8) { 576 /* Not supported */ 577 DBG_DEC(pImg->uiBitsPerComponent); 578 return FALSE; 579 } 580 581 if (pImg->iColorsUsed == 0 && 582 pImg->iComponents == 1 && 583 pImg->uiBitsPerComponent <= 4) { 584 /* 585 * No palette is supplied, but PostScript needs one in these 586 * cases, so we add a default palette here 587 */ 588 pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent; 589 iIncrement = 0xff / (pImg->iColorsUsed - 1); 590 for (iIndex = 0, iColor = 0x00; 591 iIndex < pImg->iColorsUsed; 592 iIndex++, iColor += iIncrement) { 593 pImg->aucPalette[iIndex][0] = (UCHAR)iColor; 594 pImg->aucPalette[iIndex][1] = (UCHAR)iColor; 595 pImg->aucPalette[iIndex][2] = (UCHAR)iColor; 596 } 597 /* Just to be sure */ 598 pImg->bColorImage = FALSE; 599 } 600 601 pImg->eCompression = compression_zlib; 602 603 return TRUE; 604 } /* end of bExaminePNG */ 605 606 /* 607 * bExamineWMF - Examine a WMF header 608 * 609 * return TRUE if successful, otherwise FALSE 610 */ 611 static BOOL 612 bExamineWMF(FILE *pFile, imagedata_type *pImg) 613 { 614 ULONG ulFileSize, ulMaxRecord, ulMagic; 615 USHORT usType, usHeaderSize, usVersion, usNoObjects; 616 617 usType = usNextWord(pFile); 618 usHeaderSize = usNextWord(pFile); 619 ulMagic = ((ULONG)usHeaderSize << 16) | (ULONG)usType; 620 usVersion = usNextWord(pFile); 621 ulFileSize = ulNextLong(pFile); 622 usNoObjects = usNextWord(pFile); 623 ulMaxRecord = ulNextLong(pFile); 624 625 DBG_HEX(ulMagic); 626 DBG_DEC(usType); 627 DBG_DEC(usHeaderSize); 628 DBG_HEX(usVersion); 629 DBG_DEC(ulFileSize); 630 DBG_DEC(usNoObjects); 631 DBG_DEC(ulMaxRecord); 632 633 return FALSE; 634 } /* end of bExamineWMF */ 635 636 #if !defined(__riscos) 637 /* 638 * vImage2Papersize - make sure the image fits on the paper 639 * 640 * This function should not be needed if Word would do a proper job 641 */ 642 static void 643 vImage2Papersize(imagedata_type *pImg) 644 { 645 static int iNetPageHeight = -1; 646 static int iNetPageWidth = -1; 647 options_type tOptions; 648 double dVerFactor, dHorFactor, dFactor; 649 650 DBG_MSG("vImage2Papersize"); 651 652 fail(pImg == NULL); 653 654 if (iNetPageHeight < 0 || iNetPageWidth < 0) { 655 /* Get the page dimensions from the options */ 656 vGetOptions(&tOptions); 657 /* Add 999 to err on the save side */ 658 iNetPageHeight = tOptions.iPageHeight - 659 (lDrawUnits2MilliPoints( 660 PS_TOP_MARGIN + PS_BOTTOM_MARGIN) + 661 999) / 1000; 662 iNetPageWidth = tOptions.iPageWidth - 663 (lDrawUnits2MilliPoints( 664 PS_LEFT_MARGIN + PS_RIGHT_MARGIN) + 665 999) / 1000; 666 DBG_DEC(iNetPageHeight); 667 DBG_DEC(iNetPageWidth); 668 } 669 670 if (pImg->iVerSizeScaled < iNetPageHeight && 671 pImg->iHorSizeScaled < iNetPageWidth) { 672 /* The image fits on the paper */ 673 return; 674 } 675 676 dVerFactor = (double)iNetPageHeight / (double)pImg->iVerSizeScaled; 677 dHorFactor = (double)iNetPageWidth / (double)pImg->iHorSizeScaled; 678 dFactor = min(dVerFactor, dHorFactor); 679 DBG_FLT(dFactor); 680 /* Round down, just to be on the save side */ 681 pImg->iVerSizeScaled = (int)(pImg->iVerSizeScaled * dFactor); 682 pImg->iHorSizeScaled = (int)(pImg->iHorSizeScaled * dFactor); 683 } /* end of vImage2Papersize */ 684 #endif /* !__riscos */ 685 686 /* 687 * tFind6Image - skip until the image is found 688 * 689 * Find the image in Word 6/7 files 690 * 691 * returns the new position when a image is found, otherwise -1 692 */ 693 static size_t 694 tFind6Image(FILE *pFile, size_t tPosition, size_t tLength, 695 imagetype_enum *peImageType) 696 { 697 ULONG ulMarker; 698 size_t tRecordLength, tToSkip; 699 USHORT usMarker; 700 701 fail(pFile == NULL); 702 fail(peImageType == NULL); 703 704 *peImageType = imagetype_is_unknown; 705 if (tPosition + 18 >= tLength) { 706 return (size_t)-1; 707 } 708 709 ulMarker = ulNextLong(pFile); 710 if (ulMarker != 0x00090001) { 711 DBG_HEX(ulMarker); 712 return (size_t)-1; 713 } 714 usMarker = usNextWord(pFile); 715 if (usMarker != 0x0300) { 716 DBG_HEX(usMarker); 717 return (size_t)-1; 718 } 719 (void)tSkipBytes(pFile, 10); 720 usMarker = usNextWord(pFile); 721 if (usMarker != 0x0000) { 722 DBG_HEX(usMarker); 723 return (size_t)-1; 724 } 725 tPosition += 18; 726 727 while (tPosition + 6 <= tLength) { 728 tRecordLength = (size_t)ulNextLong(pFile); 729 usMarker = usNextWord(pFile); 730 tPosition += 6; 731 NO_DBG_DEC(tRecordLength); 732 NO_DBG_HEX(usMarker); 733 switch (usMarker) { 734 case 0x0000: 735 DBG_HEX(ulGetDataOffset(pFile)); 736 return (size_t)-1; 737 case 0x0b41: 738 DBG_MSG("DIB"); 739 *peImageType = imagetype_is_dib; 740 tPosition += tSkipBytes(pFile, 20); 741 return tPosition; 742 case 0x0f43: 743 DBG_MSG("DIB"); 744 *peImageType = imagetype_is_dib; 745 tPosition += tSkipBytes(pFile, 22); 746 return tPosition; 747 default: 748 if (tRecordLength < 3) { 749 break; 750 } 751 if (tRecordLength > SIZE_T_MAX / 2) { 752 /* 753 * No need to compute the number of bytes 754 * to skip 755 */ 756 DBG_DEC(tRecordLength); 757 DBG_HEX(tRecordLength); 758 DBG_FIXME(); 759 return (size_t)-1; 760 } 761 tToSkip = tRecordLength * 2 - 6; 762 if (tToSkip > tLength - tPosition) { 763 /* You can't skip this number of bytes */ 764 DBG_DEC(tToSkip); 765 DBG_DEC(tLength - tPosition); 766 return (size_t)-1; 767 } 768 tPosition += tSkipBytes(pFile, tToSkip); 769 break; 770 } 771 } 772 773 return (size_t)-1; 774 } /* end of tFind6Image */ 775 776 /* 777 * tFind8Image - skip until the image is found 778 * 779 * Find the image in Word 8/9/10 files 780 * 781 * returns the new position when a image is found, otherwise -1 782 */ 783 static size_t 784 tFind8Image(FILE *pFile, size_t tPosition, size_t tLength, 785 imagetype_enum *peImageType) 786 { 787 size_t tRecordLength, tNameLen; 788 USHORT usRecordVersion, usRecordType, usRecordInstance; 789 USHORT usTmp; 790 791 fail(pFile == NULL); 792 fail(peImageType == NULL); 793 794 *peImageType = imagetype_is_unknown; 795 while (tPosition + 8 <= tLength) { 796 usTmp = usNextWord(pFile); 797 usRecordVersion = usTmp & 0x000f; 798 usRecordInstance = usTmp >> 4; 799 usRecordType = usNextWord(pFile); 800 tRecordLength = (size_t)ulNextLong(pFile); 801 tPosition += 8; 802 NO_DBG_HEX(usRecordVersion); 803 NO_DBG_HEX(usRecordInstance); 804 NO_DBG_HEX(usRecordType); 805 NO_DBG_DEC(tRecordLength); 806 switch (usRecordType) { 807 case 0xf000: case 0xf001: case 0xf002: case 0xf003: 808 case 0xf004: case 0xf005: 809 break; 810 case 0xf007: 811 tPosition += tSkipBytes(pFile, 33); 812 tNameLen = (size_t)iNextByte(pFile); 813 tPosition++; 814 DBG_DEC_C(tNameLen != 0, tNameLen); 815 tPosition += tSkipBytes(pFile, 2 + tNameLen * 2); 816 break; 817 case 0xf008: 818 tPosition += tSkipBytes(pFile, 8); 819 break; 820 case 0xf009: 821 tPosition += tSkipBytes(pFile, 16); 822 break; 823 case 0xf006: case 0xf00a: case 0xf00b: case 0xf00d: 824 case 0xf00e: case 0xf00f: case 0xf010: case 0xf011: 825 case 0xf122: 826 tPosition += tSkipBytes(pFile, tRecordLength); 827 break; 828 case 0xf01a: 829 DBG_MSG("EMF"); 830 *peImageType = imagetype_is_emf; 831 tPosition += tSkipBytes(pFile, 50); 832 if ((usRecordInstance ^ MSOBI_EMF) == 1) { 833 tPosition += tSkipBytes(pFile, 16); 834 } 835 return tPosition; 836 case 0xf01b: 837 DBG_MSG("WMF"); 838 *peImageType = imagetype_is_wmf; 839 tPosition += tSkipBytes(pFile, 50); 840 if ((usRecordInstance ^ MSOBI_WMF) == 1) { 841 tPosition += tSkipBytes(pFile, 16); 842 } 843 return tPosition; 844 case 0xf01c: 845 DBG_MSG("PICT"); 846 *peImageType = imagetype_is_pict; 847 tPosition += tSkipBytes(pFile, 50); 848 if ((usRecordInstance ^ MSOBI_PICT) == 1) { 849 tPosition += tSkipBytes(pFile, 16); 850 } 851 return tPosition; 852 case 0xf01d: 853 DBG_MSG("JPEG"); 854 *peImageType = imagetype_is_jpeg; 855 tPosition += tSkipBytes(pFile, 17); 856 if ((usRecordInstance ^ MSOBI_JPEG) == 1) { 857 tPosition += tSkipBytes(pFile, 16); 858 } 859 return tPosition; 860 case 0xf01e: 861 DBG_MSG("PNG"); 862 *peImageType = imagetype_is_png; 863 tPosition += tSkipBytes(pFile, 17); 864 if ((usRecordInstance ^ MSOBI_PNG) == 1) { 865 tPosition += tSkipBytes(pFile, 16); 866 } 867 return tPosition; 868 case 0xf01f: 869 DBG_MSG("DIB"); 870 /* DIB is a BMP minus its 14 byte header */ 871 *peImageType = imagetype_is_dib; 872 tPosition += tSkipBytes(pFile, 17); 873 if ((usRecordInstance ^ MSOBI_DIB) == 1) { 874 tPosition += tSkipBytes(pFile, 16); 875 } 876 return tPosition; 877 case 0xf00c: 878 default: 879 DBG_HEX(usRecordType); 880 DBG_DEC_C(tRecordLength % 4 != 0, tRecordLength); 881 DBG_FIXME(); 882 return (size_t)-1; 883 } 884 } 885 886 return (size_t)-1; 887 } /* end of tFind8Image */ 888 889 /* 890 * eExamineImage - Examine the image 891 * 892 * Returns an indication of the amount of information found 893 */ 894 image_info_enum 895 eExamineImage(FILE *pFile, ULONG ulFileOffsetImage, imagedata_type *pImg) 896 { 897 long lTmp; 898 size_t tWordHeaderLen, tLength, tPos; 899 int iType, iHorSize, iVerSize; 900 USHORT usHorScalingFactor, usVerScalingFactor; 901 902 if (ulFileOffsetImage == FC_INVALID) { 903 return image_no_information; 904 } 905 DBG_HEX(ulFileOffsetImage); 906 907 if (!bSetDataOffset(pFile, ulFileOffsetImage)) { 908 return image_no_information; 909 } 910 911 tLength = (size_t)ulNextLong(pFile); 912 DBG_DEC(tLength); 913 if (tLength < 46) { 914 /* Smaller than the smallest known header */ 915 DBG_FIXME(); 916 return image_no_information; 917 } 918 tWordHeaderLen = (size_t)usNextWord(pFile); 919 DBG_DEC(tWordHeaderLen); 920 fail(tWordHeaderLen != 46 && 921 tWordHeaderLen != 58 && 922 tWordHeaderLen != 68); 923 924 if (tLength < tWordHeaderLen) { 925 /* Smaller than the current header */ 926 return image_no_information; 927 } 928 iType = (int)usNextWord(pFile); 929 DBG_DEC(iType); 930 (void)tSkipBytes(pFile, 28 - 8); 931 932 lTmp = lTwips2MilliPoints(usNextWord(pFile)); 933 iHorSize = (int)(lTmp / 1000); 934 if (lTmp % 1000 != 0) { 935 iHorSize++; 936 } 937 DBG_DEC(iHorSize); 938 lTmp = lTwips2MilliPoints(usNextWord(pFile)); 939 iVerSize = (int)(lTmp / 1000); 940 if (lTmp % 1000 != 0) { 941 iVerSize++; 942 } 943 DBG_DEC(iVerSize); 944 945 usHorScalingFactor = usNextWord(pFile); 946 DBG_DEC(usHorScalingFactor); 947 usVerScalingFactor = usNextWord(pFile); 948 DBG_DEC(usVerScalingFactor); 949 950 /* Sanity checks */ 951 lTmp = (long)iHorSize * (long)usHorScalingFactor; 952 if (lTmp < 2835) { 953 /* This image would be less than 1 millimeter wide */ 954 DBG_DEC(lTmp); 955 return image_no_information; 956 } 957 lTmp = (long)iVerSize * (long)usVerScalingFactor; 958 if (lTmp < 2835) { 959 /* This image would be less than 1 millimeter high */ 960 DBG_DEC(lTmp); 961 return image_no_information; 962 } 963 964 /* Skip the rest of the header */ 965 (void)tSkipBytes(pFile, tWordHeaderLen - 36); 966 tPos = tWordHeaderLen; 967 968 (void)memset(pImg, 0, sizeof(*pImg)); 969 970 switch (iType) { 971 case 7: 972 case 8: 973 tPos = tFind6Image(pFile, tPos, tLength, &pImg->eImageType); 974 if (tPos == (size_t)-1) { 975 /* No image found */ 976 return image_no_information; 977 } 978 DBG_HEX(tPos); 979 break; 980 case 94: /* Word 6/7, no image just a pathname */ 981 pImg->eImageType = imagetype_is_external; 982 DBG_HEX(ulFileOffsetImage + tPos); 983 break; 984 case 100: 985 tPos = tFind8Image(pFile, tPos, tLength, &pImg->eImageType); 986 if (tPos == (size_t)-1) { 987 /* No image found */ 988 return image_no_information; 989 } 990 DBG_HEX(tPos); 991 break; 992 case 102: /* Word 8/9/10, no image just a pathname or URL */ 993 pImg->eImageType = imagetype_is_external; 994 DBG_HEX(ulFileOffsetImage + tPos); 995 break; 996 default: 997 DBG_DEC(iType); 998 DBG_HEX(ulFileOffsetImage + tPos); 999 DBG_FIXME(); 1000 return image_no_information; 1001 } 1002 1003 /* Minimal information is now available */ 1004 pImg->tLength = tLength; 1005 pImg->tPosition = tPos; 1006 pImg->iHorSizeScaled = 1007 (int)(((long)iHorSize * (long)usHorScalingFactor + 500) / 1000); 1008 pImg->iVerSizeScaled = 1009 (int)(((long)iVerSize * (long)usVerScalingFactor + 500) / 1000); 1010 #if !defined(__riscos) 1011 vImage2Papersize(pImg); 1012 #endif /* !__riscos */ 1013 1014 /* Image type specific examinations */ 1015 switch (pImg->eImageType) { 1016 case imagetype_is_dib: 1017 if (bExamineDIB(pFile, pImg)) { 1018 return image_full_information; 1019 } 1020 return image_minimal_information; 1021 case imagetype_is_jpeg: 1022 if (bExamineJPEG(pFile, pImg)) { 1023 return image_full_information; 1024 } 1025 return image_minimal_information; 1026 case imagetype_is_png: 1027 if (bExaminePNG(pFile, pImg)) { 1028 return image_full_information; 1029 } 1030 return image_minimal_information; 1031 case imagetype_is_wmf: 1032 if (bExamineWMF(pFile, pImg)) { 1033 return image_full_information; 1034 } 1035 return image_minimal_information; 1036 case imagetype_is_emf: 1037 case imagetype_is_pict: 1038 case imagetype_is_external: 1039 return image_minimal_information; 1040 case imagetype_is_unknown: 1041 default: 1042 return image_no_information; 1043 } 1044 } /* end of eExamineImage */ 1045