📄 jpgwidget.c
字号:
//*****************************************************************************
//
// jpgwidget.c - JPEG image display and button widgets.
//
// Copyright (c) 2009 Luminary Micro, Inc. All rights reserved.
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". 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.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 5228 of the DK-LM3S9B96 Firmware Package.
//
//*****************************************************************************
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "grlib/grlib.h"
#include "grlib/widget.h"
#include "third_party/jpeg/jinclude.h"
#include "third_party/jpeg/jpeglib.h"
#include "third_party/jpeg/jerror.h"
#include "third_party/jpeg/jramdatasrc.h"
#include "extram.h"
#include "jpgwidget.h"
//*****************************************************************************
//
//! \addtogroup jpgwidget_api
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// Decompress the JPEG image whose compressed data is linked to the supplied
// widget.
//
//*****************************************************************************
static long
JPEGDecompressImage(tJPEGWidget *pJPEG)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
boolean bRetcode;
JDIMENSION iNumLines;
JSAMPROW pScanRows[4];
unsigned char *pSrcPixel;
unsigned short *pusPixel;
unsigned long ulImageSize, ulScanBufferHeight, ulColor;
int iPixel, iTotalPixels;
//
// Initialize the deccompression object.
//
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
//
// Set the data source.
//
bRetcode = jpeg_ram_src(&cinfo, (JOCTET *)pJPEG->pucImage,
pJPEG->ulImageLen);
if(!bRetcode)
{
return(1);
}
//
// Read the image header.
//
jpeg_read_header(&cinfo, TRUE);
//
// Tell the JPEG decoder to use the fast integer DCT algorithm. This is
// required since the default is the slow integer version but we have
// disabled this in the current version of third_party/jpeg/jmorecfg.h to
// reduce the image size.
//
cinfo.dct_method = JDCT_IFAST;
//
// Calculate the output image dimensions so that we can allocate
// appropriate buffers.
//
jpeg_calc_output_dimensions(&cinfo);
//
// Allocate a buffer large enough to hold the output image stored at 16
// bits per pixel (the native color format for the display)
//
ulImageSize = (cinfo.output_width * cinfo.output_height * 2);
pJPEG->psJPEGInst->pusImage = (unsigned short *)ExtRAMAlloc(ulImageSize);
pusPixel = pJPEG->psJPEGInst->pusImage;
if(!pJPEG->psJPEGInst->pusImage)
{
return(2);
}
//
// Allocate a buffer that can hold cinfo.rec_outbuf_height lines of pixels
// output from the decompressor. These pixels are described as multiple
// components (typically 3) so we need to take this into account.
//
ulScanBufferHeight = ((cinfo.rec_outbuf_height < 4) ?
cinfo.rec_outbuf_height : 4);
pScanRows[0] = (JSAMPROW)ExtRAMAlloc(cinfo.output_width *
ulScanBufferHeight *
cinfo.output_components);
if(!pScanRows[0])
{
ExtRAMFree(pJPEG->psJPEGInst->pusImage);
pJPEG->psJPEGInst->pusImage = 0;
return(3);
}
//
// Remember the size of the image we are decompressing.
//
pJPEG->psJPEGInst->usHeight = cinfo.output_height;
pJPEG->psJPEGInst->usWidth = cinfo.output_width;
pJPEG->psJPEGInst->sXOffset = 0;
pJPEG->psJPEGInst->sYOffset = 0;
//
// If we allocated more than 1 line, we need to fill in the row pointers
// for each of the other rows in the scanline buffer.
//
for(iNumLines = 1; iNumLines < (int)ulScanBufferHeight; iNumLines++)
{
pScanRows[iNumLines] = pScanRows[iNumLines - 1] +
(cinfo.output_width * cinfo.output_components);
}
//
//
// Start decompression.
//
jpeg_start_decompress(&cinfo);
//
// Decompress the image a piece at a time.
//
while (cinfo.output_scanline < cinfo.output_height)
{
//
// Request some decompressed pixels.
//
iNumLines = jpeg_read_scanlines(&cinfo, pScanRows, ulScanBufferHeight);
//
// How many pixels do we need to process?
//
iTotalPixels = iNumLines * cinfo.output_width;
pSrcPixel = (unsigned char *)pScanRows[0];
for(iPixel = iTotalPixels; iPixel; iPixel--)
{
//
// Read the RGB pixel from the scanline.
//
ulColor = *pSrcPixel++;
ulColor <<= 8;
ulColor |= *pSrcPixel++;
ulColor <<= 8;
ulColor |= *pSrcPixel++;
//
// Convert to 16 bit and store in the output image buffer.
//
*pusPixel = pJPEG->sBase.pDisplay->pfnColorTranslate(
pJPEG->sBase.pDisplay->pvDisplayData,
ulColor);
pusPixel++;
}
}
//
// Destroy the decompression object.
//
jpeg_finish_decompress(&cinfo);
//
// Free the scanline buffer.
//
ExtRAMFree(pScanRows[0]);
//
// Tell the caller everything went well.
//
return(0);
}
//*****************************************************************************
//
// Draws a JPEG widget.
//
// \param pWidget is a pointer to the JPEG widget to be drawn.
//
// This function draws a JPEG widget on the display. This is called in
// response to a \b WIDGET_MSG_PAINT message.
//
// \return None.
//
//*****************************************************************************
static void
JPEGWidgetPaint(tWidget *pWidget)
{
tRectangle sRect;
tJPEGWidget *pJPEG;
tContext sCtx;
unsigned short usWidth, usHeight, usRow;
unsigned short *pusRow;
short sSrcX, sSrcY, sDstX, sDstY;
//
// Check the arguments.
//
ASSERT(pWidget);
//
// Convert the generic widget pointer into a JPEG widget pointer.
//
pJPEG = (tJPEGWidget *)pWidget;
//
// Initialize a drawing context.
//
GrContextInit(&sCtx, pWidget->pDisplay);
//
// Initialize the clipping region based on the extents of this rectangular
// JPEG widget.
//
GrContextClipRegionSet(&sCtx, &(pWidget->sPosition));
//
// Take a copy of the current widget position.
//
sRect=pWidget->sPosition;
//
// See if the JPEG widget outline style is selected.
//
if(pJPEG->ulStyle & JW_STYLE_OUTLINE)
{
unsigned long ulLoop;
GrContextForegroundSet(&sCtx, pJPEG->ulOutlineColor);
//
// Outline the JPEG widget with the outline color.
//
for(ulLoop = 0; ulLoop < (unsigned long)pJPEG->ucBorderWidth; ulLoop++)
{
GrRectDraw(&sCtx, &sRect);
sRect.sXMin++;
sRect.sYMin++;
sRect.sXMax--;
sRect.sYMax--;
}
}
//
// If the fill style is selected fill the widget with the appropriate color.
//
if(pJPEG->ulStyle & JW_STYLE_FILL)
{
//
// Fill the JPEG widget with the fill color.
//
GrContextForegroundSet(&sCtx, pJPEG->ulFillColor);
GrRectFill(&sCtx, &sRect);
}
//
// Does the widget had a decompressed image to draw?
//
if(pJPEG->psJPEGInst->pusImage)
{
//
// What is the size of the image area of the widget?
//
usWidth = (sRect.sXMax - sRect.sXMin) + 1;
usHeight = (sRect.sYMax - sRect.sYMin) + 1;
//
// Is the display window wider than the image?
//
if(usWidth > pJPEG->psJPEGInst->usWidth)
{
//
// The display window is wider so we need to center the image
// within the window.
//
sDstX = sRect.sXMin +
(short)(usWidth - pJPEG->psJPEGInst->usWidth) / 2;
sSrcX = 0;
usWidth = pJPEG->psJPEGInst->usWidth;
}
else
{
//
// The image is wider so we will fill the window (in the x
// direction) and clip the image accordingly.
//
sDstX = sRect.sXMin;
sSrcX = (pJPEG->psJPEGInst->usWidth - usWidth) / 2 -
pJPEG->psJPEGInst->sXOffset;
//
// Ensure we don't wrap the image due to an offset that is too
// large.
//
sSrcX = (sSrcX < 0) ? 0 : sSrcX;
}
//
// Is the image highter than the display window?
//
if(usHeight > pJPEG->psJPEGInst->usHeight)
{
//
// The display window is higher so we need to center the image
// within the window.
//
sDstY = sRect.sYMin +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -