From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/plugins/png2dib/png2dib.c | 411 +++++++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 miranda-wine/plugins/png2dib/png2dib.c (limited to 'miranda-wine/plugins/png2dib/png2dib.c') diff --git a/miranda-wine/plugins/png2dib/png2dib.c b/miranda-wine/plugins/png2dib/png2dib.c new file mode 100644 index 0000000..5e531ef --- /dev/null +++ b/miranda-wine/plugins/png2dib/png2dib.c @@ -0,0 +1,411 @@ +/* +Plugin of Miranda IM for reading/writing PNG images. +Copyright (c) 2004-6 George Hazan (ghazan@postman.ru) + +Portions of this code are gotten from the libpng codebase. +Copyright 2000, Willem van Schaik. For conditions of distribution and +use, see the copyright/license/disclaimer notice in png.h + +Miranda IM: the free icq client for MS Windows +Copyright (C) 2000-2002 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +File name : $Source: /cvsroot/miranda/miranda/plugins/png2dib/png2dib.c,v $ +Revision : $Revision: 3502 $ +Last change on : $Date: 2006-08-16 01:21:49 +0400 (Срд, 16 Авг 2006) $ +Last change by : $Author: ghazan $ + +*/ + +#include +#include +#include +#include +#include + +#include "libpng/png.h" + +#include "newpluginapi.h" +#include "version.h" +#include "m_png.h" + +DWORD __declspec(dllexport) getver( void ) +{ + return __VERSION_DWORD; +} + +// PNG image handler functions + +typedef struct { + char* mBuffer; + size_t mBufSize; + size_t mBufPtr; +} + HMemBufInfo; + +static void png_read_data( png_structp png_ptr, png_bytep data, png_size_t length ) +{ + HMemBufInfo* io = ( HMemBufInfo* )png_ptr->io_ptr; + if ( length + io->mBufPtr > io->mBufSize ) + length = io->mBufSize - io->mBufPtr; + + if ( length > 0 ) { + memcpy( data, io->mBuffer + io->mBufPtr, length ); + io->mBufPtr += length; + } + else png_error(png_ptr, "Read Error"); +} + +static void png_write_data( png_structp png_ptr, png_bytep data, png_size_t length ) +{ + HMemBufInfo* io = ( HMemBufInfo* )png_ptr->io_ptr; + if ( io->mBuffer != NULL ) + memcpy( io->mBuffer + io->mBufPtr, data, length ); + + io->mBufPtr += length; +} + +static void png_flush( png_structp png_ptr ) +{ +} + +/* + * Converting a png image into a bitmap + */ + +BOOL __declspec(dllexport) mempng2dib( + BYTE* pSource, + DWORD cbSourceSize, + BITMAPINFOHEADER** ppDibData ) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + HMemBufInfo sBuffer = { pSource, cbSourceSize, 8 }; + + BOOL bResult = FALSE; + int iWidth; + int iHeight; + png_color pBkgColor; + int iBitDepth; + int iColorType; + double dGamma; + png_color_16* pBackground; + png_uint_32 ulChannels; + png_uint_32 ulRowBytes; + png_byte* pbImageData; + png_byte** ppbRowPointers = NULL; + int i; + int wDIRowBytes; + BYTE* pImageData; + + *ppDibData = NULL; + + if ( pSource == NULL || cbSourceSize == 0 ) + return FALSE; + + if ( !png_check_sig( pSource, 8 )) + return FALSE; + + // create the two png(-info) structures + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); + if (!png_ptr) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + if ( !info_ptr ) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return FALSE; + } + + // initialize the png structure + png_set_read_fn(png_ptr, (png_voidp)&sBuffer, png_read_data); + png_set_sig_bytes(png_ptr, 8); + + // read all PNG info up to image data + png_read_info(png_ptr, info_ptr); + + // get width, height, bit-depth and color-type + + png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); + + // expand images of all color-type and bit-depth to 3x8 bit RGB images + // let the library process things like alpha, transparency, background + + if ( iBitDepth == 16 ) + png_set_strip_16( png_ptr ); + if ( iColorType == PNG_COLOR_TYPE_PALETTE ) + png_set_expand( png_ptr ); + if ( iBitDepth < 8 ) + png_set_expand( png_ptr ); + if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS )) + png_set_expand( png_ptr ); + if ( iColorType == PNG_COLOR_TYPE_GRAY || iColorType == PNG_COLOR_TYPE_GRAY_ALPHA ) + png_set_gray_to_rgb( png_ptr ); + + // set the background color to draw transparent and alpha images over. + if (png_get_bKGD( png_ptr, info_ptr, &pBackground )) { + png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + pBkgColor.red = (byte) pBackground->red; + pBkgColor.green = (byte) pBackground->green; + pBkgColor.blue = (byte) pBackground->blue; + } + + // if required set gamma conversion + if ( png_get_gAMA( png_ptr, info_ptr, &dGamma )) + png_set_gamma( png_ptr, (double) 2.2, dGamma ); + + // after the transformations have been registered update info_ptr data + png_read_update_info(png_ptr, info_ptr); + + // get again width, height and the new bit-depth and color-type + png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); + + // row_bytes is the width x number of channels + ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); + ulChannels = png_get_channels(png_ptr, info_ptr); + wDIRowBytes = (WORD) (( ulChannels * iWidth + 3L) >> 2) << 2; + + // now we can allocate memory to store the image + { DWORD cbMemSize = sizeof( BITMAPINFOHEADER ); + cbMemSize += wDIRowBytes * iHeight; + if (( pbImageData = ( png_byte* )GlobalAlloc( LPTR, cbMemSize )) == NULL ) { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } } + + // initialize the dib-structure + { BITMAPINFOHEADER* pbmih = ( BITMAPINFOHEADER* )pbImageData; + *ppDibData = pbmih; + + pbmih->biSize = sizeof( BITMAPINFOHEADER ); + pbmih->biWidth = iWidth; + pbmih->biHeight = iHeight; + pbmih->biPlanes = 1; + pbmih->biBitCount = ulChannels * 8; + pbmih->biCompression = 0; + pbmih->biSizeImage = iWidth * iHeight * ulChannels; + + pbImageData += sizeof( BITMAPINFOHEADER ); + } + + pImageData = (BYTE*)malloc( ulRowBytes * iHeight ); + if ( pImageData == NULL ) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return FALSE; + } + + // and allocate memory for an array of row-pointers + ppbRowPointers = ( png_bytepp )alloca( iHeight * sizeof( png_bytep )); + + // set the individual row-pointers to point at the correct offsets + for ( i = 0; i < iHeight; i++ ) + ppbRowPointers[i] = ( png_bytep )&pImageData[ i*ulRowBytes ]; + + // now we can go ahead and just read the whole image + png_read_image( png_ptr, ppbRowPointers ); + png_read_end(png_ptr, NULL); + + // repack bytes to fill the bitmap + for ( i = iHeight-1; i >= 0; i-- ) + { + int j; + png_byte a; + png_bytep s = ppbRowPointers[i]; + BYTE* dest = pbImageData; pbImageData += wDIRowBytes; + + for ( j = 0; j < iWidth; j++ ) { + png_byte r = *s++; + png_byte g = *s++; + png_byte b = *s++; + if ( ulChannels == 4 ) + a = *s++; + + *dest++ = b; + *dest++ = g; + *dest++ = r; + if ( ulChannels == 4 ) + *dest++ = a; + } } + + free( pImageData ); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return TRUE; +} + +/* + * Converting a bitmap into a png image + */ + +BOOL __declspec(dllexport) dib2mempng( BITMAPINFO* pbmi, png_byte* pDiData, BYTE* pResult, long* pResultLen ) +{ + int ciBitDepth = 8; + int ciChannels = pbmi->bmiHeader.biBitCount / 8; + + png_uint_32 ulSrcRowBytes, ulDstRowBytes; + int i; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_bytepp ppbRowPointers; + png_bytep pTempBuffer; + + HMemBufInfo sBuffer = { pResult, 0, 0 }; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); + if (!png_ptr) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + return FALSE; + } + + // initialize the png structure + png_set_write_fn(png_ptr, (png_voidp)&sBuffer, png_write_data, png_flush); + + png_set_IHDR(png_ptr, info_ptr, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight, ciBitDepth, + PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + // write the file header information + png_write_info(png_ptr, info_ptr); + + // swap the BGR pixels in the DiData structure to RGB + png_set_bgr(png_ptr); + + // row_bytes is the width x number of channels + ulSrcRowBytes = ((( pbmi->bmiHeader.biWidth * ciChannels + 3 ) >> 2 ) << 2 ); + ulDstRowBytes = ((( pbmi->bmiHeader.biWidth * 3 + 3 ) >> 2 ) << 2 ); + + ppbRowPointers = (png_bytepp)alloca( pbmi->bmiHeader.biHeight * sizeof(png_bytep)); + + pTempBuffer = ( png_bytep )malloc( pbmi->bmiHeader.biHeight * ulDstRowBytes ); + if ( pTempBuffer != NULL ) { + png_bytep pDest = pTempBuffer; + for ( i = pbmi->bmiHeader.biHeight-1; i >= 0; i--) { + BYTE *s, *d; + int j; + s = pDiData; pDiData += ulSrcRowBytes; + d = ppbRowPointers[i] = pDest; pDest += ulDstRowBytes; + + if ( ciChannels >= 3 ) { + for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { + png_byte b = *s++; + png_byte g = *s++; + png_byte r = *s++; + png_byte a = 0; + + if ( ciChannels == 4 ) + a = *s++; + + *d++ = b; + *d++ = g; + *d++ = r; + } } + else { + for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { + DWORD point; + if ( ciChannels == 1 ) { + *d++ = ( BYTE )( point & 0x03 ) << 6; + *d++ = ( BYTE )(( point & 0x0C ) >> 2 ) << 6; + *d++ = ( BYTE )(( point & 0x30 ) >> 4 ) << 6; + point = *s++; + } + else { + point = *( WORD* )s; + s += sizeof( WORD ); + *d++ = ( BYTE )(( point & 0x001F ) << 3 ); + *d++ = ( BYTE )((( point & 0x07e0 ) >> 6 ) << 3 ); + *d++ = ( BYTE )((( point & 0xF800 ) >> 11 ) << 3 ); + } } } } + + png_write_image (png_ptr, ppbRowPointers); + png_write_end(png_ptr, info_ptr); + + if ( pResultLen != NULL ) + *pResultLen = sBuffer.mBufPtr; + + free( pTempBuffer ); + } + + png_destroy_write_struct(&png_ptr, &info_ptr ); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Standard Miranda structures & functions + +HINSTANCE hInst = NULL; +PLUGINLINK *pluginLink; + +static HANDLE hDib2mempng = NULL; +static HANDLE hMempng2Dib = NULL; + +PLUGININFO pluginInfo = { + sizeof( PLUGININFO ), + "PNG images processor", + __VERSION_DWORD, + "png2dib plugin for Miranda IM ( "__DATE__" )", + "George Hazan", + "ghazan@miranda-im.org", + "(c) 2004-06 George Hazan", + "http://addons.miranda-im.org/details.php?action=viewfile&id=1420", + 0, + 0 +}; + +__declspec( dllexport ) PLUGININFO* MirandaPluginInfo( DWORD mirandaVersion ) +{ + if ( mirandaVersion < PLUGIN_MAKE_VERSION( 0,4,3,0 )) { + MessageBox( NULL, "The png2dib plugin cannot be loaded. It requires Miranda IM 0.5 or later.", "png2dib Plugin", MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST ); + return NULL; + } + + return &pluginInfo; +} + +/////////////////////////////////////////////////////////////////////////////// +// Load - initializes the plugin instance + +static int serviceDib2Png( WPARAM wParam, LPARAM lParam ) +{ + DIB2PNG* param = ( DIB2PNG* )lParam; + return dib2mempng( param->pbmi, param->pDiData, param->pResult, param->pResultLen ); +} + +static int servicePng2Dib( WPARAM wParam, LPARAM lParam ) +{ + PNG2DIB* param = ( PNG2DIB* )lParam; + return mempng2dib( param->pSource, param->cbSourceSize, param->pResult ); +} + +int __declspec( dllexport ) Load( PLUGINLINK *link ) +{ + pluginLink = link; + + hDib2mempng = CreateServiceFunction( MS_DIB2PNG, serviceDib2Png ); + hMempng2Dib = CreateServiceFunction( MS_PNG2DIB, servicePng2Dib ); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// Unload - destroys the plugin instance + +int __declspec( dllexport ) Unload( void ) +{ + DestroyServiceFunction( hDib2mempng ); + DestroyServiceFunction( hMempng2Dib ); + return 0; +} -- cgit v1.2.3