mirror of
				https://github.com/simon987/antiword.git
				synced 2025-10-30 23:36:52 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1045 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1045 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * imgexam.c
 | |
|  * Copyright (C) 2000-2004 A.J. van Os; Released under GNU GPL
 | |
|  *
 | |
|  * Description:
 | |
|  * Functions to examine image headers
 | |
|  *
 | |
|  *================================================================
 | |
|  * Part of this software is based on:
 | |
|  * jpeg2ps - convert JPEG compressed images to PostScript Level 2
 | |
|  * Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
 | |
|  *================================================================
 | |
|  * The credit should go to him, but all the bugs are mine.
 | |
|  */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <ctype.h>
 | |
| #include "antiword.h"
 | |
| 
 | |
| /* BMP compression types */
 | |
| #define BI_RGB		0
 | |
| #define BI_RLE8		1
 | |
| #define BI_RLE4		2
 | |
| 
 | |
| /* PNG colortype bits */
 | |
| #define PNG_CB_PALETTE		0x01
 | |
| #define PNG_CB_COLOR		0x02
 | |
| #define PNG_CB_ALPHA		0x04
 | |
| 
 | |
| /* Instance signature */
 | |
| #define MSOBI_WMF	0x0216
 | |
| #define MSOBI_EMF	0x03d4
 | |
| #define MSOBI_PICT	0x0542
 | |
| #define MSOBI_PNG	0x06e0
 | |
| #define MSOBI_JPEG	0x046a
 | |
| #define MSOBI_DIB	0x07a8
 | |
| 
 | |
| /* The following enum is stolen from the IJG JPEG library */
 | |
| typedef enum {		/* JPEG marker codes			*/
 | |
| 	M_SOF0	= 0xc0,	/* baseline DCT				*/
 | |
| 	M_SOF1	= 0xc1,	/* extended sequential DCT		*/
 | |
| 	M_SOF2	= 0xc2,	/* progressive DCT			*/
 | |
| 	M_SOF3	= 0xc3,	/* lossless (sequential)		*/
 | |
| 
 | |
| 	M_SOF5	= 0xc5,	/* differential sequential DCT		*/
 | |
| 	M_SOF6	= 0xc6,	/* differential progressive DCT		*/
 | |
| 	M_SOF7	= 0xc7,	/* differential lossless		*/
 | |
| 
 | |
| 	M_JPG	= 0xc8,	/* JPEG extensions			*/
 | |
| 	M_SOF9	= 0xc9,	/* extended sequential DCT		*/
 | |
| 	M_SOF10	= 0xca,	/* progressive DCT			*/
 | |
| 	M_SOF11	= 0xcb,	/* lossless (sequential)		*/
 | |
| 
 | |
| 	M_SOF13	= 0xcd,	/* differential sequential DCT		*/
 | |
| 	M_SOF14	= 0xce,	/* differential progressive DCT		*/
 | |
| 	M_SOF15	= 0xcf,	/* differential lossless		*/
 | |
| 
 | |
| 	M_DHT	= 0xc4,	/* define Huffman tables		*/
 | |
| 
 | |
| 	M_DAC	= 0xcc,	/* define arithmetic conditioning table	*/
 | |
| 
 | |
| 	M_RST0	= 0xd0,	/* restart				*/
 | |
| 	M_RST1	= 0xd1,	/* restart				*/
 | |
| 	M_RST2	= 0xd2,	/* restart				*/
 | |
| 	M_RST3	= 0xd3,	/* restart				*/
 | |
| 	M_RST4	= 0xd4,	/* restart				*/
 | |
| 	M_RST5	= 0xd5,	/* restart				*/
 | |
| 	M_RST6	= 0xd6,	/* restart				*/
 | |
| 	M_RST7	= 0xd7,	/* restart				*/
 | |
| 
 | |
| 	M_SOI	= 0xd8,	/* start of image			*/
 | |
| 	M_EOI	= 0xd9,	/* end of image				*/
 | |
| 	M_SOS	= 0xda,	/* start of scan			*/
 | |
| 	M_DQT	= 0xdb,	/* define quantization tables		*/
 | |
| 	M_DNL	= 0xdc,	/* define number of lines		*/
 | |
| 	M_DRI	= 0xdd,	/* define restart interval		*/
 | |
| 	M_DHP	= 0xde,	/* define hierarchical progression	*/
 | |
| 	M_EXP	= 0xdf,	/* expand reference image(s)		*/
 | |
| 
 | |
| 	M_APP0	= 0xe0,	/* application marker, used for JFIF	*/
 | |
| 	M_APP1	= 0xe1,	/* application marker			*/
 | |
| 	M_APP2	= 0xe2,	/* application marker			*/
 | |
| 	M_APP3	= 0xe3,	/* application marker			*/
 | |
| 	M_APP4	= 0xe4,	/* application marker			*/
 | |
| 	M_APP5	= 0xe5,	/* application marker			*/
 | |
| 	M_APP6	= 0xe6,	/* application marker			*/
 | |
| 	M_APP7	= 0xe7,	/* application marker			*/
 | |
| 	M_APP8	= 0xe8,	/* application marker			*/
 | |
| 	M_APP9	= 0xe9,	/* application marker			*/
 | |
| 	M_APP10	= 0xea,	/* application marker			*/
 | |
| 	M_APP11	= 0xeb,	/* application marker			*/
 | |
| 	M_APP12	= 0xec,	/* application marker			*/
 | |
| 	M_APP13	= 0xed,	/* application marker			*/
 | |
| 	M_APP14	= 0xee,	/* application marker, used by Adobe	*/
 | |
| 	M_APP15	= 0xef,	/* application marker			*/
 | |
| 
 | |
| 	M_JPG0	= 0xf0,	/* reserved for JPEG extensions		*/
 | |
| 	M_JPG13	= 0xfd,	/* reserved for JPEG extensions		*/
 | |
| 	M_COM	= 0xfe,	/* comment				*/
 | |
| 
 | |
| 	M_TEM	= 0x01	/* temporary use			*/
 | |
| } JPEG_MARKER;
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * bFillPaletteDIB - fill the palette part of the imagesdata
 | |
