📄 imgexam.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 BOOLbFillPaletteDIB(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 BOOLbExamineDIB(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 intiNextMarker(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 BOOLbExamineJPEG(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 BOOLbFillPalettePNG(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 BOOLbExaminePNG(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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -