3 * Copyright (C) 2000-2004 A.J. van Os; Released under GNU GPL
6 * Functions to examine image headers
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.
21 /* BMP compression types */
26 /* PNG colortype bits */
27 #define PNG_CB_PALETTE 0x01
28 #define PNG_CB_COLOR 0x02
29 #define PNG_CB_ALPHA 0x04
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
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) */
46 M_SOF5
= 0xc5, /* differential sequential DCT */
47 M_SOF6
= 0xc6, /* differential progressive DCT */
48 M_SOF7
= 0xc7, /* differential lossless */
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) */
55 M_SOF13
= 0xcd, /* differential sequential DCT */
56 M_SOF14
= 0xce, /* differential progressive DCT */
57 M_SOF15
= 0xcf, /* differential lossless */
59 M_DHT
= 0xc4, /* define Huffman tables */
61 M_DAC
= 0xcc, /* define arithmetic conditioning table */
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 */
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) */
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 */
98 M_JPG0
= 0xf0, /* reserved for JPEG extensions */
99 M_JPG13
= 0xfd, /* reserved for JPEG extensions */
100 M_COM
= 0xfe, /* comment */
102 M_TEM
= 0x01 /* temporary use */
107 * bFillPaletteDIB - fill the palette part of the imagesdata
109 * returns TRUE if the images must be a color image, otherwise FALSE;
112 bFillPaletteDIB(FILE *pFile
, imagedata_type
*pImg
, BOOL bNewFormat
)
115 BOOL bIsColorPalette
;
120 if (pImg
->uiBitsPerComponent
> 8) {
121 /* No palette, image uses more than 256 colors */
125 if (pImg
->iColorsUsed
<= 0) {
126 /* Not specified, so compute the number of colors used */
127 pImg
->iColorsUsed
= 1 << pImg
->uiBitsPerComponent
;
130 fail(pImg
->iColorsUsed
> 256);
131 if (pImg
->iColorsUsed
> 256) {
132 pImg
->iColorsUsed
= 256;
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
);
142 (void)iNextByte(pFile
);
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
;
153 return bIsColorPalette
;
154 } /* end of bFillPaletteDIB */
157 * bExamineDIB - Examine a DIB header
159 * return TRUE if successful, otherwise FALSE
162 bExamineDIB(FILE *pFile
, imagedata_type
*pImg
)
165 int iPlanes
, iCompression
;
167 tHeaderSize
= (size_t)ulNextLong(pFile
);
168 switch (tHeaderSize
) {
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;
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);
189 DBG_DEC(tHeaderSize
);
192 DBG_DEC(pImg
->iWidth
);
193 DBG_DEC(pImg
->iHeight
);
194 DBG_DEC(pImg
->uiBitsPerComponent
);
195 DBG_DEC(iCompression
);
196 DBG_DEC(pImg
->iColorsUsed
);
198 /* Do some sanity checks with the parameters */
203 if (pImg
->iWidth
<= 0 || pImg
->iHeight
<= 0) {
204 DBG_DEC(pImg
->iWidth
);
205 DBG_DEC(pImg
->iHeight
);
208 if (pImg
->uiBitsPerComponent
!= 1 && pImg
->uiBitsPerComponent
!= 4 &&
209 pImg
->uiBitsPerComponent
!= 8 && pImg
->uiBitsPerComponent
!= 24) {
210 DBG_DEC(pImg
->uiBitsPerComponent
);
213 if (iCompression
!= BI_RGB
&&
214 (pImg
->uiBitsPerComponent
== 1 || pImg
->uiBitsPerComponent
== 24)) {
217 if (iCompression
== BI_RLE8
&& pImg
->uiBitsPerComponent
== 4) {
220 if (iCompression
== BI_RLE4
&& pImg
->uiBitsPerComponent
== 8) {
224 switch (iCompression
) {
226 pImg
->eCompression
= compression_none
;
229 pImg
->eCompression
= compression_rle4
;
232 pImg
->eCompression
= compression_rle8
;
235 DBG_DEC(iCompression
);
239 pImg
->bColorImage
= bFillPaletteDIB(pFile
, pImg
, tHeaderSize
> 12);
241 if (pImg
->uiBitsPerComponent
<= 8) {
242 pImg
->iComponents
= 1;
244 pImg
->iComponents
= (int)(pImg
->uiBitsPerComponent
/ 8);
248 } /* end of bExamineDIB */
251 * iNextMarker - read the next JPEG marker
254 iNextMarker(FILE *pFile
)
260 iMarker
= iNextByte(pFile
);
261 } while (iMarker
!= 0xff && iMarker
!= EOF
);
262 if (iMarker
== EOF
) {
266 iMarker
= iNextByte(pFile
);
267 } while (iMarker
== 0xff);
268 } while (iMarker
== 0x00); /* repeat if ff/00 */
271 } /* end of iNextMarker */
274 * bExamineJPEG - Examine a JPEG header
276 * return TRUE if successful, otherwise FALSE
279 bExamineJPEG(FILE *pFile
, imagedata_type
*pImg
)
289 /* process JPEG markers */
290 while (!bSOFDone
&& (iMarker
= iNextMarker(pFile
)) != (int)M_EOI
) {
293 DBG_MSG("Error: unexpected end of JPEG file");
295 /* The following are not officially supported in PostScript level 2 */
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
);
320 * Check for Adobe application marker. It is known (per Adobe's
321 * TN5116) to contain the string "Adobe" at the start of the
324 tLength
= (size_t)usNextWordBE(pFile
);
326 (void)tSkipBytes(pFile
, tLength
- 2);
328 for (iIndex
= 0; iIndex
< 5; iIndex
++) {
330 (char)iNextByte(pFile
);
333 if (STREQ(appstring
, "Adobe")) {
336 (void)tSkipBytes(pFile
, tLength
- 7);
339 case M_SOI
: /* ignore markers without parameters */
351 default: /* skip variable length markers */
352 tLength
= (size_t)usNextWordBE(pFile
);
353 (void)tSkipBytes(pFile
, tLength
- 2);
358 DBG_DEC(pImg
->iWidth
);
359 DBG_DEC(pImg
->iHeight
);
360 DBG_DEC(pImg
->uiBitsPerComponent
);
361 DBG_DEC(pImg
->iComponents
);
363 /* Do some sanity checks with the parameters */
364 if (pImg
->iHeight
<= 0 ||
366 pImg
->iComponents
<= 0) {
367 DBG_DEC(pImg
->iHeight
);
368 DBG_DEC(pImg
->iWidth
);
369 DBG_DEC(pImg
->iComponents
);
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");
378 if (pImg
->uiBitsPerComponent
!= 8) {
379 DBG_DEC(pImg
->uiBitsPerComponent
);
380 DBG_MSG("Not supported in PostScript level 2");
384 if (pImg
->iComponents
!= 1 &&
385 pImg
->iComponents
!= 3 &&
386 pImg
->iComponents
!= 4) {
387 DBG_DEC(pImg
->iComponents
);
391 pImg
->bColorImage
= pImg
->iComponents
>= 3;
392 pImg
->iColorsUsed
= 0;
393 pImg
->eCompression
= compression_jpeg
;
396 } /* end of bExamineJPEG */
399 * bFillPalettePNG - fill the palette part of the imagesdata
401 * returns TRUE if sucessful, otherwise FALSE;
404 bFillPalettePNG(FILE *pFile
, imagedata_type
*pImg
, size_t tLength
)
406 int iIndex
, iEntries
;
411 if (pImg
->uiBitsPerComponent
> 8) {
412 /* No palette, image uses more than 256 colors */
416 if (!pImg
->bColorImage
) {
417 /* Only color images can have a palette */
421 if (tLength
% 3 != 0) {
422 /* Each palette entry takes three bytes */
427 iEntries
= (int)(tLength
/ 3);
429 pImg
->iColorsUsed
= 1 << pImg
->uiBitsPerComponent
;
430 DBG_DEC(pImg
->iColorsUsed
);
432 if (iEntries
> 256) {
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);
443 for (;iIndex
< pImg
->iColorsUsed
; iIndex
++) {
444 pImg
->aucPalette
[iIndex
][0] = 0;
445 pImg
->aucPalette
[iIndex
][1] = 0;
446 pImg
->aucPalette
[iIndex
][2] = 0;
450 } /* end of bFillPalettePNG */
453 * bExaminePNG - Examine a PNG header
455 * return TRUE if successful, otherwise FALSE
458 bExaminePNG(FILE *pFile
, imagedata_type
*pImg
)
461 ULONG ulLong1
, ulLong2
, ulName
;
463 int iCompressionMethod
, iFilterMethod
, iInterlaceMethod
;
464 int iColor
, iIncrement
;
465 BOOL bHasPalette
, bHasAlpha
;
468 /* Check signature */
469 ulLong1
= ulNextLongBE(pFile
);
470 ulLong2
= ulNextLongBE(pFile
);
471 if (ulLong1
!= 0x89504e47UL
|| ulLong2
!= 0x0d0a1a0aUL
) {
481 while (ulName
!= PNG_CN_IEND
) {
482 tLength
= (size_t)ulNextLongBE(pFile
);
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
]);
491 ulName
|= aucBuf
[iIndex
];
501 pImg
->iWidth
= (int)ulNextLongBE(pFile
);
502 pImg
->iHeight
= (int)ulNextLongBE(pFile
);
503 pImg
->uiBitsPerComponent
= (UINT
)iNextByte(pFile
);
504 iTmp
= iNextByte(pFile
);
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 */
514 (bHasPalette
|| !pImg
->bColorImage
) ? 1 : 3;
518 iCompressionMethod
= iNextByte(pFile
);
519 if (iCompressionMethod
!= 0) {
520 DBG_DEC(iCompressionMethod
);
523 iFilterMethod
= iNextByte(pFile
);
524 if (iFilterMethod
!= 0) {
525 DBG_DEC(iFilterMethod
);
528 iInterlaceMethod
= iNextByte(pFile
);
529 if (iInterlaceMethod
!= 0) {
530 DBG_DEC(iInterlaceMethod
);
533 pImg
->iColorsUsed
= 0;
534 (void)tSkipBytes(pFile
, tLength
- 13 + 4);
540 if (!bFillPalettePNG(pFile
, pImg
, tLength
)) {
543 (void)tSkipBytes(pFile
, 4);
546 (void)tSkipBytes(pFile
, tLength
+ 4);
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
);
557 /* Do some sanity checks with the parameters */
558 if (pImg
->iWidth
<= 0 || pImg
->iHeight
<= 0) {
562 if (pImg
->uiBitsPerComponent
!= 1 && pImg
->uiBitsPerComponent
!= 2 &&
563 pImg
->uiBitsPerComponent
!= 4 && pImg
->uiBitsPerComponent
!= 8 &&
564 pImg
->uiBitsPerComponent
!= 16) {
565 DBG_DEC(pImg
->uiBitsPerComponent
);
569 if (pImg
->iComponents
!= 1 && pImg
->iComponents
!= 3) {
571 DBG_DEC(pImg
->iComponents
);
575 if (pImg
->uiBitsPerComponent
> 8) {
577 DBG_DEC(pImg
->uiBitsPerComponent
);
581 if (pImg
->iColorsUsed
== 0 &&
582 pImg
->iComponents
== 1 &&
583 pImg
->uiBitsPerComponent
<= 4) {
585 * No palette is supplied, but PostScript needs one in these
586 * cases, so we add a default palette here
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
;
597 /* Just to be sure */
598 pImg
->bColorImage
= FALSE
;
601 pImg
->eCompression
= compression_zlib
;
604 } /* end of bExaminePNG */
607 * bExamineWMF - Examine a WMF header
609 * return TRUE if successful, otherwise FALSE
612 bExamineWMF(FILE *pFile
, imagedata_type
*pImg
)
614 ULONG ulFileSize
, ulMaxRecord
, ulMagic
;
615 USHORT usType
, usHeaderSize
, usVersion
, usNoObjects
;
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
);
627 DBG_DEC(usHeaderSize
);
630 DBG_DEC(usNoObjects
);
631 DBG_DEC(ulMaxRecord
);
634 } /* end of bExamineWMF */
636 #if !defined(__riscos)
638 * vImage2Papersize - make sure the image fits on the paper
640 * This function should not be needed if Word would do a proper job
643 vImage2Papersize(imagedata_type
*pImg
)
645 static int iNetPageHeight
= -1;
646 static int iNetPageWidth
= -1;
647 options_type tOptions
;
648 double dVerFactor
, dHorFactor
, dFactor
;
650 DBG_MSG("vImage2Papersize");
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
) +
662 iNetPageWidth
= tOptions
.iPageWidth
-
663 (lDrawUnits2MilliPoints(
664 PS_LEFT_MARGIN
+ PS_RIGHT_MARGIN
) +
666 DBG_DEC(iNetPageHeight
);
667 DBG_DEC(iNetPageWidth
);
670 if (pImg
->iVerSizeScaled
< iNetPageHeight
&&
671 pImg
->iHorSizeScaled
< iNetPageWidth
) {
672 /* The image fits on the paper */
676 dVerFactor
= (double)iNetPageHeight
/ (double)pImg
->iVerSizeScaled
;
677 dHorFactor
= (double)iNetPageWidth
/ (double)pImg
->iHorSizeScaled
;
678 dFactor
= min(dVerFactor
, dHorFactor
);
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 */
687 * tFind6Image - skip until the image is found
689 * Find the image in Word 6/7 files
691 * returns the new position when a image is found, otherwise -1
694 tFind6Image(FILE *pFile
, size_t tPosition
, size_t tLength
,
695 imagetype_enum
*peImageType
)
698 size_t tRecordLength
, tToSkip
;
702 fail(peImageType
== NULL
);
704 *peImageType
= imagetype_is_unknown
;
705 if (tPosition
+ 18 >= tLength
) {
709 ulMarker
= ulNextLong(pFile
);
710 if (ulMarker
!= 0x00090001) {
714 usMarker
= usNextWord(pFile
);
715 if (usMarker
!= 0x0300) {
719 (void)tSkipBytes(pFile
, 10);
720 usMarker
= usNextWord(pFile
);
721 if (usMarker
!= 0x0000) {
727 while (tPosition
+ 6 <= tLength
) {
728 tRecordLength
= (size_t)ulNextLong(pFile
);
729 usMarker
= usNextWord(pFile
);
731 NO_DBG_DEC(tRecordLength
);
732 NO_DBG_HEX(usMarker
);
735 DBG_HEX(ulGetDataOffset(pFile
));
739 *peImageType
= imagetype_is_dib
;
740 tPosition
+= tSkipBytes(pFile
, 20);
744 *peImageType
= imagetype_is_dib
;
745 tPosition
+= tSkipBytes(pFile
, 22);
748 if (tRecordLength
< 3) {
751 if (tRecordLength
> SIZE_T_MAX
/ 2) {
753 * No need to compute the number of bytes
756 DBG_DEC(tRecordLength
);
757 DBG_HEX(tRecordLength
);
761 tToSkip
= tRecordLength
* 2 - 6;
762 if (tToSkip
> tLength
- tPosition
) {
763 /* You can't skip this number of bytes */
765 DBG_DEC(tLength
- tPosition
);
768 tPosition
+= tSkipBytes(pFile
, tToSkip
);
774 } /* end of tFind6Image */
777 * tFind8Image - skip until the image is found
779 * Find the image in Word 8/9/10 files
781 * returns the new position when a image is found, otherwise -1
784 tFind8Image(FILE *pFile
, size_t tPosition
, size_t tLength
,
785 imagetype_enum
*peImageType
)
787 size_t tRecordLength
, tNameLen
;
788 USHORT usRecordVersion
, usRecordType
, usRecordInstance
;
792 fail(peImageType
== NULL
);
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
);
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:
811 tPosition
+= tSkipBytes(pFile
, 33);
812 tNameLen
= (size_t)iNextByte(pFile
);
814 DBG_DEC_C(tNameLen
!= 0, tNameLen
);
815 tPosition
+= tSkipBytes(pFile
, 2 + tNameLen
* 2);
818 tPosition
+= tSkipBytes(pFile
, 8);
821 tPosition
+= tSkipBytes(pFile
, 16);
823 case 0xf006: case 0xf00a: case 0xf00b: case 0xf00d:
824 case 0xf00e: case 0xf00f: case 0xf010: case 0xf011:
826 tPosition
+= tSkipBytes(pFile
, tRecordLength
);
830 *peImageType
= imagetype_is_emf
;
831 tPosition
+= tSkipBytes(pFile
, 50);
832 if ((usRecordInstance
^ MSOBI_EMF
) == 1) {
833 tPosition
+= tSkipBytes(pFile
, 16);
838 *peImageType
= imagetype_is_wmf
;
839 tPosition
+= tSkipBytes(pFile
, 50);
840 if ((usRecordInstance
^ MSOBI_WMF
) == 1) {
841 tPosition
+= tSkipBytes(pFile
, 16);
846 *peImageType
= imagetype_is_pict
;
847 tPosition
+= tSkipBytes(pFile
, 50);
848 if ((usRecordInstance
^ MSOBI_PICT
) == 1) {
849 tPosition
+= tSkipBytes(pFile
, 16);
854 *peImageType
= imagetype_is_jpeg
;
855 tPosition
+= tSkipBytes(pFile
, 17);
856 if ((usRecordInstance
^ MSOBI_JPEG
) == 1) {
857 tPosition
+= tSkipBytes(pFile
, 16);
862 *peImageType
= imagetype_is_png
;
863 tPosition
+= tSkipBytes(pFile
, 17);
864 if ((usRecordInstance
^ MSOBI_PNG
) == 1) {
865 tPosition
+= tSkipBytes(pFile
, 16);
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);
879 DBG_HEX(usRecordType
);
880 DBG_DEC_C(tRecordLength
% 4 != 0, tRecordLength
);
887 } /* end of tFind8Image */
890 * eExamineImage - Examine the image
892 * Returns an indication of the amount of information found
895 eExamineImage(FILE *pFile
, ULONG ulFileOffsetImage
, imagedata_type
*pImg
)
898 size_t tWordHeaderLen
, tLength
, tPos
;
899 int iType
, iHorSize
, iVerSize
;
900 USHORT usHorScalingFactor
, usVerScalingFactor
;
902 if (ulFileOffsetImage
== FC_INVALID
) {
903 return image_no_information
;
905 DBG_HEX(ulFileOffsetImage
);
907 if (!bSetDataOffset(pFile
, ulFileOffsetImage
)) {
908 return image_no_information
;
911 tLength
= (size_t)ulNextLong(pFile
);
914 /* Smaller than the smallest known header */
916 return image_no_information
;
918 tWordHeaderLen
= (size_t)usNextWord(pFile
);
919 DBG_DEC(tWordHeaderLen
);
920 fail(tWordHeaderLen
!= 46 &&
921 tWordHeaderLen
!= 58 &&
922 tWordHeaderLen
!= 68);
924 if (tLength
< tWordHeaderLen
) {
925 /* Smaller than the current header */
926 return image_no_information
;
928 iType
= (int)usNextWord(pFile
);
930 (void)tSkipBytes(pFile
, 28 - 8);
932 lTmp
= lTwips2MilliPoints(usNextWord(pFile
));
933 iHorSize
= (int)(lTmp
/ 1000);
934 if (lTmp
% 1000 != 0) {
938 lTmp
= lTwips2MilliPoints(usNextWord(pFile
));
939 iVerSize
= (int)(lTmp
/ 1000);
940 if (lTmp
% 1000 != 0) {
945 usHorScalingFactor
= usNextWord(pFile
);
946 DBG_DEC(usHorScalingFactor
);
947 usVerScalingFactor
= usNextWord(pFile
);
948 DBG_DEC(usVerScalingFactor
);
951 lTmp
= (long)iHorSize
* (long)usHorScalingFactor
;
953 /* This image would be less than 1 millimeter wide */
955 return image_no_information
;
957 lTmp
= (long)iVerSize
* (long)usVerScalingFactor
;
959 /* This image would be less than 1 millimeter high */
961 return image_no_information
;
964 /* Skip the rest of the header */
965 (void)tSkipBytes(pFile
, tWordHeaderLen
- 36);
966 tPos
= tWordHeaderLen
;
968 (void)memset(pImg
, 0, sizeof(*pImg
));
973 tPos
= tFind6Image(pFile
, tPos
, tLength
, &pImg
->eImageType
);
974 if (tPos
== (size_t)-1) {
976 return image_no_information
;
980 case 94: /* Word 6/7, no image just a pathname */
981 pImg
->eImageType
= imagetype_is_external
;
982 DBG_HEX(ulFileOffsetImage
+ tPos
);
985 tPos
= tFind8Image(pFile
, tPos
, tLength
, &pImg
->eImageType
);
986 if (tPos
== (size_t)-1) {
988 return image_no_information
;
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
);
998 DBG_HEX(ulFileOffsetImage
+ tPos
);
1000 return image_no_information
;
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 */
1014 /* Image type specific examinations */
1015 switch (pImg
->eImageType
) {
1016 case imagetype_is_dib
:
1017 if (bExamineDIB(pFile
, pImg
)) {
1018 return image_full_information
;
1020 return image_minimal_information
;
1021 case imagetype_is_jpeg
:
1022 if (bExamineJPEG(pFile
, pImg
)) {
1023 return image_full_information
;
1025 return image_minimal_information
;
1026 case imagetype_is_png
:
1027 if (bExaminePNG(pFile
, pImg
)) {
1028 return image_full_information
;
1030 return image_minimal_information
;
1031 case imagetype_is_wmf
:
1032 if (bExamineWMF(pFile
, pImg
)) {
1033 return image_full_information
;
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
:
1042 return image_no_information
;
1044 } /* end of eExamineImage */