|  *
 | |
|  * returns TRUE if the images must be a color image, otherwise FALSE;
 | |
|  */
 | |
| static BOOL
 | |
| bFillPaletteDIB(FILE *pFile, imagedata_type *pImg, BOOL bNewFormat)
 | |
| {
 | |
| 	int	iIndex;
 | |
| 	BOOL	bIsColorPalette;
 | |
| 
 | |
| 	fail(pFile == NULL);
 | |
| 	fail(pImg == NULL);
 | |
| 
 | |
| 	if (pImg->uiBitsPerComponent > 8) {
 | |
| 		/* No palette, image uses more than 256 colors */
 | |
| 		return TRUE;
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->iColorsUsed <= 0) {
 | |
| 		/* Not specified, so compute the number of colors used */
 | |
| 		pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent;
 | |
| 	}
 | |
| 
 | |
| 	fail(pImg->iColorsUsed > 256);
 | |
| 	if (pImg->iColorsUsed > 256) {
 | |
| 		pImg->iColorsUsed = 256;
 | |
| 	}
 | |
| 
 | |
| 	bIsColorPalette = FALSE;
 | |
| 	for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) {
 | |
| 		/* From BGR order to RGB order */
 | |
| 		pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile);
 | |
| 		pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile);
 | |
| 		pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile);
 | |
| 		if (bNewFormat) {
 | |
| 			(void)iNextByte(pFile);
 | |
| 		}
 | |
| 		NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3);
 | |
| 		if (pImg->aucPalette[iIndex][0] !=
 | |
| 		     pImg->aucPalette[iIndex][1] ||
 | |
| 		    pImg->aucPalette[iIndex][1] !=
 | |
| 		     pImg->aucPalette[iIndex][2]) {
 | |
| 			bIsColorPalette = TRUE;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return bIsColorPalette;
 | |
| } /* end of bFillPaletteDIB */
 | |
| 
 | |
| /*
 | |
|  * bExamineDIB - Examine a DIB header
 | |
|  *
 | |
|  * return TRUE if successful, otherwise FALSE
 | |
|  */
 | |
| static BOOL
 | |
| bExamineDIB(FILE *pFile, imagedata_type *pImg)
 | |
