imgexam.c 26 KB

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