| /* ************************************************************************** */ |
| /* * For conditions of distribution and use, * */ |
| /* * see copyright notice in libmng.h * */ |
| /* ************************************************************************** */ |
| /* * * */ |
| /* * project : libmng * */ |
| /* * file : libmng_pixels.c copyright (c) 2000-2005 G.Juyn * */ |
| /* * version : 1.0.10 * */ |
| /* * * */ |
| /* * purpose : Pixel-row management routines (implementation) * */ |
| /* * * */ |
| /* * author : G.Juyn * */ |
| /* * * */ |
| /* * comment : implementation of the pixel-row management routines * */ |
| /* * * */ |
| /* * the dual alpha-composing for RGBA/BGRA/etc output-canvas' * */ |
| /* * is based on the Note on Compositing chapter of the * */ |
| /* * DOH-3 draft, noted to me by Adam M. Costello * */ |
| /* * * */ |
| /* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */ |
| /* * - changed strict-ANSI stuff * */ |
| /* * 0.5.1 - 05/11/2000 - G.Juyn * */ |
| /* * - added callback error-reporting support * */ |
| /* * 0.5.1 - 05/12/2000 - G.Juyn * */ |
| /* * - changed trace to macro for callback error-reporting * */ |
| /* * * */ |
| /* * 0.5.2 - 05/22/2000 - G.Juyn * */ |
| /* * - added JNG support * */ |
| /* * 0.5.2 - 05/30/2000 - G.Juyn * */ |
| /* * - fixed minor bugs 16-bit pixel-handling * */ |
| /* * - added delta-image row-processing routines * */ |
| /* * 0.5.2 - 06/02/2000 - G.Juyn * */ |
| /* * - fixed endian support (hopefully) * */ |
| /* * 0.5.2 - 06/03/2000 - G.Juyn * */ |
| /* * - fixed makeup for Linux gcc compile * */ |
| /* * 0.5.2 - 06/05/2000 - G.Juyn * */ |
| /* * - implemented app bkgd restore routines * */ |
| /* * - implemented RGBA8, ARGB8, BGRA8 & ABGR8 display routines * */ |
| /* * - added support for RGB8_A8 canvasstyle * */ |
| /* * 0.5.2 - 06/09/2000 - G.Juyn * */ |
| /* * - fixed alpha-handling for alpha canvasstyles * */ |
| /* * * */ |
| /* * 0.5.3 - 06/16/2000 - G.Juyn * */ |
| /* * - changed progressive-display processing * */ |
| /* * 0.5.3 - 06/17/2000 - G.Juyn * */ |
| /* * - changed to support delta-images * */ |
| /* * - optimized some store_xxx routines * */ |
| /* * 0.5.3 - 06/20/2000 - G.Juyn * */ |
| /* * - fixed nasty bug with embedded PNG after delta-image * */ |
| /* * 0.5.3 - 06/24/2000 - G.Juyn * */ |
| /* * - fixed problem with 16-bit GA format * */ |
| /* * 0.5.3 - 06/25/2000 - G.Juyn * */ |
| /* * - fixed problem with cheap transparency for 4-bit gray * */ |
| /* * - fixed display_xxxx routines for interlaced images * */ |
| /* * 0.5.3 - 06/28/2000 - G.Juyn * */ |
| /* * - fixed compiler-warning for non-initialized iB variable * */ |
| /* * * */ |
| /* * 0.9.1 - 07/05/2000 - G.Juyn * */ |
| /* * - fixed mandatory BACK color to be opaque * */ |
| /* * * */ |
| /* * 0.9.2 - 07/31/2000 - G.Juyn * */ |
| /* * - B110547 - fixed bug in interlace code * */ |
| /* * 0.9.2 - 08/05/2000 - G.Juyn * */ |
| /* * - changed file-prefixes * */ |
| /* * * */ |
| /* * 0.9.3 - 08/20/2000 - G.Juyn * */ |
| /* * - fixed app-supplied background restore * */ |
| /* * 0.9.3 - 08/26/2000 - G.Juyn * */ |
| /* * - added MAGN chunk * */ |
| /* * 0.9.3 - 09/07/2000 - G.Juyn * */ |
| /* * - added support for new filter_types * */ |
| /* * 0.9.3 - 09/30/2000 - G.Juyn * */ |
| /* * - fixed MAGN rounding errors (thanks Matthias!) * */ |
| /* * 0.9.3 - 10/10/2000 - G.Juyn * */ |
| /* * - fixed alpha-blending for RGBA canvasstyle * */ |
| /* * 0.9.3 - 10/11/2000 - G.Juyn * */ |
| /* * - fixed alpha-blending for other alpha-canvasstyles * */ |
| /* * 0.9.3 - 10/16/2000 - G.Juyn * */ |
| /* * - added optional support for bKGD for PNG images * */ |
| /* * - added support for JDAA * */ |
| /* * 0.9.3 - 10/17/2000 - G.Juyn * */ |
| /* * - fixed support for bKGD * */ |
| /* * 0.9.3 - 10/19/2000 - G.Juyn * */ |
| /* * - implemented delayed delta-processing * */ |
| /* * 0.9.3 - 10/28/2000 - G.Juyn * */ |
| /* * - fixed tRNS processing for gray-image < 8-bits * */ |
| /* * * */ |
| /* * 0.9.4 - 12/16/2000 - G.Juyn * */ |
| /* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */ |
| /* * 0.9.4 - 1/18/2001 - G.Juyn * */ |
| /* * - removed "old" MAGN methods 3 & 4 * */ |
| /* * - added "new" MAGN methods 3, 4 & 5 * */ |
| /* * - removed test filter-methods 1 & 65 * */ |
| /* * * */ |
| /* * 1.0.1 - 04/21/2001 - G.Juyn (code by G.Kelly) * */ |
| /* * - added BGRA8 canvas with premultiplied alpha * */ |
| /* * 1.0.1 - 04/25/2001 - G.Juyn * */ |
| /* * - moved mng_clear_cms to libmng_cms * */ |
| /* * * */ |
| /* * 1.0.2 - 06/25/2001 - G.Juyn * */ |
| /* * - added option to turn off progressive refresh * */ |
| /* * * */ |
| /* * 1.0.4 - 11/04/2001 - G.Juyn * */ |
| /* * - fixed possible compile-problem in cleanup_rowproc * */ |
| /* * 1.0.4 - 06/22/2002 - G.Juyn * */ |
| /* * - B558212 - off by one error * */ |
| /* * - MNG subimage alpha composite wrong for rgba8 images * */ |
| /* * * */ |
| /* * 1.0.5 - 08/07/2002 - G.Juyn * */ |
| /* * - added test-option for PNG filter method 193 (=no filter) * */ |
| /* * 1.0.5 - 08/15/2002 - G.Juyn * */ |
| /* * - completed PROM support * */ |
| /* * - completed delta-image support * */ |
| /* * 1.0.5 - 08/16/2002 - G.Juyn * */ |
| /* * - completed MAGN support (16-bit functions) * */ |
| /* * 1.0.5 - 08/19/2002 - G.Juyn * */ |
| /* * - B597134 - libmng pollutes the linker namespace * */ |
| /* * 1.0.5 - 09/19/2002 - G.Juyn * */ |
| /* * - optimized restore-background for bKGD cases * */ |
| /* * 1.0.5 - 09/20/2002 - G.Juyn * */ |
| /* * - finished support for BACK image & tiling * */ |
| /* * 1.0.5 - 09/22/2002 - G.Juyn * */ |
| /* * - added bgrx8 canvas (filler byte) * */ |
| /* * 1.0.5 - 09/23/2002 - G.Juyn * */ |
| /* * - added compose over/under routines for PAST processing * */ |
| /* * - added flip & tile routines for PAST processing * */ |
| /* * * */ |
| /* * 1.0.6 - 03/09/2003 - G.Juyn * */ |
| /* * - hiding 12-bit JPEG stuff * */ |
| /* * 1.0.6 - 05/11/2003 - Glenn RP * */ |
| /* * - added size-optimization COMPOSE routine usage * */ |
| /* * 1.0.6 - 05/11/2003 - G. Juyn * */ |
| /* * - added conditionals around canvas update routines * */ |
| /* * 1.0.6 - 05/25/2003 - Glenn RP * */ |
| /* * - added size-optimization DIV255B8 routine usage * */ |
| /* * 1.0.6 - 06/09/2003 - G. R-P * */ |
| /* * - added conditionals around 8-bit magn routines * */ |
| /* * 1.0.6 - 07/07/2003 - G. R-P * */ |
| /* * - removed conditionals around 8-bit magn routines * */ |
| /* * - added MNG_NO_16BIT_SUPPORT and MNG_NO_DELTA_PNG * */ |
| /* * conditionals * */ |
| /* * - reversed many loops to use decrementing counter * */ |
| /* * - combined init functions * */ |
| /* * - converted some switches to array references * */ |
| /* * 1.0.6 - 07/29/2003 - G.Juyn * */ |
| /* * - fixed duplicate for-loop * */ |
| /* * 1.0.6 - 07/29/2003 - G.R-P * */ |
| /* * - added SKIPCHUNK conditionals around PAST chunk support * */ |
| /* * - fixed "FOOTPRINT_COMPOSEIV" typo (now "FOOTPRINT_DIV") * */ |
| /* * 1.0.6 - 08/17/2003 - G.R-P * */ |
| /* * - added more conditionals around "promote" functions * */ |
| /* * * */ |
| /* * 1.0.7 - 11/27/2003 - R.A * */ |
| /* * - added CANVAS_RGB565 and CANVAS_BGR565 * */ |
| /* * 1.0.7 - 12/06/2003 - R.A * */ |
| /* * - added CANVAS_RGBA565 and CANVAS_BGRA565 * */ |
| /* * 1.0.7 - 01/25/2004 - J.S * */ |
| /* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */ |
| /* * 1.0.7 - 03/08/2004 - G.R-P * */ |
| /* * - added more conditionals around 16-bit-supporting code * */ |
| /* * 1.0.7 - 03/09/2004 - G.Juyn * */ |
| /* * - fixed bug in promote_g8_g8 with 16bit support off * */ |
| /* * 1.0.7 - 03/09/2004 - G.R-P * */ |
| /* * - more optimizations with 16bit support off * */ |
| /* * 1.0.7 - 03/10/2004 - G.Juyn * */ |
| /* * - fixed some warnings for 16bit optimizations * */ |
| /* * 1.0.7 - 03/21/2004 - G.Juyn * */ |
| /* * - fixed some 64-bit platform compiler warnings * */ |
| /* * * */ |
| /* * 1.0.8 - 06/20/2004 - G.Juyn * */ |
| /* * - some speed optimizations (thanks to John Stiles) * */ |
| /* * 1.0.8 - 08/01/2004 - G.Juyn * */ |
| /* * - added support for 3+byte pixelsize for JPEG's * */ |
| /* * * */ |
| /* * 1.0.9 - 10/10/2004 - G.R-P. * */ |
| /* * - added MNG_NO_1_2_4BIT_SUPPORT * */ |
| /* * 1.0.9 - 10/14/2004 - G.Juyn * */ |
| /* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */ |
| /* * 1.0.9 - 12/05/2004 - G.Juyn * */ |
| /* * - added LITTLEENDIAN/BIGENDIAN fixtures (thanks J.Stiles) * */ |
| /* * - fixed MNG_NO_1_2_4BIT_SUPPORT for TBBN1G04.PNG * */ |
| /* * 1.0.9 - 12/31/2004 - G.R-P. * */ |
| /* * - fixed warnings about C++ style (//) comments * */ |
| /* * * */ |
| /* * 1.0.10 - 07/06/2005 - G.R-P. * */ |
| /* * - added MORE MNG_NO_1_2_4BIT_SUPPORT * */ |
| /* * 1.0.10 - 10/06/2005 - G.R-P. * */ |
| /* * - alloc more memory for MNG_NO_1_2_4BIT_SUPPORT * */ |
| /* * 1.0.10 - 12/07/2005 - G.R-P. * */ |
| /* * - optimized footprint of 16bit support * */ |
| /* * 1.0.10 - 03/07/2006 - (thanks to W. Manthey) * */ |
| /* * - added CANVAS_RGB555 and CANVAS_BGR555 * */ |
| /* * * */ |
| /* ************************************************************************** */ |
| |
| #include "libmng.h" |
| #include "libmng_data.h" |
| #include "libmng_error.h" |
| #include "libmng_trace.h" |
| #ifdef __BORLANDC__ |
| #pragma hdrstop |
| #endif |
| #include "libmng_objects.h" |
| #include "libmng_object_prc.h" |
| #include "libmng_memory.h" |
| #include "libmng_cms.h" |
| #include "libmng_filter.h" |
| #include "libmng_pixels.h" |
| |
| #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI) |
| #pragma option -A /* force ANSI-C */ |
| #endif |
| |
| /* ************************************************************************** */ |
| |
| #ifdef MNG_INCLUDE_DISPLAY_PROCS |
| |
| /* TODO: magnification & canvas-positioning/-clipping */ |
| |
| /* TODO: major optimization of pixel-loops by using assembler (?) */ |
| |
| /* ************************************************************************** */ |
| /* * * */ |
| /* * Interlace tables * */ |
| /* * * */ |
| /* ************************************************************************** */ |
| |
| MNG_LOCAL mng_uint32 const interlace_row [7] = { 0, 0, 4, 0, 2, 0, 1 }; |
| MNG_LOCAL mng_uint32 const interlace_rowskip [7] = { 8, 8, 8, 4, 4, 2, 2 }; |
| MNG_LOCAL mng_uint32 const interlace_col [7] = { 0, 4, 0, 2, 0, 1, 0 }; |
| MNG_LOCAL mng_uint32 const interlace_colskip [7] = { 8, 8, 4, 4, 2, 2, 1 }; |
| MNG_LOCAL mng_uint32 const interlace_roundoff [7] = { 7, 7, 3, 3, 1, 1, 0 }; |
| MNG_LOCAL mng_uint32 const interlace_divider [7] = { 3, 3, 2, 2, 1, 1, 0 }; |
| |
| /* ************************************************************************** */ |
| /* * * */ |
| /* * Alpha composing macros * */ |
| /* * the code below is slightly modified from the libpng package * */ |
| /* * the original was last optimized by Greg Roelofs & Mark Adler * */ |
| /* * * */ |
| /* ************************************************************************** */ |
| |
| #define MNG_COMPOSE8(RET,FG,ALPHA,BG) { \ |
| mng_uint16 iH = (mng_uint16)((mng_uint16)(FG) * (mng_uint16)(ALPHA) \ |
| + (mng_uint16)(BG)*(mng_uint16)(255 - \ |
| (mng_uint16)(ALPHA)) + (mng_uint16)128); \ |
| (RET) = (mng_uint8)((iH + (iH >> 8)) >> 8); } |
| |
| #define MNG_COMPOSE16(RET,FG,ALPHA,BG) { \ |
| mng_uint32 iH = (mng_uint32)((mng_uint32)(FG) * (mng_uint32)(ALPHA) \ |
| + (mng_uint32)(BG)*(mng_uint32)(65535L - \ |
| (mng_uint32)(ALPHA)) + (mng_uint32)32768L); \ |
| (RET) = (mng_uint16)((iH + (iH >> 16)) >> 16); } |
| |
| /* ************************************************************************** */ |
| /* * * */ |
| /* * Alpha blending macros * */ |
| /* * this code is based on Adam Costello's "Note on Compositing" from the * */ |
| /* * mng-list which gives the following formula: * */ |
| /* * * */ |
| /* * top pixel = (Rt, Gt, Bt, At) * */ |
| /* * bottom pixel = (Rb, Gb, Bb, Ab) * */ |
| /* * composite pixel = (Rc, Gc, Bc, Ac) * */ |
| /* * * */ |
| /* * all values in the range 0..1 * */ |
| /* * * */ |
| /* * Ac = 1 - (1 - At)(1 - Ab) * */ |
| /* * s = At / Ac * */ |
| /* * t = (1 - At) Ab / Ac * */ |
| /* * Rc = s Rt + t Rb * */ |
| /* * Gc = s Gt + t Gb * */ |
| /* * Bc = s Bt + t Bb * */ |
| /* * * */ |
| /* * (I just hope I coded it correctly in integer arithmetic...) * */ |
| /* * * */ |
| /* ************************************************************************** */ |
| |
| #define MNG_BLEND8(RT, GT, BT, AT, RB, GB, BB, AB, RC, GC, BC, AC) { \ |
| mng_uint32 S, T; \ |
| (AC) = (mng_uint8)((mng_uint32)255 - \ |
| ((((mng_uint32)255 - (mng_uint32)(AT)) * \ |
| ((mng_uint32)255 - (mng_uint32)(AB)) ) >> 8)); \ |
| S = (mng_uint32)(((mng_uint32)(AT) << 8) / \ |
| (mng_uint32)(AC)); \ |
| T = (mng_uint32)(((mng_uint32)255 - (mng_uint32)(AT)) * \ |
| (mng_uint32)(AB) / (mng_uint32)(AC)); \ |
| (RC) = (mng_uint8)((S * (mng_uint32)(RT) + \ |
| T * (mng_uint32)(RB) + (mng_uint32)127) >> 8); \ |
| (GC) = (mng_uint8)((S * (mng_uint32)(GT) + \ |
| T * (mng_uint32)(GB) + (mng_uint32)127) >> 8); \ |
| (BC) = (mng_uint8)((S * (mng_uint32)(BT) + \ |
| T * (mng_uint32)(BB) + (mng_uint32)127) >> 8); } |
| |
| #define MNG_BLEND16(RT, GT, BT, AT, RB, GB, BB, AB, RC, GC, BC, AC) { \ |
| mng_uint32 S, T; \ |
| (AC) = (mng_uint16)((mng_uint32)65535 - \ |
| ((((mng_uint32)65535 - (mng_uint32)(AT)) * \ |
| ((mng_uint32)65535 - (mng_uint32)(AB)) ) >> 16)); \ |
| S = (mng_uint32)(((mng_uint32)(AT) << 16) / \ |
| (mng_uint32)(AC)); \ |
| T = (mng_uint32)(((mng_uint32)65535 - (mng_uint32)(AT)) * \ |
| (mng_uint32)(AB) / (mng_uint32)(AC)); \ |
| (RC) = (mng_uint16)((S * (mng_uint32)(RT) + \ |
| T * (mng_uint32)(RB) + (mng_uint32)32767) >> 16); \ |
| (GC) = (mng_uint16)((S * (mng_uint32)(GT) + \ |
| T * (mng_uint32)(GB) + (mng_uint32)32767) >> 16); \ |
| (BC) = (mng_uint16)((S * (mng_uint32)(BT) + \ |
| T * (mng_uint32)(BB) + (mng_uint32)32767) >> 16); } |
| |
| /* ************************************************************************** */ |
| |
| /* note a good optimizing compiler will optimize this */ |
| #define DIV255B8(x) (mng_uint8)(((x) + 127) / 255) |
| #define DIV255B16(x) (mng_uint16)(((x) + 32767) / 65535) |
| |
| /* ************************************************************************** */ |
| /* * * */ |
| /* * Progressive display check - checks to see if progressive display is * */ |
| /* * in order & indicates so * */ |
| /* * * */ |
| /* * The routine is called after a call to one of the display_xxx routines * */ |
| /* * if appropriate * */ |
| /* * * */ |
| /* * The refresh is warrented in the read_chunk routine (mng_read.c) * */ |
| /* * and only during read&display processing, since there's not much point * */ |
| /* * doing it from memory! * */ |
| /* * * */ |
| /* ************************************************************************** */ |
| |
| mng_retcode mng_display_progressive_check (mng_datap pData) |
| { |
| if ((pData->bDoProgressive) && /* need progressive display? */ |
| ((pData->eImagetype != mng_it_mng) || (pData->iDataheight > 300)) && |
| (pData->iDestb - pData->iDestt > 50) && (!pData->pCurraniobj)) |
| { |
| mng_int32 iC = pData->iRow + pData->iDestt - pData->iSourcet; |
| |
| if (iC % 20 == 0) /* every 20th line */ |
| pData->bNeedrefresh = MNG_TRUE; |
| |
| } |
| |
| return MNG_NOERROR; |
| } |
| |
| /* ************************************************************************** */ |
| /* * * */ |
| /* * Display routines - convert rowdata (which is already color-corrected) * */ |
| /* * to the output canvas, respecting the opacity information * */ |
| /* * * */ |
| /* ************************************************************************** */ |
| |
| MNG_LOCAL void check_update_region (mng_datap pData) |
| { /* determine actual canvas row */ |
| mng_int32 iRow = pData->iRow + pData->iDestt - pData->iSourcet; |
| /* check for change in update-region */ |
| if ((pData->iDestl < (mng_int32)pData->iUpdateleft) || (pData->iUpdateright == 0)) |
| pData->iUpdateleft = pData->iDestl; |
| |
| if (pData->iDestr > (mng_int32)pData->iUpdateright) |
| pData->iUpdateright = pData->iDestr; |
| |
| if ((iRow < (mng_int32)pData->iUpdatetop) || (pData->iUpdatebottom == 0)) |
| pData->iUpdatetop = iRow; |
| |
| if (iRow+1 > (mng_int32)pData->iUpdatebottom) |
| pData->iUpdatebottom = iRow+1; |
| |
| return; |
| } |
| |
| /* ************************************************************************** */ |
| |
| #ifndef MNG_SKIPCANVAS_RGB8 |
| #ifndef MNG_NO_16BIT_SUPPORT |
| #ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| mng_retcode mng_display_rgb8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint16 iA16; |
| mng_uint16 iFGr16, iFGg16, iFGb16; |
| mng_uint16 iBGr16, iBGg16, iBGb16; |
| mng_uint8 iA8; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| if (pData->bIsRGBA16) /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3); |
| else |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+2); |
| *(pScanline+2) = *(pDataline+4); |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iA16 = mng_get_uint16 (pDataline+6); |
| |
| if (iA16) /* any opacity at all ? */ |
| { |
| if (iA16 == 0xFFFF) /* fully opaque ? */ |
| { /* scale down by dropping the LSB */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+2); |
| *(pScanline+2) = *(pDataline+4); |
| } |
| else |
| { /* get the proper values */ |
| iFGr16 = mng_get_uint16 (pDataline ); |
| iFGg16 = mng_get_uint16 (pDataline+2); |
| iFGb16 = mng_get_uint16 (pDataline+4); |
| /* scale background up */ |
| iBGr16 = (mng_uint16)(*pScanline ); |
| iBGg16 = (mng_uint16)(*(pScanline+1)); |
| iBGb16 = (mng_uint16)(*(pScanline+2)); |
| iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16; |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16; |
| /* now compose */ |
| MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16); |
| MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16); |
| MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16); |
| /* and return the composed values */ |
| *pScanline = (mng_uint8)(iFGr16 >> 8); |
| *(pScanline+1) = (mng_uint8)(iFGg16 >> 8); |
| *(pScanline+2) = (mng_uint8)(iFGb16 >> 8); |
| } |
| } |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iA8 = *(pDataline+3); /* get alpha value */ |
| |
| if (iA8) /* any opacity at all ? */ |
| { |
| if (iA8 == 0xFF) /* fully opaque ? */ |
| { /* then simply copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| } |
| else |
| { /* do alpha composing */ |
| MNG_COMPOSE8 (*pScanline, *pDataline, iA8, *pScanline ); |
| MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1)); |
| MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iA8, *(pScanline+2)); |
| } |
| } |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| mng_retcode mng_display_rgb8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint16 iA16; |
| mng_uint16 iFGg16; |
| mng_uint16 iBGg16; |
| mng_uint8 iA8; |
| mng_uint8 iBps; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_START); |
| #endif |
| |
| iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1); |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1)); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+iBps); |
| *(pScanline+2) = *(pDataline+2*iBps); |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 4*iBps; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iA16 = mng_get_uint16 (pDataline+6); |
| |
| if (iA16) /* any opacity at all ? */ |
| { |
| if (iA16 == 0xFFFF) /* fully opaque ? */ |
| { /* scale down by dropping the LSB */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+2); |
| *(pScanline+2) = *(pDataline+4); |
| } |
| else |
| { /* get the proper values */ |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| iFGg16 = mng_get_uint16 (pDataline+i+i); |
| /* scale background up */ |
| iBGg16 = (mng_uint16)(*(pScanline+i)); |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| /* now compose */ |
| MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16); |
| /* and return the composed values */ |
| *(pScanline+i) = (mng_uint8)(iFGg16 >> 8); |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iA8 = *(pDataline+3); /* get alpha value */ |
| |
| if (iA8) /* any opacity at all ? */ |
| { |
| if (iA8 == 0xFF) /* fully opaque ? */ |
| { /* then simply copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| } |
| else |
| { /* do alpha composing */ |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iA8, *(pScanline+i)); |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| #else /* MNG_NO_16BIT_SUPPORT */ |
| mng_retcode mng_display_rgb8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iA8; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iA8 = *(pDataline+3); /* get alpha value */ |
| |
| if (iA8) /* any opacity at all ? */ |
| { |
| if (iA8 == 0xFF) /* fully opaque ? */ |
| { /* then simply copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| } |
| else |
| { /* do alpha composing */ |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iA8, *(pScanline+i)); |
| } |
| #else |
| MNG_COMPOSE8 (*pScanline, *pDataline, iA8, *pScanline ); |
| MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1)); |
| MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iA8, *(pScanline+2)); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc * 3); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_NO_16BIT_SUPPORT */ |
| #endif /* MNG_SKIPCANVAS_RGB8 */ |
| |
| /* ************************************************************************** */ |
| |
| #ifndef MNG_SKIPCANVAS_RGBA8 |
| #ifndef MNG_NO_16BIT_SUPPORT |
| #ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| mng_retcode mng_display_rgba8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iFGa8, iBGa8, iCa8; |
| mng_uint16 iFGa16, iBGa16, iCa16; |
| mng_uint16 iFGr16, iFGg16, iFGb16; |
| mng_uint16 iBGr16, iBGg16, iBGb16; |
| mng_uint16 iCr16, iCg16, iCb16; |
| mng_uint8 iCr8, iCg8, iCb8; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| if (pData->bIsRGBA16) /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3); |
| else |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+2); |
| *(pScanline+2) = *(pDataline+4); |
| *(pScanline+3) = *(pDataline+6); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+3); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| iFGa16 = mng_get_uint16 (pDataline+6); |
| iBGa16 = (mng_uint16)(*(pScanline+3)); |
| iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16; |
| |
| if (iFGa16) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa16 == 0xFFFF) || (iBGa16 == 0)) |
| { /* plain copy it */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+2); |
| *(pScanline+2) = *(pDataline+4); |
| *(pScanline+3) = *(pDataline+6); |
| } |
| else |
| { |
| if (iBGa16 == 0xFFFF) /* background fully opaque ? */ |
| { /* get the proper values */ |
| iFGr16 = mng_get_uint16 (pDataline ); |
| iFGg16 = mng_get_uint16 (pDataline+2); |
| iFGb16 = mng_get_uint16 (pDataline+4); |
| /* scale background up */ |
| iBGr16 = (mng_uint16)(*pScanline ); |
| iBGg16 = (mng_uint16)(*(pScanline+1)); |
| iBGb16 = (mng_uint16)(*(pScanline+2)); |
| iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16; |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16; |
| /* now compose */ |
| MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16); |
| MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16); |
| MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16); |
| /* and return the composed values */ |
| *pScanline = (mng_uint8)(iFGr16 >> 8); |
| *(pScanline+1) = (mng_uint8)(iFGg16 >> 8); |
| *(pScanline+2) = (mng_uint8)(iFGb16 >> 8); |
| /* alpha remains fully opaque !!! */ |
| } |
| else |
| { /* scale background up */ |
| iBGr16 = (mng_uint16)(*pScanline ); |
| iBGg16 = (mng_uint16)(*(pScanline+1)); |
| iBGb16 = (mng_uint16)(*(pScanline+2)); |
| iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16; |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16; |
| /* let's blend */ |
| MNG_BLEND16 (mng_get_uint16 (pDataline ), |
| mng_get_uint16 (pDataline+2), |
| mng_get_uint16 (pDataline+4), iFGa16, |
| iBGr16, iBGg16, iBGb16, iBGa16, |
| iCr16, iCg16, iCb16, iCa16); |
| /* and return the composed values */ |
| *pScanline = (mng_uint8)(iCr16 >> 8); |
| *(pScanline+1) = (mng_uint8)(iCg16 >> 8); |
| *(pScanline+2) = (mng_uint8)(iCb16 >> 8); |
| *(pScanline+3) = (mng_uint8)(iCa16 >> 8); |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iFGa8 = *(pDataline+3); /* get alpha values */ |
| iBGa8 = *(pScanline+3); |
| |
| if (iFGa8) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa8 == 0xFF) || (iBGa8 == 0)) |
| { /* then simply copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+3); |
| } |
| else |
| { |
| if (iBGa8 == 0xFF) /* background fully opaque ? */ |
| { /* do alpha composing */ |
| MNG_COMPOSE8 (*pScanline, *pDataline, iFGa8, *pScanline ); |
| MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1)); |
| MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iFGa8, *(pScanline+2)); |
| /* alpha remains fully opaque !!! */ |
| } |
| else |
| { /* now blend */ |
| MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8, |
| *pScanline, *(pScanline+1), *(pScanline+2), iBGa8, |
| iCr8, iCg8, iCb8, iCa8); |
| /* and return the composed values */ |
| *pScanline = iCr8; |
| *(pScanline+1) = iCg8; |
| *(pScanline+2) = iCb8; |
| *(pScanline+3) = iCa8; |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| mng_retcode mng_display_rgba8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iFGa8, iBGa8, iCa8; |
| mng_uint16 iFGa16, iBGa16, iCa16; |
| mng_uint16 iFGg16; |
| mng_uint16 iBGr16, iBGg16, iBGb16; |
| mng_uint16 iCr16, iCg16, iCb16; |
| mng_uint8 iCr8, iCg8, iCb8; |
| mng_uint8 iBps; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_START); |
| #endif |
| |
| iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1); |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1)); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+iBps); |
| *(pScanline+2) = *(pDataline+2*iBps); |
| *(pScanline+3) = *(pDataline+3*iBps); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4*iBps; |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| iFGa16 = mng_get_uint16 (pDataline+6); |
| iBGa16 = (mng_uint16)(*(pScanline+3)); |
| iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16; |
| |
| if (iFGa16) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa16 == 0xFFFF) || (iBGa16 == 0)) |
| { /* plain copy it */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+2); |
| *(pScanline+2) = *(pDataline+4); |
| *(pScanline+3) = *(pDataline+6); |
| } |
| else |
| { |
| if (iBGa16 == 0xFFFF) /* background fully opaque ? */ |
| { /* get the proper values */ |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| iFGg16 = mng_get_uint16 (pDataline+i+i); |
| /* scale background up */ |
| iBGg16 = (mng_uint16)(*(pScanline+i)); |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| /* now compose */ |
| MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16); |
| /* and return the composed values */ |
| *(pScanline+i) = (mng_uint8)(iFGg16 >> 8); |
| /* alpha remains fully opaque !!! */ |
| } |
| } |
| else |
| { /* scale background up */ |
| iBGr16 = (mng_uint16)(*pScanline ); |
| iBGg16 = (mng_uint16)(*(pScanline+1)); |
| iBGb16 = (mng_uint16)(*(pScanline+2)); |
| iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16; |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16; |
| /* let's blend */ |
| MNG_BLEND16 (mng_get_uint16 (pDataline ), |
| mng_get_uint16 (pDataline+2), |
| mng_get_uint16 (pDataline+4), iFGa16, |
| iBGr16, iBGg16, iBGb16, iBGa16, |
| iCr16, iCg16, iCb16, iCa16); |
| /* and return the composed values */ |
| *pScanline = (mng_uint8)(iCr16 >> 8); |
| *(pScanline+1) = (mng_uint8)(iCg16 >> 8); |
| *(pScanline+2) = (mng_uint8)(iCb16 >> 8); |
| *(pScanline+3) = (mng_uint8)(iCa16 >> 8); |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iFGa8 = *(pDataline+3); /* get alpha values */ |
| iBGa8 = *(pScanline+3); |
| |
| if (iFGa8) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa8 == 0xFF) || (iBGa8 == 0)) |
| { /* then simply copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+3); |
| } |
| else |
| { |
| if (iBGa8 == 0xFF) /* background fully opaque ? */ |
| { /* do alpha composing */ |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iFGa8, *(pScanline+i)); |
| } |
| /* alpha remains fully opaque !!! */ |
| } |
| else |
| { /* now blend */ |
| MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8, |
| *pScanline, *(pScanline+1), *(pScanline+2), iBGa8, |
| iCr8, iCg8, iCb8, iCa8); |
| /* and return the composed values */ |
| *pScanline = iCr8; |
| *(pScanline+1) = iCg8; |
| *(pScanline+2) = iCb8; |
| *(pScanline+3) = iCa8; |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| #else /* MNG_NO_16BIT_SUPPORT */ |
| mng_retcode mng_display_rgba8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iFGa8, iBGa8, iCa8; |
| mng_uint8 iCr8, iCg8, iCb8; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+3); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iFGa8 = *(pDataline+3); /* get alpha values */ |
| iBGa8 = *(pScanline+3); |
| |
| if (iFGa8) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa8 == 0xFF) || (iBGa8 == 0)) |
| { /* then simply copy the values */ |
| *pScanline = *pDataline; |
| *(pScanline+1) = *(pDataline+1); |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+3); |
| } |
| else |
| { |
| if (iBGa8 == 0xFF) /* background fully opaque ? */ |
| { /* do alpha composing */ |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iFGa8, *(pScanline+i)); |
| } |
| #else |
| MNG_COMPOSE8 (*pScanline, *pDataline, iFGa8, *pScanline ); |
| MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1)); |
| MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iFGa8, *(pScanline+2)); |
| #endif |
| /* alpha remains fully opaque !!! */ |
| } |
| else |
| { /* now blend */ |
| MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8, |
| *pScanline, *(pScanline+1), *(pScanline+2), iBGa8, |
| iCr8, iCg8, iCb8, iCa8); |
| /* and return the composed values */ |
| *pScanline = iCr8; |
| *(pScanline+1) = iCg8; |
| *(pScanline+2) = iCb8; |
| *(pScanline+3) = iCa8; |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_NO_16BIT_SUPPORT */ |
| #endif /* MNG_SKIPCANVAS_RGBA8 */ |
| |
| /* ************************************************************************** */ |
| |
| #ifndef MNG_SKIPCANVAS_RGBA8_PM |
| #ifndef MNG_NO_16BIT_SUPPORT |
| #ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| mng_retcode mng_display_rgba8_pm (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint32 s, t; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| if (pData->bIsRGBA16) /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3); |
| else |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| if ((s = pDataline[6]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[2]; |
| pScanline[2] = pDataline[4]; |
| pScanline[3] = 255; |
| } |
| else |
| { |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[4-i-i]); |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[2]); |
| pScanline[2] = DIV255B8(s * pDataline[4]); |
| #endif |
| pScanline[3] = (mng_uint8)s; |
| } |
| } |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values and premultiply */ |
| if ((s = pDataline[3]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| #ifdef MNG_BIGENDIAN_SUPPORTED |
| *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF; |
| #else |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[1]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = 255; |
| #endif |
| } |
| else |
| { |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[2-i]); |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)s; |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| if ((s = pDataline[6]) != 0) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if (s == 255) |
| { /* plain copy it */ |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[2]; |
| pScanline[2] = pDataline[4]; |
| pScanline[3] = 255; |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[4-i-i] + t * |
| pScanline[2-i]); |
| } |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[4] + t * pScanline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3]))); |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| if ((s = pDataline[3]) != 0) /* any opacity at all ? */ |
| { /* fully opaque ? */ |
| if (s == 255) |
| { /* then simply copy the values */ |
| #ifdef MNG_BIGENDIAN_SUPPORTED |
| *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF; |
| #else |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[1]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = 255; |
| #endif |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[2-i] + t * |
| pScanline[2-i]); |
| } |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3]))); |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| mng_retcode mng_display_rgba8_pm (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint32 s, t; |
| mng_uint8 iBps; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_START); |
| #endif |
| |
| iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1); |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1)); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| if ((s = pDataline[6]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[2]; |
| pScanline[2] = pDataline[4]; |
| pScanline[3] = 255; |
| } |
| else |
| { |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[4-i-i]); |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[2]); |
| pScanline[2] = DIV255B8(s * pDataline[4]); |
| #endif |
| pScanline[3] = (mng_uint8)s; |
| } |
| } |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values and premultiply */ |
| if ((s = pDataline[3]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| #ifdef MNG_BIGENDIAN_SUPPORTED |
| *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF; |
| #else |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[1]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = 255; |
| #endif |
| } |
| else |
| { |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[2-i]); |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)s; |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| if ((s = pDataline[6]) != 0) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if (s == 255) |
| { /* plain copy it */ |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[2]; |
| pScanline[2] = pDataline[4]; |
| pScanline[3] = 255; |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[4-i-i] + t * |
| pScanline[2-i]); |
| } |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[4] + t * pScanline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3]))); |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| if ((s = pDataline[3]) != 0) /* any opacity at all ? */ |
| { /* fully opaque ? */ |
| if (s == 255) |
| { /* then simply copy the values */ |
| #ifdef MNG_BIGENDIAN_SUPPORTED |
| *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF; |
| #else |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[1]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = 255; |
| #endif |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[2-i] + t * |
| pScanline[2-i]); |
| } |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3]))); |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| #else /* MNG_NO_16BIT_SUPPORT */ |
| mng_retcode mng_display_rgba8_pm (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint32 s, t; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values and premultiply */ |
| if ((s = pDataline[3]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| #ifdef MNG_BIGENDIAN_SUPPORTED |
| *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF; |
| #else |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[1]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = 255; |
| #endif |
| } |
| else |
| { |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[2-i]); |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)s; |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| if ((s = pDataline[3]) != 0) /* any opacity at all ? */ |
| { /* fully opaque ? */ |
| if (s == 255) |
| { /* then simply copy the values */ |
| #ifdef MNG_BIGENDIAN_SUPPORTED |
| *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF; |
| #else |
| pScanline[0] = pDataline[0]; |
| pScanline[1] = pDataline[1]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = 255; |
| #endif |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[2-i] = DIV255B8(s * pDataline[2-i] + t * |
| pScanline[2-i]); |
| } |
| } |
| #else |
| pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]); |
| pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]); |
| #endif |
| pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3]))); |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_NO_16BIT_SUPPORT */ |
| #endif /* MNG_SKIPCANVAS_RGBA8_PM */ |
| |
| /* ************************************************************************** */ |
| |
| #ifndef MNG_SKIPCANVAS_ARGB8 |
| #ifndef MNG_NO_16BIT_SUPPORT |
| #ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| mng_retcode mng_display_argb8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iFGa8, iBGa8, iCa8; |
| mng_uint16 iFGa16, iBGa16, iCa16; |
| mng_uint16 iFGr16, iFGg16, iFGb16; |
| mng_uint16 iBGr16, iBGg16, iBGb16; |
| mng_uint16 iCr16, iCg16, iCb16; |
| mng_uint8 iCr8, iCg8, iCb8; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_START); |
| #endif |
| |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| if (pData->bIsRGBA16) /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3); |
| else |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| *pScanline = *(pDataline+6); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+4); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values */ |
| *pScanline = *(pDataline+3); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+1); |
| *(pScanline+3) = *(pDataline+2); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| iFGa16 = mng_get_uint16 (pDataline+6); |
| iBGa16 = (mng_uint16)(*pScanline); |
| iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16; |
| |
| if (iFGa16) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa16 == 0xFFFF) || (iBGa16 == 0)) |
| { /* plain copy it */ |
| *pScanline = *(pDataline+6); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+4); |
| } |
| else |
| { |
| if (iBGa16 == 0xFFFF) /* background fully opaque ? */ |
| { /* get the proper values */ |
| iFGr16 = mng_get_uint16 (pDataline ); |
| iFGg16 = mng_get_uint16 (pDataline+2); |
| iFGb16 = mng_get_uint16 (pDataline+4); |
| /* scale background up */ |
| iBGr16 = (mng_uint16)(*(pScanline+1)); |
| iBGg16 = (mng_uint16)(*(pScanline+2)); |
| iBGb16 = (mng_uint16)(*(pScanline+3)); |
| iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16; |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16; |
| /* now compose */ |
| MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16); |
| MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16); |
| MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16); |
| /* and return the composed values */ |
| /* alpha remains fully opaque !!! */ |
| *(pScanline+1) = (mng_uint8)(iFGr16 >> 8); |
| *(pScanline+2) = (mng_uint8)(iFGg16 >> 8); |
| *(pScanline+3) = (mng_uint8)(iFGb16 >> 8); |
| } |
| else |
| { /* scale background up */ |
| iBGr16 = (mng_uint16)(*(pScanline+1)); |
| iBGg16 = (mng_uint16)(*(pScanline+2)); |
| iBGb16 = (mng_uint16)(*(pScanline+3)); |
| iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16; |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16; |
| /* let's blend */ |
| MNG_BLEND16 (mng_get_uint16 (pDataline ), |
| mng_get_uint16 (pDataline+2), |
| mng_get_uint16 (pDataline+4), iFGa16, |
| iBGr16, iBGg16, iBGb16, iBGa16, |
| iCr16, iCg16, iCb16, iCa16); |
| /* and return the composed values */ |
| *pScanline = (mng_uint8)(iCa16 >> 8); |
| *(pScanline+1) = (mng_uint8)(iCr16 >> 8); |
| *(pScanline+2) = (mng_uint8)(iCg16 >> 8); |
| *(pScanline+3) = (mng_uint8)(iCb16 >> 8); |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iFGa8 = *(pDataline+3); /* get alpha values */ |
| iBGa8 = *pScanline; |
| |
| if (iFGa8) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa8 == 0xFF) || (iBGa8 == 0)) |
| { /* then simply copy the values */ |
| *pScanline = *(pDataline+3); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+1); |
| *(pScanline+3) = *(pDataline+2); |
| } |
| else |
| { |
| if (iBGa8 == 0xFF) /* background fully opaque ? */ |
| { /* do simple alpha composing */ |
| /* alpha itself remains fully opaque !!! */ |
| } |
| else |
| { /* now blend */ |
| MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8, |
| *(pScanline+1), *(pScanline+2), *(pScanline+3), iBGa8, |
| iCr8, iCg8, iCb8, iCa8); |
| /* and return the composed values */ |
| *pScanline = iCa8; |
| *(pScanline+1) = iCr8; |
| *(pScanline+2) = iCg8; |
| *(pScanline+3) = iCb8; |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| mng_retcode mng_display_argb8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iFGa8, iBGa8, iCa8; |
| mng_uint16 iFGa16, iBGa16, iCa16; |
| mng_uint16 iFGg16; |
| mng_uint16 iBGr16, iBGg16, iBGb16; |
| mng_uint16 iCr16, iCg16, iCb16; |
| mng_uint8 iCr8, iCg8, iCb8; |
| mng_uint8 iBps; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_START); |
| #endif |
| |
| iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1); |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1)); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| *pScanline = *(pDataline+3*iBps); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+iBps); |
| *(pScanline+3) = *(pDataline+2*iBps); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4*iBps; |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| iFGa16 = mng_get_uint16 (pDataline+6); |
| iBGa16 = (mng_uint16)(*pScanline); |
| iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16; |
| |
| if (iFGa16) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa16 == 0xFFFF) || (iBGa16 == 0)) |
| { /* plain copy it */ |
| *pScanline = *(pDataline+6); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+2); |
| *(pScanline+3) = *(pDataline+4); |
| } |
| else |
| { |
| if (iBGa16 == 0xFFFF) /* background fully opaque ? */ |
| { /* get the proper values */ |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| iFGg16 = mng_get_uint16 (pDataline+i+i); |
| /* scale background up */ |
| iBGg16 = (mng_uint16)(*(pScanline+i+1)); |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| /* now compose */ |
| MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16); |
| /* and return the composed values */ |
| /* alpha remains fully opaque !!! */ |
| *(pScanline+i+1) = (mng_uint8)(iFGg16 >> 8); |
| } |
| } |
| else |
| { /* scale background up */ |
| iBGr16 = (mng_uint16)(*(pScanline+1)); |
| iBGg16 = (mng_uint16)(*(pScanline+2)); |
| iBGb16 = (mng_uint16)(*(pScanline+3)); |
| iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16; |
| iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16; |
| iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16; |
| /* let's blend */ |
| MNG_BLEND16 (mng_get_uint16 (pDataline ), |
| mng_get_uint16 (pDataline+2), |
| mng_get_uint16 (pDataline+4), iFGa16, |
| iBGr16, iBGg16, iBGb16, iBGa16, |
| iCr16, iCg16, iCb16, iCa16); |
| /* and return the composed values */ |
| *pScanline = (mng_uint8)(iCa16 >> 8); |
| *(pScanline+1) = (mng_uint8)(iCr16 >> 8); |
| *(pScanline+2) = (mng_uint8)(iCg16 >> 8); |
| *(pScanline+3) = (mng_uint8)(iCb16 >> 8); |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iFGa8 = *(pDataline+3); /* get alpha values */ |
| iBGa8 = *pScanline; |
| |
| if (iFGa8) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa8 == 0xFF) || (iBGa8 == 0)) |
| { /* then simply copy the values */ |
| *pScanline = *(pDataline+3); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+1); |
| *(pScanline+3) = *(pDataline+2); |
| } |
| else |
| { |
| if (iBGa8 == 0xFF) /* background fully opaque ? */ |
| { /* do simple alpha composing */ |
| /* alpha itself remains fully opaque !!! */ |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| MNG_COMPOSE8 (*(pScanline+i+1), *(pDataline+i), iFGa8, *(pScanline+i+1)); |
| } |
| } |
| else |
| { /* now blend */ |
| MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8, |
| *(pScanline+1), *(pScanline+2), *(pScanline+3), iBGa8, |
| iCr8, iCg8, iCb8, iCa8); |
| /* and return the composed values */ |
| *pScanline = iCa8; |
| *(pScanline+1) = iCr8; |
| *(pScanline+2) = iCg8; |
| *(pScanline+3) = iCb8; |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| #else /* MNG_NO_16BIT_SUPPORT */ |
| mng_retcode mng_display_argb8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iFGa8, iBGa8, iCa8; |
| mng_uint8 iCr8, iCg8, iCb8; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_START); |
| #endif |
| |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values */ |
| *pScanline = *(pDataline+3); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+1); |
| *(pScanline+3) = *(pDataline+2); |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| iFGa8 = *(pDataline+3); /* get alpha values */ |
| iBGa8 = *pScanline; |
| |
| if (iFGa8) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if ((iFGa8 == 0xFF) || (iBGa8 == 0)) |
| { /* then simply copy the values */ |
| *pScanline = *(pDataline+3); |
| *(pScanline+1) = *pDataline; |
| *(pScanline+2) = *(pDataline+1); |
| *(pScanline+3) = *(pDataline+2); |
| } |
| else |
| { |
| if (iBGa8 == 0xFF) /* background fully opaque ? */ |
| { /* do simple alpha composing */ |
| /* alpha itself remains fully opaque !!! */ |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| MNG_COMPOSE8 (*(pScanline+i+1), *(pDataline+i), iFGa8, *(pScanline+i+1)); |
| } |
| #else |
| MNG_COMPOSE8 (*(pScanline+1), *pDataline, iFGa8, *(pScanline+1)); |
| MNG_COMPOSE8 (*(pScanline+2), *(pDataline+1), iFGa8, *(pScanline+2)); |
| MNG_COMPOSE8 (*(pScanline+3), *(pDataline+2), iFGa8, *(pScanline+3)); |
| #endif |
| } |
| else |
| { /* now blend */ |
| MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8, |
| *(pScanline+1), *(pScanline+2), *(pScanline+3), iBGa8, |
| iCr8, iCg8, iCb8, iCa8); |
| /* and return the composed values */ |
| *pScanline = iCa8; |
| *(pScanline+1) = iCr8; |
| *(pScanline+2) = iCg8; |
| *(pScanline+3) = iCb8; |
| } |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_NO_16BIT_SUPPORT */ |
| #endif /* MNG_SKIPCANVAS_ARGB8 */ |
| |
| /* ************************************************************************** */ |
| |
| #ifndef MNG_SKIPCANVAS_ARGB8_PM |
| #ifndef MNG_NO_16BIT_SUPPORT |
| #ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| mng_retcode mng_display_argb8_pm (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint32 s, t; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| if (pData->bIsRGBA16) /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3); |
| else |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| if ((s = pDataline[6]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = pDataline[4]; |
| } |
| else |
| { |
| pScanline[0] = (mng_uint8)s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[4-i-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0]); |
| pScanline[2] = DIV255B8(s * pDataline[2]); |
| pScanline[3] = DIV255B8(s * pDataline[4]); |
| #endif |
| } |
| } |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values and premultiply */ |
| if ((s = pDataline[3]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[1]; |
| pScanline[3] = pDataline[2]; |
| } |
| else |
| { |
| pScanline[0] = (mng_uint8)s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[2-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0]); |
| pScanline[2] = DIV255B8(s * pDataline[1]); |
| pScanline[3] = DIV255B8(s * pDataline[2]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| if ((s = pDataline[6]) != 0) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if (s == 255) |
| { /* plain copy it */ |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = pDataline[4]; |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0]))); |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[4-i-i] + t * |
| pScanline[3-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]); |
| pScanline[3] = DIV255B8(s * pDataline[4] + t * pScanline[3]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| if ((s = pDataline[3]) != 0) /* any opacity at all ? */ |
| { /* fully opaque ? */ |
| if (s == 255) |
| { /* then simply copy the values */ |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[1]; |
| pScanline[3] = pDataline[2]; |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0]))); |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[2-i] + t * |
| pScanline[3-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]); |
| pScanline[3] = DIV255B8(s * pDataline[2] + t * pScanline[3]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| mng_retcode mng_display_argb8_pm (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint32 s, t; |
| mng_uint8 iBps; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_START); |
| #endif |
| |
| iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1); |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| /* adjust source row starting-point */ |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1)); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* scale down by dropping the LSB */ |
| if ((s = pDataline[6]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = pDataline[4]; |
| } |
| else |
| { |
| pScanline[0] = (mng_uint8)s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[4-i-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0]); |
| pScanline[2] = DIV255B8(s * pDataline[2]); |
| pScanline[3] = DIV255B8(s * pDataline[4]); |
| #endif |
| } |
| } |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values and premultiply */ |
| if ((s = pDataline[3]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[1]; |
| pScanline[3] = pDataline[2]; |
| } |
| else |
| { |
| pScanline[0] = (mng_uint8)s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[2-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0]); |
| pScanline[2] = DIV255B8(s * pDataline[1]); |
| pScanline[3] = DIV255B8(s * pDataline[2]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| if (pData->bIsRGBA16) /* 16-bit input row ? */ |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* get alpha values */ |
| if ((s = pDataline[6]) != 0) /* any opacity at all ? */ |
| { /* fully opaque or background fully transparent ? */ |
| if (s == 255) |
| { /* plain copy it */ |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[2]; |
| pScanline[3] = pDataline[4]; |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0]))); |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[4-i-i] + t * |
| pScanline[3-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]); |
| pScanline[3] = DIV255B8(s * pDataline[4] + t * pScanline[3]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 8; |
| } |
| } |
| else |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| if ((s = pDataline[3]) != 0) /* any opacity at all ? */ |
| { /* fully opaque ? */ |
| if (s == 255) |
| { /* then simply copy the values */ |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[1]; |
| pScanline[3] = pDataline[2]; |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0]))); |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[2-i] + t * |
| pScanline[3-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]); |
| pScanline[3] = DIV255B8(s * pDataline[2] + t * pScanline[3]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */ |
| #else /* MNG_NO_16BIT_SUPPORT */ |
| mng_retcode mng_display_argb8_pm (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint32 s, t; |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_START); |
| #endif |
| /* viewable row ? */ |
| if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb)) |
| { /* address destination row */ |
| pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData), |
| pData->iRow + pData->iDestt - |
| pData->iSourcet); |
| /* adjust destination row starting-point */ |
| pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2); |
| pDataline = pData->pRGBArow; /* address source row */ |
| |
| pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2); |
| |
| if (pData->bIsOpaque) /* forget about transparency ? */ |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { /* copy the values and premultiply */ |
| if ((s = pDataline[3]) == 0) |
| *(mng_uint32*) pScanline = 0; /* set all components = 0 */ |
| else |
| { |
| if (s == 255) |
| { |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[1]; |
| pScanline[3] = pDataline[2]; |
| } |
| else |
| { |
| pScanline[0] = (mng_uint8)s; |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[2-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0]); |
| pScanline[2] = DIV255B8(s * pDataline[1]); |
| pScanline[3] = DIV255B8(s * pDataline[2]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| else |
| { |
| { |
| for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer; |
| iX += pData->iColinc) |
| { |
| if ((s = pDataline[3]) != 0) /* any opacity at all ? */ |
| { /* fully opaque ? */ |
| if (s == 255) |
| { /* then simply copy the values */ |
| pScanline[0] = 255; |
| pScanline[1] = pDataline[0]; |
| pScanline[2] = pDataline[1]; |
| pScanline[3] = pDataline[2]; |
| } |
| else |
| { /* now blend (premultiplied) */ |
| t = 255 - s; |
| pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0]))); |
| #ifdef MNG_OPTIMIZE_FOOTPRINT_DIV |
| { |
| int i; |
| for (i=2; i >= 0; i--) |
| { |
| pScanline[3-i] = DIV255B8(s * pDataline[2-i] + t * |
| pScanline[3-i]); |
| } |
| } |
| #else |
| pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]); |
| pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]); |
| pScanline[3] = DIV255B8(s * pDataline[2] + t * pScanline[3]); |
| #endif |
| } |
| } |
| |
| pScanline += (pData->iColinc << 2); |
| pDataline += 4; |
| } |
| } |
| } |
| } |
| |
| check_update_region (pData); |
| |
| #ifdef MNG_SUPPORT_TRACE |
| MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_END); |
| #endif |
| |
| return MNG_NOERROR; |
| } |
| #endif /* MNG_NO_16BIT_SUPPORT */ |
| #endif /* MNG_SKIPCANVAS_ARGB8_PM */ |
| |
| /* ************************************************************************** */ |
| |
| #ifndef MNG_SKIPCANVAS_RGB8_A8 |
| #ifndef MNG_NO_16BIT_SUPPORT |
| #ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE |
| mng_retcode mng_display_rgb8_a8 (mng_datap pData) |
| { |
| mng_uint8p pScanline; |
| mng_uint8p pAlphaline; |
| mng_uint8p pDataline; |
| mng_int32 iX; |
| mng_uint8 iFGa8, iBGa8, iCa8; |
| mng_uint16 iFGa16, iBGa16, iCa16; |
| mng_uint16 iFGr16, iFGg16, iFGb16; |
| mng_uint16 iBGr16, iBGg16, iBGb16; |
| mng_uint16 iCr16, iCg16, iCb16; |
| mng_uint8 iCr8, iCg8, iCb8; |
| |
| #ifdef MNG_SUPPORT_TRACE |
|