| {
 | |
| 	size_t	tHeaderSize;
 | |
| 	int	iPlanes, iCompression;
 | |
| 
 | |
| 	tHeaderSize = (size_t)ulNextLong(pFile);
 | |
| 	switch (tHeaderSize) {
 | |
| 	case 12:
 | |
| 		pImg->iWidth = (int)usNextWord(pFile);
 | |
| 		pImg->iHeight = (int)usNextWord(pFile);
 | |
| 		iPlanes = (int)usNextWord(pFile);
 | |
| 		pImg->uiBitsPerComponent = (UINT)usNextWord(pFile);
 | |
| 		iCompression = BI_RGB;
 | |
| 		pImg->iColorsUsed = 0;
 | |
| 		break;
 | |
| 	case 40:
 | |
| 	case 64:
 | |
| 		pImg->iWidth = (int)ulNextLong(pFile);
 | |
| 		pImg->iHeight = (int)ulNextLong(pFile);
 | |
| 		iPlanes = (int)usNextWord(pFile);
 | |
| 		pImg->uiBitsPerComponent = (UINT)usNextWord(pFile);
 | |
| 		iCompression = (int)ulNextLong(pFile);
 | |
| 		(void)tSkipBytes(pFile, 12);
 | |
| 		pImg->iColorsUsed = (int)ulNextLong(pFile);
 | |
| 		(void)tSkipBytes(pFile, tHeaderSize - 36);
 | |
| 		break;
 | |
| 	default:
 | |
| 		DBG_DEC(tHeaderSize);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	DBG_DEC(pImg->iWidth);
 | |
| 	DBG_DEC(pImg->iHeight);
 | |
| 	DBG_DEC(pImg->uiBitsPerComponent);
 | |
| 	DBG_DEC(iCompression);
 | |
| 	DBG_DEC(pImg->iColorsUsed);
 | |
| 
 | |
| 	/* Do some sanity checks with the parameters */
 | |
| 	if (iPlanes != 1) {
 | |
| 		DBG_DEC(iPlanes);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	if (pImg->iWidth <= 0 || pImg->iHeight <= 0) {
 | |
| 		DBG_DEC(pImg->iWidth);
 | |
| 		DBG_DEC(pImg->iHeight);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 4 &&
 | |
| 	    pImg->uiBitsPerComponent != 8 && pImg->uiBitsPerComponent != 24) {
 | |
| 		DBG_DEC(pImg->uiBitsPerComponent);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	if (iCompression != BI_RGB &&
 | |
| 	    (pImg->uiBitsPerComponent == 1 || pImg->uiBitsPerComponent == 24)) {
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	if (iCompression == BI_RLE8 && pImg->uiBitsPerComponent == 4) {
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	if (iCompression == BI_RLE4 && pImg->uiBitsPerComponent == 8) {
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	switch (iCompression) {
 | |
| 	case BI_RGB:
 | |
| 		pImg->eCompression = compression_none;
 | |
| 		break;
 | |
| 	case BI_RLE4:
 | |
| 		pImg->eCompression = compression_rle4;
 | |
| 		break;
 | |
| 	case BI_RLE8:
 | |
| 		pImg->eCompression = compression_rle8;
 | |
| 		break;
 | |
| 	default:
 | |
| 		DBG_DEC(iCompression);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	pImg->bColorImage = bFillPaletteDIB(pFile, pImg, tHeaderSize > 12);
 | |
| 
 | |
| 	if (pImg->uiBitsPerComponent <= 8) {
 | |
| 		pImg->iComponents = 1;
 | |
| 	} else {
 | |
| 		pImg->iComponents = (int)(pImg->uiBitsPerComponent / 8);
 | |
| 	}
 | |
| 
 | |
| 	return TRUE;
 | |
| } /* end of bExamineDIB */
 | |
| 
 | |
| /*
 | |
|  * iNextMarker - read the next JPEG marker
 | |
|  */
 | |
| static int
 | |
| iNextMarker(FILE *pFile)
 | |
| {
 | |
| 	int	iMarker;
 | |
| 
 | |
| 	do {
 | |
| 		do {
 | |
| 			iMarker = iNextByte(pFile);
 | |
| 		} while (iMarker != 0xff && iMarker != EOF);
 | |
| 		if (iMarker == EOF) {
 | |
| 			return EOF;
 | |
| 		}
 | |
| 		do {
 | |
| 			iMarker = iNextByte(pFile);
 | |
| 		} while (iMarker == 0xff);
 | |
| 	} while (iMarker == 0x00);			/* repeat if ff/00 */
 | |
| 
 | |
| 	return iMarker;
 | |
| } /* end of iNextMarker */
 | |
| 
 | |
| /*
 | |
|  * bExamineJPEG - Examine a JPEG header
 | |
|  *
 | |
|  * return TRUE if successful, otherwise FALSE
 | |
|  */
 | |
| static BOOL
 | |
| bExamineJPEG(FILE *pFile, imagedata_type *pImg)
 | |
| {
 | |
| 	size_t	tLength;
 | |
| 	int	iMarker, iIndex;
 | |
| 	char	appstring[10];
 | |
| 	BOOL	bSOFDone;
 | |
| 
 | |
| 	tLength = 0;
 | |
| 	bSOFDone = FALSE;
 | |
| 
 | |
| 	/* process JPEG markers */
 | |
| 	while (!bSOFDone && (iMarker = iNextMarker(pFile)) != (int)M_EOI) {
 | |
| 		switch (iMarker) {
 | |
| 		case EOF:
 | |
| 			DBG_MSG("Error: unexpected end of JPEG file");
 | |
| 			return FALSE;
 | |
| 	/* The following are not officially supported in PostScript level 2 */
 | |
| 		case M_SOF2:
 | |
| 		case M_SOF3:
 | |
| 		case M_SOF5:
 | |
| 		case M_SOF6:
 | |
| 		case M_SOF7:
 | |
| 		case M_SOF9:
 | |
| 		case M_SOF10:
 | |
| 		case M_SOF11:
 | |
| 		case M_SOF13:
 | |
| 		case M_SOF14:
 | |
| 		case M_SOF15:
 | |
| 			DBG_HEX(iMarker);
 | |
| 			return FALSE;
 | |
| 		case M_SOF0:
 | |
| 		case M_SOF1:
 | |
| 			tLength = (size_t)usNextWordBE(pFile);
 | |
| 			pImg->uiBitsPerComponent = (UINT)iNextByte(pFile);
 | |
| 			pImg->iHeight = (int)usNextWordBE(pFile);
 | |
| 			pImg->iWidth = (int)usNextWordBE(pFile);
 | |
| 			pImg->iComponents = iNextByte(pFile);
 | |
| 			bSOFDone = TRUE;
 | |
| 			break;
 | |
| 		case M_APP14:
 | |
| 		/*
 | |
| 		 * Check for Adobe application marker. It is known (per Adobe's
 | |
| 		 * TN5116) to contain the string "Adobe" at the start of the
 | |
| 		 * APP14 marker.
 | |
| 		 */
 | |
| 			tLength = (size_t)usNextWordBE(pFile);
 | |
| 			if (tLength < 12) {
 | |
| 				(void)tSkipBytes(pFile, tLength - 2);
 | |
| 			} else {
 | |
| 				for (iIndex = 0; iIndex < 5; iIndex++) {
 | |
| 					appstring[iIndex] =
 | |
| 							(char)iNextByte(pFile);
 | |
| 				}
 | |
| 				appstring[5] = '\0';
 | |
| 				if (STREQ(appstring, "Adobe")) {
 | |
| 					pImg->bAdobe = TRUE;
 | |
| 				}
 | |
| 				(void)tSkipBytes(pFile, tLength - 7);
 | |
| 			}
 | |
| 			break;
 | |
| 		case M_SOI:		/* ignore markers without parameters */
 | |
| 		case M_EOI:
 | |
| 		case M_TEM:
 | |
| 		case M_RST0:
 | |
| 		case M_RST1:
 | |
| 		case M_RST2:
 | |
| 		case M_RST3:
 | |
| 		case M_RST4:
 | |
| 		case M_RST5:
 | |
| 		case M_RST6:
 | |
| 		case M_RST7:
 | |
| 			break;
 | |
| 		default:		/* skip variable length markers */
 | |
| 			tLength = (size_t)usNextWordBE(pFile);
 | |
| 			(void)tSkipBytes(pFile, tLength - 2);
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	DBG_DEC(pImg->iWidth);
 | |
| 	DBG_DEC(pImg->iHeight);
 | |
| 	DBG_DEC(pImg->uiBitsPerComponent);
 | |
| 	DBG_DEC(pImg->iComponents);
 | |
| 
 | |
| 	/* Do some sanity checks with the parameters */
 | |
| 	if (pImg->iHeight <= 0 ||
 | |
| 	    pImg->iWidth <= 0 ||
 | |
| 	    pImg->iComponents <= 0) {
 | |
| 		DBG_DEC(pImg->iHeight);
 | |
| 		DBG_DEC(pImg->iWidth);
 | |
| 		DBG_DEC(pImg->iComponents);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	/* Some broken JPEG files have this but they print anyway... */
 | |
| 	if (pImg->iComponents * 3 + 8 != (int)tLength) {
 | |
| 		DBG_MSG("Warning: SOF marker has incorrect length - ignored");
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->uiBitsPerComponent != 8) {
 | |
| 		DBG_DEC(pImg->uiBitsPerComponent);
 | |
| 		DBG_MSG("Not supported in PostScript level 2");
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->iComponents != 1 &&
 | |
| 	    pImg->iComponents != 3 &&
 | |
| 	    pImg->iComponents != 4) {
 | |
| 		DBG_DEC(pImg->iComponents);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	pImg->bColorImage = pImg->iComponents >= 3;
 | |
| 	pImg->iColorsUsed = 0;
 | |
| 	pImg->eCompression = compression_jpeg;
 | |
| 
 | |
| 	return TRUE;
 | |
| } /* end of bExamineJPEG */
 | |
| 
 | |
| /*
 | |
|  * bFillPalettePNG - fill the palette part of the imagesdata
 | |
|  *
 | |
|  * returns TRUE if sucessful, otherwise FALSE;
 | |
|  */
 | |
| static BOOL
 | |
| bFillPalettePNG(FILE *pFile, imagedata_type *pImg, size_t tLength)
 | |
| {
 | |
| 	int	iIndex, iEntries;
 | |
| 
 | |
| 	fail(pFile == NULL);
 | |
| 	fail(pImg == NULL);
 | |
| 
 | |
| 	if (pImg->uiBitsPerComponent > 8) {
 | |
| 		/* No palette, image uses more than 256 colors */
 | |
| 		return TRUE;
 | |
| 	}
 | |
| 
 | |
| 	if (!pImg->bColorImage) {
 | |
| 		/* Only color images can have a palette */
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	if (tLength % 3 != 0) {
 | |
| 		/* Each palette entry takes three bytes */
 | |
| 		DBG_DEC(tLength);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	iEntries = (int)(tLength / 3);
 | |
| 	DBG_DEC(iEntries);
 | |
| 	pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent;
 | |
| 	DBG_DEC(pImg->iColorsUsed);
 | |
| 
 | |
| 	if (iEntries > 256) {
 | |
| 		DBG_DEC(iEntries);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	for (iIndex = 0; iIndex < iEntries; iIndex++) {
 | |
| 		pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile);
 | |
| 		pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile);
 | |
| 		pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile);
 | |
| 		NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3);
 | |
| 	}
 | |
| 	for (;iIndex < pImg->iColorsUsed; iIndex++) {
 | |
| 		pImg->aucPalette[iIndex][0] = 0;
 | |
| 		pImg->aucPalette[iIndex][1] = 0;
 | |
| 		pImg->aucPalette[iIndex][2] = 0;
 | |
| 	}
 | |
| 
 | |
| 	return TRUE;
 | |
| } /* end of bFillPalettePNG */
 | |
| 
 | |
| /*
 | |
|  * bExaminePNG - Examine a PNG header
 | |
|  *
 | |
|  * return TRUE if successful, otherwise FALSE
 | |
|  */
 | |
| static BOOL
 | |
| bExaminePNG(FILE *pFile, imagedata_type *pImg)
 | |
| {
 | |
| 	size_t		tLength;
 | |
| 	ULONG		ulLong1, ulLong2, ulName;
 | |
| 	int		iIndex, iTmp;
 | |
| 	int		iCompressionMethod, iFilterMethod, iInterlaceMethod;
 | |
| 	int		iColor, iIncrement;
 | |
| 	BOOL		bHasPalette, bHasAlpha;
 | |
| 	UCHAR	aucBuf[4];
 | |
| 
 | |
| 	/* Check signature */
 | |
| 	ulLong1 = ulNextLongBE(pFile);
 | |
| 	ulLong2 = ulNextLongBE(pFile);
 | |
| 	if (ulLong1 != 0x89504e47UL || ulLong2 != 0x0d0a1a0aUL) {
 | |
| 		DBG_HEX(ulLong1);
 | |
| 		DBG_HEX(ulLong2);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	ulName = 0x00;
 | |
| 	bHasPalette = FALSE;
 | |
| 
 | |
| 	/* Examine chunks */
 | |
| 	while (ulName != PNG_CN_IEND) {
 | |
| 		tLength = (size_t)ulNextLongBE(pFile);
 | |
| 		ulName = 0x00;
 | |
| 		for (iIndex = 0; iIndex < (int)elementsof(aucBuf); iIndex++) {
 | |
| 			aucBuf[iIndex] = (UCHAR)iNextByte(pFile);
 | |
| 			if (!isalpha(aucBuf[iIndex])) {
 | |
| 				DBG_HEX(aucBuf[iIndex]);
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			ulName <<= 8;
 | |
| 			ulName |= aucBuf[iIndex];
 | |
| 		}
 | |
| 
 | |
| 		switch (ulName) {
 | |
| 		case PNG_CN_IHDR:
 | |
| 			/* Header chunck */
 | |
| 			if (tLength < 13) {
 | |
| 				DBG_DEC(tLength);
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			pImg->iWidth = (int)ulNextLongBE(pFile);
 | |
| 			pImg->iHeight = (int)ulNextLongBE(pFile);
 | |
| 			pImg->uiBitsPerComponent = (UINT)iNextByte(pFile);
 | |
| 			iTmp = iNextByte(pFile);
 | |
| 			NO_DBG_HEX(iTmp);
 | |
| 			pImg->bColorImage = (iTmp & PNG_CB_COLOR) != 0;
 | |
| 			bHasPalette = (iTmp & PNG_CB_PALETTE) != 0;
 | |
| 			bHasAlpha = (iTmp & PNG_CB_ALPHA) != 0;
 | |
| 			if (bHasPalette && pImg->uiBitsPerComponent > 8) {
 | |
| 				/* This should not happen */
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			pImg->iComponents =
 | |
| 				(bHasPalette || !pImg->bColorImage) ? 1 : 3;
 | |
| 			if (bHasAlpha) {
 | |
| 				pImg->iComponents++;
 | |
| 			}
 | |
| 			iCompressionMethod = iNextByte(pFile);
 | |
| 			if (iCompressionMethod != 0) {
 | |
| 				DBG_DEC(iCompressionMethod);
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			iFilterMethod = iNextByte(pFile);
 | |
| 			if (iFilterMethod != 0) {
 | |
| 				DBG_DEC(iFilterMethod);
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			iInterlaceMethod = iNextByte(pFile);
 | |
| 			if (iInterlaceMethod != 0) {
 | |
| 				DBG_DEC(iInterlaceMethod);
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			pImg->iColorsUsed = 0;
 | |
| 			(void)tSkipBytes(pFile, tLength - 13 + 4);
 | |
| 			break;
 | |
| 		case PNG_CN_PLTE:
 | |
| 			if (!bHasPalette) {
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			if (!bFillPalettePNG(pFile, pImg, tLength)) {
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			(void)tSkipBytes(pFile, 4);
 | |
| 			break;
 | |
| 		default:
 | |
| 			(void)tSkipBytes(pFile, tLength + 4);
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	DBG_DEC(pImg->iWidth);
 | |
| 	DBG_DEC(pImg->iHeight);
 | |
| 	DBG_DEC(pImg->uiBitsPerComponent);
 | |
| 	DBG_DEC(pImg->iColorsUsed);
 | |
| 	DBG_DEC(pImg->iComponents);
 | |
| 
 | |
| 	/* Do some sanity checks with the parameters */
 | |
| 	if (pImg->iWidth <= 0 || pImg->iHeight <= 0) {
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 2 &&
 | |
| 	    pImg->uiBitsPerComponent != 4 && pImg->uiBitsPerComponent != 8 &&
 | |
| 	    pImg->uiBitsPerComponent != 16) {
 | |
| 		DBG_DEC(pImg->uiBitsPerComponent);
 | |
| 		return  FALSE;
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->iComponents != 1 && pImg->iComponents != 3) {
 | |
| 		/* Not supported */
 | |
| 		DBG_DEC(pImg->iComponents);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->uiBitsPerComponent > 8) {
 | |
| 		/* Not supported */
 | |
| 		DBG_DEC(pImg->uiBitsPerComponent);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->iColorsUsed == 0 &&
 | |
| 	    pImg->iComponents == 1 &&
 | |
| 	    pImg->uiBitsPerComponent <= 4) {
 | |
| 		/*
 | |
| 		 * No palette is supplied, but PostScript needs one in these
 | |
| 		 * cases, so we add a default palette here
 | |
| 		 */
 | |
| 		pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent;
 | |
| 		iIncrement = 0xff / (pImg->iColorsUsed - 1);
 | |
| 		for (iIndex = 0, iColor = 0x00;
 | |
| 		     iIndex < pImg->iColorsUsed;
 | |
| 		     iIndex++, iColor += iIncrement) {
 | |
| 			pImg->aucPalette[iIndex][0] = (UCHAR)iColor;
 | |
| 			pImg->aucPalette[iIndex][1] = (UCHAR)iColor;
 | |
| 			pImg->aucPalette[iIndex][2] = (UCHAR)iColor;
 | |
| 		}
 | |
| 		/* Just to be sure */
 | |
| 		pImg->bColorImage = FALSE;
 | |
| 	}
 | |
| 
 | |
| 	pImg->eCompression = compression_zlib;
 | |
| 
 | |
| 	return TRUE;
 | |
| } /* end of bExaminePNG */
 | |
| 
 | |
| /*
 | |
|  * bExamineWMF - Examine a WMF header
 | |
|  *
 | |
|  * return TRUE if successful, otherwise FALSE
 | |
|  */
 | |
| static BOOL
 | |
| bExamineWMF(FILE *pFile, imagedata_type *pImg)
 | |
| {
 | |
| 	ULONG	ulFileSize, ulMaxRecord, ulMagic;
 | |
| 	USHORT	usType, usHeaderSize, usVersion, usNoObjects;
 | |
| 
 | |
| 	usType = usNextWord(pFile);
 | |
| 	usHeaderSize = usNextWord(pFile);
 | |
| 	ulMagic = ((ULONG)usHeaderSize << 16) | (ULONG)usType;
 | |
| 	usVersion = usNextWord(pFile);
 | |
| 	ulFileSize = ulNextLong(pFile);
 | |
| 	usNoObjects = usNextWord(pFile);
 | |
| 	ulMaxRecord = ulNextLong(pFile);
 | |
| 
 | |
| 	DBG_HEX(ulMagic);
 | |
| 	DBG_DEC(usType);
 | |
| 	DBG_DEC(usHeaderSize);
 | |
| 	DBG_HEX(usVersion);
 | |
| 	DBG_DEC(ulFileSize);
 | |
| 	DBG_DEC(usNoObjects);
 | |
| 	DBG_DEC(ulMaxRecord);
 | |
| 
 | |
| 	return FALSE;
 | |
| } /* end of bExamineWMF */
 | |
| 
 | |
| #if !defined(__riscos)
 | |
| /*
 | |
|  * vImage2Papersize - make sure the image fits on the paper
 | |
|  *
 | |
|  * This function should not be needed if Word would do a proper job
 | |
|  */
 | |
| static void
 | |
| vImage2Papersize(imagedata_type *pImg)
 | |
| {
 | |
| 	static int	iNetPageHeight = -1;
 | |
| 	static int	iNetPageWidth = -1;
 | |
| 	options_type	tOptions;
 | |
|         double  dVerFactor, dHorFactor, dFactor;
 | |
| 
 | |
| 	DBG_MSG("vImage2Papersize");
 | |
| 
 | |
| 	fail(pImg == NULL);
 | |
| 
 | |
| 	if (iNetPageHeight < 0 || iNetPageWidth < 0) {
 | |
| 		/* Get the page dimensions from the options */
 | |
| 		vGetOptions(&tOptions);
 | |
| 		/* Add 999 to err on the save side */
 | |
| 		iNetPageHeight = tOptions.iPageHeight -
 | |
| 				(lDrawUnits2MilliPoints(
 | |
| 					PS_TOP_MARGIN + PS_BOTTOM_MARGIN) +
 | |
| 					999) / 1000;
 | |
| 		iNetPageWidth = tOptions.iPageWidth -
 | |
| 				(lDrawUnits2MilliPoints(
 | |
| 					PS_LEFT_MARGIN + PS_RIGHT_MARGIN) +
 | |
| 					999) / 1000;
 | |
| 		DBG_DEC(iNetPageHeight);
 | |
| 		DBG_DEC(iNetPageWidth);
 | |
| 	}
 | |
| 
 | |
| 	if (pImg->iVerSizeScaled < iNetPageHeight &&
 | |
| 	    pImg->iHorSizeScaled < iNetPageWidth) {
 | |
| 		/* The image fits on the paper */
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	dVerFactor = (double)iNetPageHeight / (double)pImg->iVerSizeScaled;
 | |
| 	dHorFactor = (double)iNetPageWidth / (double)pImg->iHorSizeScaled;
 | |
|         dFactor = min(dVerFactor, dHorFactor);
 | |
|         DBG_FLT(dFactor);
 | |
|         /* Round down, just to be on the save side */
 | |
|         pImg->iVerSizeScaled = (int)(pImg->iVerSizeScaled * dFactor);
 | |
|         pImg->iHorSizeScaled = (int)(pImg->iHorSizeScaled * dFactor);
 | |
| } /* end of vImage2Papersize */
 | |
| #endif /* !__riscos */
 | |
| 
 | |
| /*
 | |
|  * tFind6Image - skip until the image is found
 | |
|  *
 | |
|  * Find the image in Word 6/7 files
 | |
|  *
 | |
|  * returns the new position when a image is found, otherwise -1
 | |
|  */
 | |
| static size_t
 | |
| tFind6Image(FILE *pFile, size_t tPosition, size_t tLength,
 | |
| 	imagetype_enum *peImageType)
 | |
| {
 | |
| 	ULONG	ulMarker;
 | |
| 	size_t	tRecordLength, tToSkip;
 | |
| 	USHORT	usMarker;
 | |
| 
 | |
| 	fail(pFile == NULL);
 | |
| 	fail(peImageType == NULL);
 | |
| 
 | |
| 	*peImageType = imagetype_is_unknown;
 | |
| 	if (tPosition + 18 >= tLength) {
 | |
| 		return (size_t)-1;
 | |
| 	}
 | |
| 
 | |
| 	ulMarker = ulNextLong(pFile);
 | |
| 	if (ulMarker != 0x00090001) {
 | |
| 		DBG_HEX(ulMarker);
 | |
| 		return (size_t)-1;
 | |
| 	}
 | |
| 	usMarker = usNextWord(pFile);
 | |
| 	if (usMarker != 0x0300) {
 | |
| 		DBG_HEX(usMarker);
 | |
| 		return (size_t)-1;
 | |
| 	}
 | |
| 	(void)tSkipBytes(pFile, 10);
 | |
| 	usMarker = usNextWord(pFile);
 | |
| 	if (usMarker != 0x0000) {
 | |
| 		DBG_HEX(usMarker);
 | |
| 		return (size_t)-1;
 | |
| 	}
 | |
| 	tPosition += 18;
 | |
| 
 | |
| 	while (tPosition + 6 <= tLength) {
 | |
| 		tRecordLength = (size_t)ulNextLong(pFile);
 | |
| 		usMarker = usNextWord(pFile);
 | |
| 		tPosition += 6;
 | |
| 		NO_DBG_DEC(tRecordLength);
 | |
| 		NO_DBG_HEX(usMarker);
 | |
| 		switch (usMarker) {
 | |
| 		case 0x0000:
 | |
| 			DBG_HEX(ulGetDataOffset(pFile));
 | |
| 			return (size_t)-1;
 | |
| 		case 0x0b41:
 | |
| 			DBG_MSG("DIB");
 | |
| 			*peImageType = imagetype_is_dib;
 | |
| 			tPosition += tSkipBytes(pFile, 20);
 | |
| 			return tPosition;
 | |
| 		case 0x0f43:
 | |
| 			DBG_MSG("DIB");
 | |
| 			*peImageType = imagetype_is_dib;
 | |
| 			tPosition += tSkipBytes(pFile, 22);
 | |
| 			return tPosition;
 | |
| 		default:
 | |
| 			if (tRecordLength < 3) {
 | |
| 				break;
 | |
| 			}
 | |
| 			if (tRecordLength > SIZE_T_MAX / 2) {
 | |
| 				/*
 | |
| 				 * No need to compute the number of bytes
 | |
| 				 * to skip
 | |
| 				 */
 | |
| 				DBG_DEC(tRecordLength);
 | |
| 				DBG_HEX(tRecordLength);
 | |
| 				DBG_FIXME();
 | |
| 				return (size_t)-1;
 | |
| 			}
 | |
| 			tToSkip = tRecordLength * 2 - 6;
 | |
| 			if (tToSkip > tLength - tPosition) {
 | |
| 				/* You can't skip this number of bytes */
 | |
| 				DBG_DEC(tToSkip);
 | |
| 				DBG_DEC(tLength - tPosition);
 | |
| 				return (size_t)-1;
 | |
| 			}
 | |
| 			tPosition += tSkipBytes(pFile, tToSkip);
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return (size_t)-1;
 | |
| } /* end of tFind6Image */
 | |
| 
 | |
| /*
 | |
|  * tFind8Image - skip until the image is found
 | |
|  *
 | |
|  * Find the image in Word 8/9/10 files
 | |
|  *
 | |
|  * returns the new position when a image is found, otherwise -1
 | |
|  */
 | |
| static size_t
 | |
| tFind8Image(FILE *pFile, size_t tPosition, size_t tLength,
 | |
| 	imagetype_enum *peImageType)
 | |
| {
 | |
| 	size_t	tRecordLength, tNameLen;
 | |
| 	USHORT	usRecordVersion, usRecordType, usRecordInstance;
 | |
| 	USHORT	usTmp;
 | |
| 
 | |
| 	fail(pFile == NULL);
 | |
| 	fail(peImageType == NULL);
 | |
| 
 | |
| 	*peImageType = imagetype_is_unknown;
 | |
| 	while (tPosition + 8 <= tLength) {
 | |
| 		usTmp = usNextWord(pFile);
 | |
| 		usRecordVersion = usTmp & 0x000f;
 | |
| 		usRecordInstance = usTmp >> 4;
 | |
| 		usRecordType = usNextWord(pFile);
 | |
| 		tRecordLength = (size_t)ulNextLong(pFile);
 | |
| 		tPosition += 8;
 | |
| 		NO_DBG_HEX(usRecordVersion);
 | |
| 		NO_DBG_HEX(usRecordInstance);
 | |
| 		NO_DBG_HEX(usRecordType);
 | |
| 		NO_DBG_DEC(tRecordLength);
 | |
| 		switch (usRecordType) {
 | |
| 		case 0xf000: case 0xf001: case 0xf002: case 0xf003:
 | |
| 		case 0xf004: case 0xf005:
 | |
| 			break;
 | |
| 		case 0xf007:
 | |
| 			tPosition += tSkipBytes(pFile, 33);
 | |
| 			tNameLen = (size_t)iNextByte(pFile);
 | |
| 			tPosition++;
 | |
| 			DBG_DEC_C(tNameLen != 0, tNameLen);
 | |
| 			tPosition += tSkipBytes(pFile, 2 + tNameLen * 2);
 | |
| 			break;
 | |
| 		case 0xf008:
 | |
| 			tPosition += tSkipBytes(pFile, 8);
 | |
| 			break;
 | |
| 		case 0xf009:
 | |
| 			tPosition += tSkipBytes(pFile, 16);
 | |
| 			break;
 | |
| 		case 0xf006: case 0xf00a: case 0xf00b: case 0xf00d:
 | |
| 		case 0xf00e: case 0xf00f: case 0xf010: case 0xf011:
 | |
| 		case 0xf122:
 | |
| 			tPosition += tSkipBytes(pFile, tRecordLength);
 | |
| 			break;
 | |
| 		case 0xf01a:
 | |
| 			DBG_MSG("EMF");
 | |
| 			*peImageType = imagetype_is_emf;
 | |
| 			tPosition += tSkipBytes(pFile, 50);
 | |
| 			if ((usRecordInstance ^ MSOBI_EMF) == 1) {
 | |
| 				tPosition += tSkipBytes(pFile, 16);
 | |
| 			}
 | |
| 			return tPosition;
 | |
| 		case 0xf01b:
 | |
| 			DBG_MSG("WMF");
 | |
| 			*peImageType = imagetype_is_wmf;
 | |
| 			tPosition += tSkipBytes(pFile, 50);
 | |
| 			if ((usRecordInstance ^ MSOBI_WMF) == 1) {
 | |
| 				tPosition += tSkipBytes(pFile, 16);
 | |
| 			}
 | |
| 			return tPosition;
 | |
| 		case 0xf01c:
 | |
| 			DBG_MSG("PICT");
 | |
| 			*peImageType = imagetype_is_pict;
 | |
| 			tPosition += tSkipBytes(pFile, 50);
 | |
| 			if ((usRecordInstance ^ MSOBI_PICT) == 1) {
 | |
| 				tPosition += tSkipBytes(pFile, 16);
 | |
| 			}
 | |
| 			return tPosition;
 | |
| 		case 0xf01d:
 | |
| 			DBG_MSG("JPEG");
 | |
| 			*peImageType = imagetype_is_jpeg;
 | |
| 			tPosition += tSkipBytes(pFile, 17);
 | |
| 			if ((usRecordInstance ^ MSOBI_JPEG) == 1) {
 | |
| 				tPosition += tSkipBytes(pFile, 16);
 | |
| 			}
 | |
| 			return tPosition;
 | |
| 		case 0xf01e:
 | |
| 			DBG_MSG("PNG");
 | |
| 			*peImageType = imagetype_is_png;
 | |
| 			tPosition += tSkipBytes(pFile, 17);
 | |
| 			if ((usRecordInstance ^ MSOBI_PNG) == 1) {
 | |
| 				tPosition += tSkipBytes(pFile, 16);
 | |
| 			}
 | |
| 			return tPosition;
 | |
| 		case 0xf01f:
 | |
| 			DBG_MSG("DIB");
 | |
| 			/* DIB is a BMP minus its 14 byte header */
 | |
| 			*peImageType = imagetype_is_dib;
 | |
| 			tPosition += tSkipBytes(pFile, 17);
 | |
| 			if ((usRecordInstance ^ MSOBI_DIB) == 1) {
 | |
| 				tPosition += tSkipBytes(pFile, 16);
 | |
| 			}
 | |
| 			return tPosition;
 | |
| 		case 0xf00c:
 | |
| 		default:
 | |
| 			DBG_HEX(usRecordType);
 | |
| 			DBG_DEC_C(tRecordLength % 4 != 0, tRecordLength);
 | |
| 			DBG_FIXME();
 | |
| 			return (size_t)-1;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return (size_t)-1;
 | |
| } /* end of tFind8Image */
 | |
| 
 | |
| /*
 | |
|  * eExamineImage - Examine the image
 | |
|  *
 | |
|  * Returns an indication of the amount of information found
 | |
|  */
 | |
| image_info_enum
 | |
| eExamineImage(FILE *pFile, ULONG ulFileOffsetImage, imagedata_type *pImg)
 | |
| {
 | |
| 	long	lTmp;
 | |
| 	size_t	tWordHeaderLen, tLength, tPos;
 | |
| 	int	iType, iHorSize, iVerSize;
 | |
| 	USHORT	usHorScalingFactor, usVerScalingFactor;
 | |
| 
 | |
| 	if (ulFileOffsetImage == FC_INVALID) {
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| 	DBG_HEX(ulFileOffsetImage);
 | |
| 
 | |
| 	if (!bSetDataOffset(pFile, ulFileOffsetImage)) {
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| 
 | |
| 	tLength = (size_t)ulNextLong(pFile);
 | |
| 	DBG_DEC(tLength);
 | |
| 	if (tLength < 46) {
 | |
| 		/* Smaller than the smallest known header */
 | |
| 		DBG_FIXME();
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| 	tWordHeaderLen = (size_t)usNextWord(pFile);
 | |
| 	DBG_DEC(tWordHeaderLen);
 | |
| 	fail(tWordHeaderLen != 46 &&
 | |
| 		tWordHeaderLen != 58 &&
 | |
| 		tWordHeaderLen != 68);
 | |
| 
 | |
| 	if (tLength < tWordHeaderLen) {
 | |
| 		/* Smaller than the current header */
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| 	iType = (int)usNextWord(pFile);
 | |
| 	DBG_DEC(iType);
 | |
| 	(void)tSkipBytes(pFile, 28 - 8);
 | |
| 
 | |
| 	lTmp = lTwips2MilliPoints(usNextWord(pFile));
 | |
| 	iHorSize = (int)(lTmp / 1000);
 | |
| 	if (lTmp % 1000 != 0) {
 | |
| 		iHorSize++;
 | |
| 	}
 | |
| 	DBG_DEC(iHorSize);
 | |
| 	lTmp = lTwips2MilliPoints(usNextWord(pFile));
 | |
| 	iVerSize = (int)(lTmp / 1000);
 | |
| 	if (lTmp % 1000 != 0) {
 | |
| 		iVerSize++;
 | |
| 	}
 | |
| 	DBG_DEC(iVerSize);
 | |
| 
 | |
| 	usHorScalingFactor = usNextWord(pFile);
 | |
| 	DBG_DEC(usHorScalingFactor);
 | |
| 	usVerScalingFactor = usNextWord(pFile);
 | |
| 	DBG_DEC(usVerScalingFactor);
 | |
| 
 | |
| 	/* Sanity checks */
 | |
| 	lTmp = (long)iHorSize * (long)usHorScalingFactor;
 | |
| 	if (lTmp < 2835) {
 | |
| 		/* This image would be less than 1 millimeter wide */
 | |
| 		DBG_DEC(lTmp);
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| 	lTmp = (long)iVerSize * (long)usVerScalingFactor;
 | |
| 	if (lTmp < 2835) {
 | |
| 		/* This image would be less than 1 millimeter high */
 | |
| 		DBG_DEC(lTmp);
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| 
 | |
| 	/* Skip the rest of the header */
 | |
| 	(void)tSkipBytes(pFile, tWordHeaderLen - 36);
 | |
| 	tPos = tWordHeaderLen;
 | |
| 
 | |
| 	(void)memset(pImg, 0, sizeof(*pImg));
 | |
| 
 | |
| 	switch (iType) {
 | |
| 	case   7:
 | |
| 	case   8:
 | |
| 		tPos = tFind6Image(pFile, tPos, tLength, &pImg->eImageType);
 | |
| 		if (tPos == (size_t)-1) {
 | |
| 			/* No image found */
 | |
| 			return image_no_information;
 | |
| 		}
 | |
| 		DBG_HEX(tPos);
 | |
| 		break;
 | |
| 	case  94:	/* Word 6/7, no image just a pathname */
 | |
| 		pImg->eImageType = imagetype_is_external;
 | |
| 		DBG_HEX(ulFileOffsetImage + tPos);
 | |
| 		break;
 | |
| 	case 100:
 | |
| 		tPos = tFind8Image(pFile, tPos, tLength, &pImg->eImageType);
 | |
| 		if (tPos == (size_t)-1) {
 | |
| 			/* No image found */
 | |
| 			return image_no_information;
 | |
| 		}
 | |
| 		DBG_HEX(tPos);
 | |
| 		break;
 | |
| 	case 102:	/* Word 8/9/10, no image just a pathname or URL */
 | |
| 		pImg->eImageType = imagetype_is_external;
 | |
| 		DBG_HEX(ulFileOffsetImage + tPos);
 | |
| 		break;
 | |
| 	default:
 | |
| 		DBG_DEC(iType);
 | |
| 		DBG_HEX(ulFileOffsetImage + tPos);
 | |
| 		DBG_FIXME();
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| 
 | |
| 	/* Minimal information is now available */
 | |
| 	pImg->tLength = tLength;
 | |
| 	pImg->tPosition = tPos;
 | |
| 	pImg->iHorSizeScaled =
 | |
| 		(int)(((long)iHorSize * (long)usHorScalingFactor + 500) / 1000);
 | |
| 	pImg->iVerSizeScaled =
 | |
| 		(int)(((long)iVerSize * (long)usVerScalingFactor + 500) / 1000);
 | |
| #if !defined(__riscos)
 | |
| 	vImage2Papersize(pImg);
 | |
| #endif /* !__riscos */
 | |
| 
 | |
| 	/* Image type specific examinations */
 | |
| 	switch (pImg->eImageType) {
 | |
| 	case imagetype_is_dib:
 | |
| 		if (bExamineDIB(pFile, pImg)) {
 | |
| 			return image_full_information;
 | |
| 		}
 | |
| 		return image_minimal_information;
 | |
| 	case imagetype_is_jpeg:
 | |
| 		if (bExamineJPEG(pFile, pImg)) {
 | |
| 			return image_full_information;
 | |
| 		}
 | |
| 		return image_minimal_information;
 | |
| 	case imagetype_is_png:
 | |
| 		if (bExaminePNG(pFile, pImg)) {
 | |
| 			return image_full_information;
 | |
| 		}
 | |
| 		return image_minimal_information;
 | |
| 	case imagetype_is_wmf:
 | |
| 		if (bExamineWMF(pFile, pImg)) {
 | |
| 			return image_full_information;
 | |
| 		}
 | |
| 		return image_minimal_information;
 | |
| 	case imagetype_is_emf:
 | |
| 	case imagetype_is_pict:
 | |
| 	case imagetype_is_external:
 | |
| 		return image_minimal_information;
 | |
| 	case imagetype_is_unknown:
 | |
| 	default:
 | |
| 		return image_no_information;
 | |
| 	}
 | |
| } /* end of eExamineImage */
 |