image.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. //*****************************************************************************
  2. //
  3. // image.c - Routines for drawing bitmap images.
  4. //
  5. // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Texas Instruments (TI) is supplying this software for use solely and
  9. // exclusively on TI's microcontroller products. The software is owned by
  10. // TI and/or its suppliers, and is protected under applicable copyright
  11. // laws. You may not combine this software with "viral" open-source
  12. // software in order to form a larger program.
  13. //
  14. // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  15. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  16. // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  18. // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  19. // DAMAGES, FOR ANY REASON WHATSOEVER.
  20. //
  21. // This is part of revision 6288 of the Stellaris Graphics Library.
  22. //
  23. //*****************************************************************************
  24. #include "debug.h"
  25. #include "grlib.h"
  26. //*****************************************************************************
  27. //
  28. //! \addtogroup primitives_api
  29. //! @{
  30. //
  31. //*****************************************************************************
  32. //*****************************************************************************
  33. //
  34. // The buffer that holds the dictionary used by the Lempel-Ziv-Storer-Szymanski
  35. // compression algorithm. This is simply the last 32 bytes decoded from the
  36. // stream, and is initially filled with zeros.
  37. //
  38. //*****************************************************************************
  39. static unsigned char g_pucDictionary[32];
  40. //*****************************************************************************
  41. //
  42. //! Draws a bitmap image.
  43. //!
  44. //! \param pContext is a pointer to the drawing context to use.
  45. //! \param pucImage is a pointer to the image to draw.
  46. //! \param lX is the X coordinate of the upper left corner of the image.
  47. //! \param lY is the Y coordinate of the upper left corner of the image.
  48. //!
  49. //! This function draws a bitmap image. The image may be 1 bit per pixel
  50. //! (using the foreground and background color from the drawing context), 4
  51. //! bits per pixel (using a palette supplied in the image data), or 8 bits per
  52. //! pixel (using a palette supplied in the image data). It can be uncompressed
  53. //! data, or it can be compressed using the Lempel-Ziv-Storer-Szymanski
  54. //! algorithm (as published in the Journal of the ACM, 29(4):928-951, October
  55. //! 1982).
  56. //!
  57. //! \return None.
  58. //
  59. //*****************************************************************************
  60. void
  61. GrImageDraw(const tContext *pContext, const unsigned char *pucImage, int lX,
  62. int lY)
  63. {
  64. unsigned int ulByte, ulBits, ulMatch, ulSize, ulIdx, ulCount, ulNum;
  65. int lBPP, lWidth, lHeight, lX0, lX1, lX2;
  66. const unsigned char *pucPalette = 0;
  67. unsigned char pucBWPalette[8];
  68. //
  69. // Check the arguments.
  70. //
  71. ASSERT(pContext);
  72. ASSERT(pucImage);
  73. //
  74. // Get the image format from the image data.
  75. //
  76. lBPP = *pucImage++;
  77. #ifdef SUPPORT_UNALIGNED
  78. //
  79. // Get the image width from the image data.
  80. //
  81. lWidth = *(unsigned short *)pucImage;
  82. pucImage += 2;
  83. //
  84. // Get the image height from the image data.
  85. //
  86. lHeight = *(unsigned short *)pucImage;
  87. pucImage += 2;
  88. #else
  89. // Get the image width from the image data.
  90. lWidth = *pucImage++;
  91. lWidth = lWidth | ((*pucImage++) << 8);
  92. // Get the image height from the image data.
  93. lHeight = *pucImage++;
  94. lHeight = lHeight | ((*pucImage++) << 8);
  95. #endif
  96. //
  97. // Return without doing anything if the entire image lies outside the
  98. // current clipping region.
  99. //
  100. if((lX > pContext->sClipRegion.sXMax) ||
  101. ((lX + lWidth - 1) < pContext->sClipRegion.sXMin) ||
  102. (lY > pContext->sClipRegion.sYMax) ||
  103. ((lY + lHeight - 1) < pContext->sClipRegion.sYMin))
  104. {
  105. return;
  106. }
  107. //
  108. // Get the starting X offset within the image based on the current clipping
  109. // region.
  110. //
  111. if(lX < pContext->sClipRegion.sXMin)
  112. {
  113. lX0 = pContext->sClipRegion.sXMin - lX;
  114. }
  115. else
  116. {
  117. lX0 = 0;
  118. }
  119. //
  120. // Get the ending X offset within the image based on the current clipping
  121. // region.
  122. //
  123. if((lX + lWidth - 1) > pContext->sClipRegion.sXMax)
  124. {
  125. lX2 = pContext->sClipRegion.sXMax - lX;
  126. }
  127. else
  128. {
  129. lX2 = lWidth - 1;
  130. }
  131. //
  132. // Reduce the height of the image, if required, based on the current
  133. // clipping region.
  134. //
  135. if((lY + lHeight - 1) > pContext->sClipRegion.sYMax)
  136. {
  137. lHeight = pContext->sClipRegion.sYMax - lY + 1;
  138. }
  139. //
  140. // Determine the color palette for the image based on the image format.
  141. //
  142. if((lBPP & 0x7f) == IMAGE_FMT_1BPP_UNCOMP)
  143. {
  144. //
  145. // Construct a local "black & white" palette based on the foreground
  146. // and background colors of the drawing context.
  147. //
  148. *(unsigned int *)pucBWPalette = pContext->ulBackground;
  149. *(unsigned int *)(pucBWPalette + 4) = pContext->ulForeground;
  150. //
  151. // Set the palette pointer to the local "black & white" palette.
  152. //
  153. pucPalette = pucBWPalette;
  154. }
  155. else if ( ((lBPP & 0x7f) == IMAGE_FMT_4BPP_UNCOMP) ||
  156. ((lBPP & 0x7f) == IMAGE_FMT_8BPP_UNCOMP))
  157. {
  158. //
  159. // For 4 and 8 BPP images, the palette is contained at the start of the
  160. // image data.
  161. //
  162. pucPalette = pucImage + 1;
  163. pucImage += (pucImage[0] * 3) + 4;
  164. }
  165. //
  166. // See if the image is compressed.
  167. //
  168. if(!(lBPP & 0x80))
  169. {
  170. //
  171. // The image is not compressed. See if the top portion of the image
  172. // lies above the clipping region.
  173. //
  174. if(lY < pContext->sClipRegion.sYMin)
  175. {
  176. //
  177. // Determine the number of rows that lie above the clipping region.
  178. //
  179. lX1 = pContext->sClipRegion.sYMin - lY;
  180. //
  181. // Skip past the data for the rows that lie above the clipping
  182. // region.
  183. //
  184. pucImage += (((lWidth * lBPP) + 7) / 8) * lX1;
  185. //
  186. // Decrement the image height by the number of skipped rows.
  187. //
  188. lHeight -= lX1;
  189. //
  190. // Increment the starting Y coordinate by the number of skipped
  191. // rows.
  192. //
  193. lY += lX1;
  194. }
  195. //
  196. // Loop while there are more rows to draw.
  197. //
  198. while(lHeight--)
  199. {
  200. //
  201. // Draw this row of image pixels.
  202. //
  203. DpyPixelDrawMultiple(pContext->pDisplay, lX + lX0, lY, lX0 & 7,
  204. lX2 - lX0 + 1, lBPP,
  205. pucImage + ((lX0 * lBPP) / 8), pucPalette);
  206. //
  207. // Skip past the data for this row.
  208. //
  209. pucImage += ((lWidth * lBPP) + 7) / 8;
  210. //
  211. // Increment the Y coordinate.
  212. //
  213. lY++;
  214. }
  215. }
  216. else
  217. {
  218. //
  219. // The image is compressed. Clear the compressed flag in the format
  220. // specifier so that the bits per pixel remains.
  221. //
  222. lBPP &= 0x7f;
  223. //
  224. // Reset the dictionary used to uncompress the image.
  225. //
  226. for(ulBits = 0; ulBits < sizeof(g_pucDictionary); ulBits += 4)
  227. {
  228. *(unsigned int *)(g_pucDictionary + ulBits) = 0;
  229. }
  230. //
  231. // Determine the number of bytes of data to decompress.
  232. //
  233. ulCount = (((lWidth * lBPP) + 7) / 8) * lHeight;
  234. //
  235. // Initialize the pointer into the dictionary.
  236. //
  237. ulIdx = 0;
  238. //
  239. // Start off with no encoding byte.
  240. //
  241. ulBits = 0;
  242. ulByte = 0;
  243. //
  244. // Start from the upper left corner of the image.
  245. //
  246. lX1 = 0;
  247. //
  248. // Loop while there are more rows or more data in the image.
  249. //
  250. while(lHeight && ulCount)
  251. {
  252. //
  253. // See if an encoding byte needs to be read.
  254. //
  255. if(ulBits == 0)
  256. {
  257. //
  258. // Read the encoding byte, which indicates if each of the
  259. // following eight bytes are encoded or literal.
  260. //
  261. ulByte = *pucImage++;
  262. ulBits = 8;
  263. }
  264. //
  265. // See if the next byte is encoded or literal.
  266. //
  267. if(ulByte & (1 << (ulBits - 1)))
  268. {
  269. //
  270. // This byte is encoded, so extract the location and size of
  271. // the encoded data within the dictionary.
  272. //
  273. ulMatch = *pucImage >> 3;
  274. ulSize = (*pucImage++ & 7) + 2;
  275. //
  276. // Decrement the count of bytes to decode by the number of
  277. // copied bytes.
  278. //
  279. ulCount -= ulSize;
  280. }
  281. else
  282. {
  283. //
  284. // This byte is a literal, so copy it into the dictionary.
  285. //
  286. g_pucDictionary[ulIdx++] = *pucImage++;
  287. //
  288. // Decrement the count of bytes to decode.
  289. //
  290. ulCount--;
  291. //
  292. // Clear any previous encoded data information.
  293. //
  294. ulMatch = 0;
  295. ulSize = 0;
  296. }
  297. //
  298. // Loop while there are bytes to copy for the encoded data, or
  299. // once for literal data.
  300. //
  301. while(ulSize || !(ulByte & (1 << (ulBits - 1))))
  302. {
  303. //
  304. // Set the encoded data bit for this data so that this loop
  305. // will only be executed once for literal data.
  306. //
  307. ulByte |= 1 << (ulBits - 1);
  308. //
  309. // Loop while there is more encoded data to copy and there is
  310. // additional space in the dictionary (before the buffer
  311. // wraps).
  312. //
  313. while(ulSize && (ulIdx != sizeof(g_pucDictionary)))
  314. {
  315. //
  316. // Copy this byte.
  317. //
  318. g_pucDictionary[ulIdx] =
  319. g_pucDictionary[(ulIdx + ulMatch) %
  320. sizeof(g_pucDictionary)];
  321. //
  322. // Increment the dictionary pointer.
  323. //
  324. ulIdx++;
  325. //
  326. // Decrement the encoded data size.
  327. //
  328. ulSize--;
  329. }
  330. //
  331. // See if the dictionary pointer is about to wrap, or if there
  332. // is no more data to decompress.
  333. //
  334. if((ulIdx == sizeof(g_pucDictionary)) || !ulCount)
  335. {
  336. //
  337. // Loop through the data in the dictionary buffer.
  338. //
  339. for(ulIdx = 0;
  340. (ulIdx < sizeof(g_pucDictionary)) && lHeight; )
  341. {
  342. //
  343. // Compute the number of pixels that remain in the
  344. // dictionary buffer.
  345. //
  346. ulNum = ((sizeof(g_pucDictionary) - ulIdx) * 8) / lBPP;
  347. //
  348. // See if any of the pixels in the dictionary buffer
  349. // are within the clipping region.
  350. //
  351. if((lY >= pContext->sClipRegion.sYMin) &&
  352. ((lX1 + ulNum) >= lX0) && (lX1 <= lX2))
  353. {
  354. //
  355. // Skip some pixels at the start of the scan line
  356. // if required to stay within the clipping region.
  357. //
  358. if(lX1 < lX0)
  359. {
  360. ulIdx += ((lX0 - lX1) * lBPP) / 8;
  361. lX1 = lX0;
  362. }
  363. //
  364. // Shorten the scan line if required to stay within
  365. // the clipping region.
  366. //
  367. if(ulNum > (lX2 - lX1 + 1))
  368. {
  369. ulNum = lX2 - lX1 + 1;
  370. }
  371. //
  372. // Draw this row of image pixels.
  373. //
  374. DpyPixelDrawMultiple(pContext->pDisplay, lX + lX1,
  375. lY, lX1 & 7, ulNum, lBPP,
  376. g_pucDictionary + ulIdx,
  377. pucPalette);
  378. }
  379. //
  380. // Move the X coordinate back to the start of the first
  381. // data byte in this portion of the dictionary buffer.
  382. //
  383. lX1 = ((lX1 * lBPP) & ~7) / lBPP;
  384. //
  385. // See if the remainder of this scan line resides
  386. // within the dictionary buffer.
  387. //
  388. if(((((lWidth - lX1) * lBPP) + 7) / 8) >
  389. (sizeof(g_pucDictionary) - ulIdx))
  390. {
  391. //
  392. // There is more to this scan line than is in the
  393. // dictionary buffer at this point, so move the
  394. // X coordinate by by the number of pixels in the
  395. // dictionary buffer.
  396. //
  397. lX1 += (((sizeof(g_pucDictionary) - ulIdx) * 8) /
  398. lBPP);
  399. //
  400. // The entire dictionary buffer has been scanned.
  401. //
  402. ulIdx = sizeof(g_pucDictionary);
  403. }
  404. else
  405. {
  406. //
  407. // The remainder of this scan line resides in the
  408. // dictionary buffer, so skip past it.
  409. //
  410. ulIdx += (((lWidth - lX1) * lBPP) + 7) / 8;
  411. //
  412. // Move to the start of the next scan line.
  413. //
  414. lX1 = 0;
  415. lY++;
  416. //
  417. // There is one less scan line to process.
  418. //
  419. lHeight--;
  420. }
  421. }
  422. //
  423. // Start over from the beginning of the dictionary buffer.
  424. //
  425. ulIdx = 0;
  426. }
  427. }
  428. //
  429. // Advance to the next bit in the encoding byte.
  430. //
  431. ulBits--;
  432. }
  433. }
  434. }
  435. //*****************************************************************************
  436. //
  437. // Close the Doxygen group.
  438. //! @}
  439. //
  440. //*****************************************************************************