/* --COPYRIGHT--,BSD * Copyright (c) 2013, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ #include "grlib.h" //***************************************************************************** // //! \addtogroup image_api //! @{ // //***************************************************************************** //***************************************************************************** // // The buffer that holds the converted palette of the image to be drawn. This // buffer contains the actual data to be written to the LCD after translation. // //***************************************************************************** static unsigned int g_pulConvertedPalette[256]; //***************************************************************************** // //! Converts the bitmap image palette. //! //! \param pContext is a pointer to the drawing context to use. //! \param pBitmap is a pointer to the image. //! //! This function converts the palette of a bitmap image. The image palette is in //! 24 bit RGB form, and this function converts that to a format to be sent to the //! LCD using DpyColorTranslate function. The converted palette is contained in a //! global buffer while the original image palette remains unchanged. //! //! \return is the address of the global buffer containing the converted palette. // //***************************************************************************** unsigned int * GrPaletteConversion(const tContext *pContext, const tImage * pBitmap) { if (pBitmap->NumColors > 256) { return 0; } int i; int NumColors = pBitmap->NumColors; const unsigned long * pulPalette = &pBitmap->pPalette[0]; for (i = 0; i < NumColors; i++) { g_pulConvertedPalette[i] = DpyColorTranslate(pContext->pDisplay, *(pulPalette + i)); } return &g_pulConvertedPalette[0]; } //***************************************************************************** // //! Draws a bitmap image. //! //! \param pContext is a pointer to the drawing context to use. //! \param pucImage is a pointer to the image to draw. //! \param lX is the X coordinate of the upper left corner of the image. //! \param lY is the Y coordinate of the upper left corner of the image. //! //! This function draws a bitmap image. The image may be 1 bit per pixel, 4 //! bits per pixel or 8 bits per pixel (using a palette supplied in the image //! data). It can be uncompressed data, or it can be compressed using //! several different compression types. Compression options are 4-bit run //! length encoding, 8-bit run length encoding, and a custom run length encoding //! variation written for complex 8-bit per pixel images. //! //! \return None. // //***************************************************************************** void GrImageDraw(const tContext *pContext, const tImage *pBitmap, int lX, int lY) { int lBPP, lWidth, lHeight, lX0, lX1, lX2; const unsigned int *pucPalette; const unsigned char * pucImage; // // Check the arguments. // assert(pContext); assert(pBitmap); // // Get the image format from the image data. // lBPP = pBitmap->BPP; // // Get the image width from the image data. // lWidth = pBitmap->XSize; // // Get the image height from the image data. // lHeight = pBitmap->YSize; // // Return without doing anything if the entire image lies outside the // current clipping region. // if((lX > pContext->sClipRegion.sXMax) || ((lX + lWidth - 1) < pContext->sClipRegion.sXMin) || (lY > pContext->sClipRegion.sYMax) || ((lY + lHeight - 1) < pContext->sClipRegion.sYMin)) { return; } // // Get the starting X offset within the image based on the current clipping // region. // if(lX < pContext->sClipRegion.sXMin) { lX0 = pContext->sClipRegion.sXMin - lX; } else { lX0 = 0; } // // Get the ending X offset within the image based on the current clipping // region. // if((lX + lWidth - 1) > pContext->sClipRegion.sXMax) { lX2 = pContext->sClipRegion.sXMax - lX; } else { lX2 = lWidth - 1; } // // Reduce the height of the image, if required, based on the current // clipping region. // if((lY + lHeight - 1) > pContext->sClipRegion.sYMax) { lHeight = pContext->sClipRegion.sYMax - lY + 1; } // // The image palette is in 24 bit R-G-B format. The palette needs // to be translated into the color format accepted by the LCD // and stored in g_pulConvertedPalette[] buffer // pucPalette = GrPaletteConversion(pContext, pBitmap); pucImage = pBitmap->pPixel; // // Check if the image is not compressed. // if(!(lBPP & 0xF0)) { // // The image is not compressed. See if the top portion of the image // lies above the clipping region. // if(lY < pContext->sClipRegion.sYMin) { // // Determine the number of rows that lie above the clipping region. // lX1 = pContext->sClipRegion.sYMin - lY; // // Skip past the data for the rows that lie above the clipping // region. // pucImage += (((lWidth * lBPP) + 7) / 8) * lX1; // // Decrement the image height by the number of skipped rows. // lHeight -= lX1; // // Increment the starting Y coordinate by the number of skipped // rows. // lY += lX1; } while(lHeight--) { // // Draw this row of image pixels. // DpyPixelDrawMultiple(pContext->pDisplay, lX + lX0, lY, lX0 & 7, lX2 - lX0 + 1, lBPP, pucImage + ((lX0 * lBPP) / 8), pucPalette); // // Skip past the data for this row. // pucImage += ((lWidth * lBPP) + 7) / 8; // // Increment the Y coordinate. // lY++; } } else { // // The image is compressed with RLE4 or RLE8 Algorithm // const unsigned char *pucData = pucImage; unsigned char ucRunLength, ucTempRun; unsigned char ucNoOverrun = 1; unsigned int uiColor; unsigned int uiLineCnt = 0; unsigned int lXS = lX; lBPP &= 0x0F; while(lHeight--) { // // Draw this row of image pixels. // while(uiLineCnt < lWidth) { if(ucNoOverrun) // Read next byte { if(lBPP == 8) // RLE 8 bit encoding { // Read Run Length ucRunLength = *pucData++; // Read Color Pointer uiColor = *pucData++; } else // lBPP = 4; RLE 4 bit encoding { // Read Run Length ucRunLength = (*pucData) >> 4; // Read Color Pointer uiColor = (*pucData++) & 0x0F; } uiColor = (*(unsigned int *)(pucPalette + uiColor)); } else { //Last line run overran the edge //Skip color and run length update and clear overrun flag ucNoOverrun = 1; ucRunLength = ucTempRun; } //After original value, but it still needs to be written once if((ucRunLength + uiLineCnt) >= lWidth) { //Run length runs past current line //Set left over run length for next line to ucTempRun ucTempRun = ucRunLength - (lWidth - uiLineCnt); //Set ucRunLength to finish this line ucRunLength = (lWidth - uiLineCnt); //Set line overrun flag ucNoOverrun = 0; } //Draw single pixel DpyPixelDraw(pContext->pDisplay, lX, lY, uiColor); lX++; uiLineCnt++; while(ucRunLength--) { //Draw run of pixels DpyPixelDraw(pContext->pDisplay, lX, lY, uiColor); lX++; uiLineCnt++; } } //End of line reached uiLineCnt = 0; //Reset Pixel Count lY++; //Increment Y value lX = lXS; } } } //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************