kopia lustrzana https://github.com/pimoroni/pimoroni-pico
				
				
				
			
		
			
				
	
	
		
			210 wiersze
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			210 wiersze
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
| //
 | |
| // PNG Decoder
 | |
| //
 | |
| // written by Larry Bank
 | |
| // bitbank@pobox.com
 | |
| // Arduino port started 5/3/2021
 | |
| // Original PNG code written 20+ years ago :)
 | |
| // The goal of this code is to decode PNG images on embedded systems
 | |
| //
 | |
| // Copyright 2021 BitBank Software, Inc. All Rights Reserved.
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //    http://www.apache.org/licenses/LICENSE-2.0
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| //===========================================================================
 | |
| //
 | |
| #include "PNGdec.h"
 | |
| 
 | |
| // forward references
 | |
| PNG_STATIC int PNGInit(PNGIMAGE *pPNG);
 | |
| PNG_STATIC int DecodePNG(PNGIMAGE *pImage, void *pUser, int iOptions);
 | |
| PNG_STATIC uint8_t PNGMakeMask(PNGDRAW *pDraw, uint8_t *pMask, uint8_t ucThreshold);
 | |
| // Include the C code which does the actual work
 | |
| #include "png.inl"
 | |
| 
 | |
| //
 | |
| // Memory initialization
 | |
| //
 | |
| int PNG::openRAM(uint8_t *pData, int iDataSize, PNG_DRAW_CALLBACK *pfnDraw)
 | |
| {
 | |
|     memset(&_png, 0, sizeof(PNGIMAGE));
 | |
|     _png.ucMemType = PNG_MEM_RAM;
 | |
|     _png.pfnRead = readRAM;
 | |
|     _png.pfnSeek = seekMem;
 | |
|     _png.pfnDraw = pfnDraw;
 | |
|     _png.pfnOpen = NULL;
 | |
|     _png.pfnClose = NULL;
 | |
|     _png.PNGFile.iSize = iDataSize;
 | |
|     _png.PNGFile.pData = pData;
 | |
|     return PNGInit(&_png);
 | |
| } /* openRAM() */
 | |
| //
 | |
| // It's necessary to separate out a FLASH version on Harvard architecture machines
 | |
| //
 | |
| int PNG::openFLASH(uint8_t *pData, int iDataSize, PNG_DRAW_CALLBACK *pfnDraw)
 | |
| {
 | |
|     memset(&_png, 0, sizeof(PNGIMAGE));
 | |
|     _png.ucMemType = PNG_MEM_FLASH;
 | |
|     _png.pfnRead = readFLASH;
 | |
|     _png.pfnSeek = seekMem;
 | |
|     _png.pfnDraw = pfnDraw;
 | |
|     _png.pfnOpen = NULL;
 | |
|     _png.pfnClose = NULL;
 | |
|     _png.PNGFile.iSize = iDataSize;
 | |
|     _png.PNGFile.pData = pData;
 | |
|     return PNGInit(&_png);
 | |
| } /* openRAM() */
 | |
| 
 | |
| //
 | |
| // File (SD/MMC) based initialization
 | |
| //
 | |
| int PNG::open(const char *szFilename, PNG_OPEN_CALLBACK *pfnOpen, PNG_CLOSE_CALLBACK *pfnClose, PNG_READ_CALLBACK *pfnRead, PNG_SEEK_CALLBACK *pfnSeek, PNG_DRAW_CALLBACK *pfnDraw)
 | |
| {
 | |
|     memset(&_png, 0, sizeof(PNGIMAGE));
 | |
|     _png.pfnRead = pfnRead;
 | |
|     _png.pfnSeek = pfnSeek;
 | |
|     _png.pfnDraw = pfnDraw;
 | |
|     _png.pfnOpen = pfnOpen;
 | |
|     _png.pfnClose = pfnClose;
 | |
|     _png.PNGFile.fHandle = (*pfnOpen)(szFilename, &_png.PNGFile.iSize);
 | |
|     if (_png.PNGFile.fHandle == NULL)
 | |
|        return 0;
 | |
|     return PNGInit(&_png);
 | |
| 
 | |
| } /* open() */
 | |
| //
 | |
| // return the last error (if any)
 | |
| //
 | |
| int PNG::getLastError()
 | |
| {
 | |
|     return _png.iError;
 | |
| } /* getLastError() */
 | |
| //
 | |
| // Get the width of the image in pixels
 | |
| // can be called after opening the file (before decoding)
 | |
| //
 | |
| int PNG::getWidth()
 | |
| {
 | |
|     return _png.iWidth;
 | |
| } /* getWidth() */
 | |
| //
 | |
| // Get the height of the image in pixels
 | |
| // can be called after opening the file (before decoding)
 | |
| //
 | |
| int PNG::getHeight()
 | |
| {
 | |
|     return _png.iHeight;
 | |
| } /* getHeight() */
 | |
| //
 | |
| // For truecolor and palette images, it's possible to have a single
 | |
| // transparent color defined. This call will return it if defined
 | |
| //
 | |
| uint32_t PNG::getTransparentColor()
 | |
| {
 | |
|     return _png.iTransparent;
 | |
| } /* getTransparentColor() */
 | |
| //
 | |
| // Alpha information can be per pixel, per color or a single color
 | |
| // depending on the PNG pixel type of the image
 | |
| // This call simply tells you if there is alpha for the current pixel type
 | |
| //
 | |
| int PNG::hasAlpha()
 | |
| {
 | |
|     return _png.iHasAlpha;
 | |
| } /* hasAlpha() */
 | |
| //
 | |
| // Returns true or false for the use of Adam7 interlacing
 | |
| // This option is not supported by the decoder, but after opening the image
 | |
| // you can determine if it's set
 | |
| //
 | |
| int PNG::isInterlaced()
 | |
| {
 | |
|     return _png.iInterlaced;
 | |
| } /* isInterlaced() */
 | |
| 
 | |
| //
 | |
| // Returns the number of bits per color stimulus
 | |
| // values of 1,2,4, and 8 are supported
 | |
| //
 | |
| int PNG::getBpp()
 | |
| {
 | |
|     return (int)_png.ucBpp;
 | |
| } /* getBpp() */
 | |
| //
 | |
| // Returns the PNG pixel type (see enum in PNGdec.h)
 | |
| //
 | |
| int PNG::getPixelType()
 | |
| {
 | |
|     return (int)_png.ucPixelType;
 | |
| } /* getPixelType() */
 | |
| //
 | |
| // Set the image buffer to memory managed by the caller
 | |
| // If set, decode() will not use the PNGDRAW callback function
 | |
| // and instead write the image into this buffer in one shot
 | |
| //
 | |
| void PNG::setBuffer(uint8_t *pBuffer)
 | |
| {
 | |
|     _png.pImage = pBuffer;
 | |
| } /* setBuffer() */
 | |
| //
 | |
| // Returns the previously set image buffer or NULL if there is none
 | |
| //
 | |
| uint8_t * PNG::getBuffer()
 | |
| {
 | |
|     return _png.pImage;
 | |
| } /* getBuffer() */
 | |
| //
 | |
| // Returns the size in bytes of the buffer needed to hold the uncompressed image
 | |
| //
 | |
| int PNG::getBufferSize()
 | |
| {
 | |
|     return _png.iHeight * _png.iPitch;
 | |
| } /* getBufferSize() */
 | |
| //
 | |
| // Returns a pointer to the palette
 | |
| // If there is alpha info for the palette, it starts at pPalette[768]
 | |
| //
 | |
| uint8_t * PNG::getPalette()
 | |
| {
 | |
|     return _png.ucPalette;
 | |
| } /* getPalette() */
 | |
| //
 | |
| // Close the file - not needed when decoding from memory
 | |
| //
 | |
| void PNG::close()
 | |
| {
 | |
|     if (_png.pfnClose)
 | |
|         (*_png.pfnClose)(_png.PNGFile.fHandle);
 | |
| } /* close() */
 | |
| 
 | |
| //
 | |
| // Decode the image
 | |
| // returns:
 | |
| // 0 = PNG_SUCCESS
 | |
| // non 0 = PNG enumerated error code
 | |
| //
 | |
| int PNG::decode(void *pUser, int iOptions)
 | |
| {
 | |
|     return DecodePNG(&_png, pUser, iOptions);
 | |
| } /* decode() */
 | |
| //
 | |
| // Convert a line of native pixels (all supported formats) into RGB565
 | |
| // can optionally mix in a background color - set to -1 to disable
 | |
| // Background color is in the form of a uint32_t -> 00BBGGRR (MSB on left)
 | |
| //
 | |
| void PNG::getLineAsRGB565(PNGDRAW *pDraw, uint16_t *pPixels, int iEndianness, uint32_t u32Bkgd)
 | |
| {
 | |
|     PNGRGB565(pDraw, pPixels, iEndianness, u32Bkgd, hasAlpha());
 | |
| } /* getLineAsRGB565() */
 | |
| 
 | |
| uint8_t PNG::getAlphaMask(PNGDRAW *pDraw, uint8_t *pMask, uint8_t ucThreshold)
 | |
| {
 | |
|     return PNGMakeMask(pDraw, pMask, ucThreshold);
 | |
| } /* getAlphaMask() */
 |