| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- //*****************************************************************************
- //
- // image.c - Routines for drawing bitmap images.
- //
- // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
- // Software License Agreement
- //
- // Texas Instruments (TI) is supplying this software for use solely and
- // exclusively on TI's microcontroller products. The software is owned by
- // TI and/or its suppliers, and is protected under applicable copyright
- // laws. You may not combine this software with "viral" open-source
- // software in order to form a larger program.
- //
- // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
- // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
- // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
- // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
- // DAMAGES, FOR ANY REASON WHATSOEVER.
- //
- // This is part of revision 6288 of the Stellaris Graphics Library.
- //
- //*****************************************************************************
- #include "debug.h"
- #include "grlib.h"
- //*****************************************************************************
- //
- //! \addtogroup primitives_api
- //! @{
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- // The buffer that holds the dictionary used by the Lempel-Ziv-Storer-Szymanski
- // compression algorithm. This is simply the last 32 bytes decoded from the
- // stream, and is initially filled with zeros.
- //
- //*****************************************************************************
- static unsigned char g_pucDictionary[32];
- //*****************************************************************************
- //
- //! 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
- //! (using the foreground and background color from the drawing context), 4
- //! bits per pixel (using a palette supplied in the image data), or 8 bits per
- //! pixel (using a palette supplied in the image data). It can be uncompressed
- //! data, or it can be compressed using the Lempel-Ziv-Storer-Szymanski
- //! algorithm (as published in the Journal of the ACM, 29(4):928-951, October
- //! 1982).
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- GrImageDraw(const tContext *pContext, const unsigned char *pucImage, int lX,
- int lY)
- {
- unsigned int ulByte, ulBits, ulMatch, ulSize, ulIdx, ulCount, ulNum;
- int lBPP, lWidth, lHeight, lX0, lX1, lX2;
- const unsigned char *pucPalette = 0;
- unsigned char pucBWPalette[8];
- //
- // Check the arguments.
- //
- ASSERT(pContext);
- ASSERT(pucImage);
- //
- // Get the image format from the image data.
- //
- lBPP = *pucImage++;
- #ifdef SUPPORT_UNALIGNED
- //
- // Get the image width from the image data.
- //
- lWidth = *(unsigned short *)pucImage;
- pucImage += 2;
- //
- // Get the image height from the image data.
- //
- lHeight = *(unsigned short *)pucImage;
- pucImage += 2;
- #else
- // Get the image width from the image data.
- lWidth = *pucImage++;
- lWidth = lWidth | ((*pucImage++) << 8);
- // Get the image height from the image data.
- lHeight = *pucImage++;
- lHeight = lHeight | ((*pucImage++) << 8);
- #endif
- //
- // 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;
- }
- //
- // Determine the color palette for the image based on the image format.
- //
- if((lBPP & 0x7f) == IMAGE_FMT_1BPP_UNCOMP)
- {
- //
- // Construct a local "black & white" palette based on the foreground
- // and background colors of the drawing context.
- //
- *(unsigned int *)pucBWPalette = pContext->ulBackground;
- *(unsigned int *)(pucBWPalette + 4) = pContext->ulForeground;
- //
- // Set the palette pointer to the local "black & white" palette.
- //
- pucPalette = pucBWPalette;
- }
- else if ( ((lBPP & 0x7f) == IMAGE_FMT_4BPP_UNCOMP) ||
- ((lBPP & 0x7f) == IMAGE_FMT_8BPP_UNCOMP))
- {
- //
- // For 4 and 8 BPP images, the palette is contained at the start of the
- // image data.
- //
- pucPalette = pucImage + 1;
- pucImage += (pucImage[0] * 3) + 4;
- }
- //
- // See if the image is compressed.
- //
- if(!(lBPP & 0x80))
- {
- //
- // 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;
- }
- //
- // Loop while there are more rows to draw.
- //
- 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. Clear the compressed flag in the format
- // specifier so that the bits per pixel remains.
- //
- lBPP &= 0x7f;
- //
- // Reset the dictionary used to uncompress the image.
- //
- for(ulBits = 0; ulBits < sizeof(g_pucDictionary); ulBits += 4)
- {
- *(unsigned int *)(g_pucDictionary + ulBits) = 0;
- }
- //
- // Determine the number of bytes of data to decompress.
- //
- ulCount = (((lWidth * lBPP) + 7) / 8) * lHeight;
- //
- // Initialize the pointer into the dictionary.
- //
- ulIdx = 0;
- //
- // Start off with no encoding byte.
- //
- ulBits = 0;
- ulByte = 0;
- //
- // Start from the upper left corner of the image.
- //
- lX1 = 0;
- //
- // Loop while there are more rows or more data in the image.
- //
- while(lHeight && ulCount)
- {
- //
- // See if an encoding byte needs to be read.
- //
- if(ulBits == 0)
- {
- //
- // Read the encoding byte, which indicates if each of the
- // following eight bytes are encoded or literal.
- //
- ulByte = *pucImage++;
- ulBits = 8;
- }
- //
- // See if the next byte is encoded or literal.
- //
- if(ulByte & (1 << (ulBits - 1)))
- {
- //
- // This byte is encoded, so extract the location and size of
- // the encoded data within the dictionary.
- //
- ulMatch = *pucImage >> 3;
- ulSize = (*pucImage++ & 7) + 2;
- //
- // Decrement the count of bytes to decode by the number of
- // copied bytes.
- //
- ulCount -= ulSize;
- }
- else
- {
- //
- // This byte is a literal, so copy it into the dictionary.
- //
- g_pucDictionary[ulIdx++] = *pucImage++;
- //
- // Decrement the count of bytes to decode.
- //
- ulCount--;
- //
- // Clear any previous encoded data information.
- //
- ulMatch = 0;
- ulSize = 0;
- }
- //
- // Loop while there are bytes to copy for the encoded data, or
- // once for literal data.
- //
- while(ulSize || !(ulByte & (1 << (ulBits - 1))))
- {
- //
- // Set the encoded data bit for this data so that this loop
- // will only be executed once for literal data.
- //
- ulByte |= 1 << (ulBits - 1);
- //
- // Loop while there is more encoded data to copy and there is
- // additional space in the dictionary (before the buffer
- // wraps).
- //
- while(ulSize && (ulIdx != sizeof(g_pucDictionary)))
- {
- //
- // Copy this byte.
- //
- g_pucDictionary[ulIdx] =
- g_pucDictionary[(ulIdx + ulMatch) %
- sizeof(g_pucDictionary)];
- //
- // Increment the dictionary pointer.
- //
- ulIdx++;
- //
- // Decrement the encoded data size.
- //
- ulSize--;
- }
- //
- // See if the dictionary pointer is about to wrap, or if there
- // is no more data to decompress.
- //
- if((ulIdx == sizeof(g_pucDictionary)) || !ulCount)
- {
- //
- // Loop through the data in the dictionary buffer.
- //
- for(ulIdx = 0;
- (ulIdx < sizeof(g_pucDictionary)) && lHeight; )
- {
- //
- // Compute the number of pixels that remain in the
- // dictionary buffer.
- //
- ulNum = ((sizeof(g_pucDictionary) - ulIdx) * 8) / lBPP;
- //
- // See if any of the pixels in the dictionary buffer
- // are within the clipping region.
- //
- if((lY >= pContext->sClipRegion.sYMin) &&
- ((lX1 + ulNum) >= lX0) && (lX1 <= lX2))
- {
- //
- // Skip some pixels at the start of the scan line
- // if required to stay within the clipping region.
- //
- if(lX1 < lX0)
- {
- ulIdx += ((lX0 - lX1) * lBPP) / 8;
- lX1 = lX0;
- }
- //
- // Shorten the scan line if required to stay within
- // the clipping region.
- //
- if(ulNum > (lX2 - lX1 + 1))
- {
- ulNum = lX2 - lX1 + 1;
- }
- //
- // Draw this row of image pixels.
- //
- DpyPixelDrawMultiple(pContext->pDisplay, lX + lX1,
- lY, lX1 & 7, ulNum, lBPP,
- g_pucDictionary + ulIdx,
- pucPalette);
- }
- //
- // Move the X coordinate back to the start of the first
- // data byte in this portion of the dictionary buffer.
- //
- lX1 = ((lX1 * lBPP) & ~7) / lBPP;
- //
- // See if the remainder of this scan line resides
- // within the dictionary buffer.
- //
- if(((((lWidth - lX1) * lBPP) + 7) / 8) >
- (sizeof(g_pucDictionary) - ulIdx))
- {
- //
- // There is more to this scan line than is in the
- // dictionary buffer at this point, so move the
- // X coordinate by by the number of pixels in the
- // dictionary buffer.
- //
- lX1 += (((sizeof(g_pucDictionary) - ulIdx) * 8) /
- lBPP);
- //
- // The entire dictionary buffer has been scanned.
- //
- ulIdx = sizeof(g_pucDictionary);
- }
- else
- {
- //
- // The remainder of this scan line resides in the
- // dictionary buffer, so skip past it.
- //
- ulIdx += (((lWidth - lX1) * lBPP) + 7) / 8;
- //
- // Move to the start of the next scan line.
- //
- lX1 = 0;
- lY++;
- //
- // There is one less scan line to process.
- //
- lHeight--;
- }
- }
- //
- // Start over from the beginning of the dictionary buffer.
- //
- ulIdx = 0;
- }
- }
- //
- // Advance to the next bit in the encoding byte.
- //
- ulBits--;
- }
- }
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|