home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / anwor032.zip / antiword.0.32 / imgexam.c < prev    next >
C/C++ Source or Header  |  2001-06-19  |  25KB  |  1,024 lines

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