123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /*
- * 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)
- {
- int32_t 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 = (int32_t)iHorSize * (int32_t)usHorScalingFactor;
- if (lTmp < 2835) {
- /* This image would be less than 1 millimeter wide */
- DBG_DEC(lTmp);
- return image_no_information;
- }
- lTmp = (int32_t)iVerSize * (int32_t)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)(((int32_t)iHorSize * (int32_t)usHorScalingFactor + 500) / 1000);
- pImg->iVerSizeScaled =
- (int)(((int32_t)iVerSize * (int32_t)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 */
|