You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
11 KiB

5 years ago
  1. /* --COPYRIGHT--,BSD
  2. * Copyright (c) 2013, Texas Instruments Incorporated
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of Texas Instruments Incorporated nor the names of
  17. * its contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  27. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  28. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. * --/COPYRIGHT--*/
  32. #include "grlib.h"
  33. //*****************************************************************************
  34. //
  35. //! \addtogroup image_api
  36. //! @{
  37. //
  38. //*****************************************************************************
  39. //*****************************************************************************
  40. //
  41. // The buffer that holds the converted palette of the image to be drawn. This
  42. // buffer contains the actual data to be written to the LCD after translation.
  43. //
  44. //*****************************************************************************
  45. static unsigned int g_pulConvertedPalette[256];
  46. //*****************************************************************************
  47. //
  48. //! Converts the bitmap image palette.
  49. //!
  50. //! \param pContext is a pointer to the drawing context to use.
  51. //! \param pBitmap is a pointer to the image.
  52. //!
  53. //! This function converts the palette of a bitmap image. The image palette is in
  54. //! 24 bit RGB form, and this function converts that to a format to be sent to the
  55. //! LCD using DpyColorTranslate function. The converted palette is contained in a
  56. //! global buffer while the original image palette remains unchanged.
  57. //!
  58. //! \return is the address of the global buffer containing the converted palette.
  59. //
  60. //*****************************************************************************
  61. unsigned int * GrPaletteConversion(const tContext *pContext, const tImage * pBitmap)
  62. {
  63. if (pBitmap->NumColors > 256)
  64. {
  65. return 0;
  66. }
  67. int i;
  68. int NumColors = pBitmap->NumColors;
  69. const unsigned long * pulPalette = &pBitmap->pPalette[0];
  70. for (i = 0; i < NumColors; i++)
  71. {
  72. g_pulConvertedPalette[i] = DpyColorTranslate(pContext->pDisplay, *(pulPalette + i));
  73. }
  74. return &g_pulConvertedPalette[0];
  75. }
  76. //*****************************************************************************
  77. //
  78. //! Draws a bitmap image.
  79. //!
  80. //! \param pContext is a pointer to the drawing context to use.
  81. //! \param pucImage is a pointer to the image to draw.
  82. //! \param lX is the X coordinate of the upper left corner of the image.
  83. //! \param lY is the Y coordinate of the upper left corner of the image.
  84. //!
  85. //! This function draws a bitmap image. The image may be 1 bit per pixel, 4
  86. //! bits per pixel or 8 bits per pixel (using a palette supplied in the image
  87. //! data). It can be uncompressed data, or it can be compressed using
  88. //! several different compression types. Compression options are 4-bit run
  89. //! length encoding, 8-bit run length encoding, and a custom run length encoding
  90. //! variation written for complex 8-bit per pixel images.
  91. //!
  92. //! \return None.
  93. //
  94. //*****************************************************************************
  95. void
  96. GrImageDraw(const tContext *pContext, const tImage *pBitmap, int lX,
  97. int lY)
  98. {
  99. int lBPP, lWidth, lHeight, lX0, lX1, lX2;
  100. const unsigned int *pucPalette;
  101. const unsigned char * pucImage;
  102. //
  103. // Check the arguments.
  104. //
  105. assert(pContext);
  106. assert(pBitmap);
  107. //
  108. // Get the image format from the image data.
  109. //
  110. lBPP = pBitmap->BPP;
  111. //
  112. // Get the image width from the image data.
  113. //
  114. lWidth = pBitmap->XSize;
  115. //
  116. // Get the image height from the image data.
  117. //
  118. lHeight = pBitmap->YSize;
  119. //
  120. // Return without doing anything if the entire image lies outside the
  121. // current clipping region.
  122. //
  123. if((lX > pContext->sClipRegion.sXMax) ||
  124. ((lX + lWidth - 1) < pContext->sClipRegion.sXMin) ||
  125. (lY > pContext->sClipRegion.sYMax) ||
  126. ((lY + lHeight - 1) < pContext->sClipRegion.sYMin))
  127. {
  128. return;
  129. }
  130. //
  131. // Get the starting X offset within the image based on the current clipping
  132. // region.
  133. //
  134. if(lX < pContext->sClipRegion.sXMin)
  135. {
  136. lX0 = pContext->sClipRegion.sXMin - lX;
  137. }
  138. else
  139. {
  140. lX0 = 0;
  141. }
  142. //
  143. // Get the ending X offset within the image based on the current clipping
  144. // region.
  145. //
  146. if((lX + lWidth - 1) > pContext->sClipRegion.sXMax)
  147. {
  148. lX2 = pContext->sClipRegion.sXMax - lX;
  149. }
  150. else
  151. {
  152. lX2 = lWidth - 1;
  153. }
  154. //
  155. // Reduce the height of the image, if required, based on the current
  156. // clipping region.
  157. //
  158. if((lY + lHeight - 1) > pContext->sClipRegion.sYMax)
  159. {
  160. lHeight = pContext->sClipRegion.sYMax - lY + 1;
  161. }
  162. //
  163. // The image palette is in 24 bit R-G-B format. The palette needs
  164. // to be translated into the color format accepted by the LCD
  165. // and stored in g_pulConvertedPalette[] buffer
  166. //
  167. pucPalette = GrPaletteConversion(pContext, pBitmap);
  168. pucImage = pBitmap->pPixel;
  169. //
  170. // Check if the image is not compressed.
  171. //
  172. if(!(lBPP & 0xF0))
  173. {
  174. //
  175. // The image is not compressed. See if the top portion of the image
  176. // lies above the clipping region.
  177. //
  178. if(lY < pContext->sClipRegion.sYMin)
  179. {
  180. //
  181. // Determine the number of rows that lie above the clipping region.
  182. //
  183. lX1 = pContext->sClipRegion.sYMin - lY;
  184. //
  185. // Skip past the data for the rows that lie above the clipping
  186. // region.
  187. //
  188. pucImage += (((lWidth * lBPP) + 7) / 8) * lX1;
  189. //
  190. // Decrement the image height by the number of skipped rows.
  191. //
  192. lHeight -= lX1;
  193. //
  194. // Increment the starting Y coordinate by the number of skipped
  195. // rows.
  196. //
  197. lY += lX1;
  198. }
  199. while(lHeight--)
  200. {
  201. //
  202. // Draw this row of image pixels.
  203. //
  204. DpyPixelDrawMultiple(pContext->pDisplay, lX + lX0, lY, lX0 & 7,
  205. lX2 - lX0 + 1, lBPP,
  206. pucImage + ((lX0 * lBPP) / 8), pucPalette);
  207. //
  208. // Skip past the data for this row.
  209. //
  210. pucImage += ((lWidth * lBPP) + 7) / 8;
  211. //
  212. // Increment the Y coordinate.
  213. //
  214. lY++;
  215. }
  216. }
  217. else
  218. {
  219. //
  220. // The image is compressed with RLE4 or RLE8 Algorithm
  221. //
  222. const unsigned char *pucData = pucImage;
  223. unsigned char ucRunLength, ucTempRun;
  224. unsigned char ucNoOverrun = 1;
  225. unsigned int uiColor;
  226. unsigned int uiLineCnt = 0;
  227. unsigned int lXS = lX;
  228. lBPP &= 0x0F;
  229. while(lHeight--)
  230. {
  231. //
  232. // Draw this row of image pixels.
  233. //
  234. while(uiLineCnt < lWidth)
  235. {
  236. if(ucNoOverrun) // Read next byte
  237. {
  238. if(lBPP == 8) // RLE 8 bit encoding
  239. {
  240. // Read Run Length
  241. ucRunLength = *pucData++;
  242. // Read Color Pointer
  243. uiColor = *pucData++;
  244. }
  245. else // lBPP = 4; RLE 4 bit encoding
  246. {
  247. // Read Run Length
  248. ucRunLength = (*pucData) >> 4;
  249. // Read Color Pointer
  250. uiColor = (*pucData++) & 0x0F;
  251. }
  252. uiColor = (*(unsigned int *)(pucPalette + uiColor));
  253. }
  254. else
  255. {
  256. //Last line run overran the edge
  257. //Skip color and run length update and clear overrun flag
  258. ucNoOverrun = 1;
  259. ucRunLength = ucTempRun;
  260. }
  261. //After original value, but it still needs to be written once
  262. if((ucRunLength + uiLineCnt) >= lWidth)
  263. {
  264. //Run length runs past current line
  265. //Set left over run length for next line to ucTempRun
  266. ucTempRun = ucRunLength - (lWidth - uiLineCnt);
  267. //Set ucRunLength to finish this line
  268. ucRunLength = (lWidth - uiLineCnt);
  269. //Set line overrun flag
  270. ucNoOverrun = 0;
  271. }
  272. //Draw single pixel
  273. DpyPixelDraw(pContext->pDisplay, lX, lY, uiColor);
  274. lX++;
  275. uiLineCnt++;
  276. while(ucRunLength--)
  277. {
  278. //Draw run of pixels
  279. DpyPixelDraw(pContext->pDisplay, lX, lY, uiColor);
  280. lX++;
  281. uiLineCnt++;
  282. }
  283. }
  284. //End of line reached
  285. uiLineCnt = 0; //Reset Pixel Count
  286. lY++; //Increment Y value
  287. lX = lXS;
  288. }
  289. }
  290. }
  291. //*****************************************************************************
  292. //
  293. // Close the Doxygen group.
  294. //! @}
  295. //
  296. //*****************************************************************************