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

/* --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.
//! @}
//
//*****************************************************************************