/*- * Copyright (c) 1997-2002 The Protein Laboratory, University of Copenhagen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id$ */ /* Created by Dmitry Karasik */ #include "img_conv.h" #ifdef __cplusplus extern "C" { #endif #define var (( PImage) self) #define BS_BYTEIMPACT( type) \ void bs_##type##_in( type * srcData, type * dstData, int w, int x, int absx, long step) \ { \ Fixed count = {0}; \ int last = 0; \ int i; \ int j = ( x == absx) ? 0 : ( absx - 1); \ int inc = ( x == absx) ? 1 : -1; \ dstData[j] = srcData[0]; \ j += inc; \ for ( i = 0; i < w; i++) \ { \ if ( count.i.i > last) \ { \ dstData[j] = srcData[i]; \ j += inc; \ last = count. i. i; \ } \ count. l += step; \ } \ } #define BS_BYTEEXPAND( type) \ void bs_##type##_out( type * srcData, type * dstData, int w, int x, int absx, long step) \ { \ Fixed count = {0}; \ int i; \ int j = ( x == absx) ? 0 : ( absx - 1); \ int inc = ( x == absx) ? 1 : -1; \ int last = 0; \ for ( i = 0; i < absx; i++) \ { \ if ( count. i. i > last) \ { \ last = count. i. i; \ srcData++; \ } \ count. l += step; \ dstData[j] = *srcData; \ j += inc; \ } \ } BS_BYTEEXPAND( uint8_t) BS_BYTEEXPAND( int16_t) BS_BYTEEXPAND( RGBColor) BS_BYTEEXPAND( int32_t) BS_BYTEEXPAND( float) BS_BYTEEXPAND( double) BS_BYTEEXPAND( Complex) BS_BYTEEXPAND( DComplex) BS_BYTEIMPACT( uint8_t) BS_BYTEIMPACT( int16_t) BS_BYTEIMPACT( RGBColor) BS_BYTEIMPACT( int32_t) BS_BYTEIMPACT( float) BS_BYTEIMPACT( double) BS_BYTEIMPACT( Complex) BS_BYTEIMPACT( DComplex) void bs_mono_in( uint8_t * srcData, uint8_t * dstData, int w, int x, int absx, long step) { Fixed count = {0}; int last = 0; register int i, j; register U16 xd, xs; if ( x == absx) { xd = (( xs = srcData[0]) >> 7) & 1; j = 1; for ( i = 0; i < w; i++) { if (( i & 7) == 0) xs = srcData[ i >> 3]; xs <<= 1; if ( count.i.i > last) { if (( j & 7) == 0) dstData[ ( j - 1) >> 3] = xd; xd <<= 1; xd |= ( xs >> 8) & 1; j++; last = count. i. i; } count. l += step; } i = j & 7; dstData[( j - 1) >> 3] = xd << ( i ? ( 8 - i) : 0); } else { j = absx - 1; xd = ( xs = srcData[ j >> 3]) & 0x80; for ( i = 0; i < w; i++) { if (( i & 7) == 0) xs = srcData[ i >> 3]; xs <<= 1; if ( count.i.i > last) { if (( j & 7) == 0) dstData[ ( j + 1) >> 3] = xd; xd >>= 1; xd |= ( xs >> 1) & 0x80; j--; last = count. i. i; } count. l += step; } dstData[( j + 1) >> 3] = xd; } } void bs_mono_out( uint8_t * srcData, uint8_t * dstData, int w, int x, int absx, long step) { Fixed count = {0}; register int i, j = 0; register U16 xd = 0, xs; int last = 0; if ( x == absx) { xs = srcData[0]; for ( i = 0; i < absx; i++) { if ( count. i. i > last) { last = count.i.i; xs <<= 1; j++; if (( j & 7) == 0) xs = srcData[ j >> 3]; } count.l += step; xd <<= 1; xd |= ( xs >> 7) & 1; if ((( i + 1) & 7) == 0) dstData[ i >> 3] = xd; } if ( i & 7) dstData[ i >> 3] = xd << ( 8 - ( i & 7)); /* dstData[ i >> 3] = xd << (( i & 7) ? ( 8 - ( i & 7)) : 0); */ } else { register int k = absx; xs = srcData[ j >> 3]; for ( i = 0; i < absx; i++) { if ( count. i. i > last) { last = count.i.i; xs <<= 1; j++; if (( j & 7) == 0) xs = srcData[ j >> 3]; } count.l += step; xd >>= 1; xd |= xs & 0x80; k--; if (( k & 7) == 0) dstData[( k + 1) >> 3] = xd; } dstData[( k + 0) >> 3] = xd; } } /* nibble stretching functions are requiring *dstData filled with zeros */ void bs_nibble_in( uint8_t * srcData, uint8_t * dstData, int w, int x, int absx, long step) { Fixed count = {0}; int last = 0; int i; int j = ( x == absx) ? 0 : ( absx - 1); int inc = ( x == absx) ? 1 : -1; dstData[ j >> 1] |= ( j & 1) ? ( srcData[ 0] >> 4) : ( srcData[ 0] & 0xF0); j += inc; for ( i = 0; i < w; i++) { if ( count.i.i > last) { if ( i & 1) dstData[ j >> 1] |= ( j & 1) ? ( srcData[ i >> 1] & 0x0F) : ( srcData[ i >> 1] << 4); else dstData[ j >> 1] |= ( j & 1) ? ( srcData[ i >> 1] >> 4) : ( srcData[ i >> 1] & 0xF0); j += inc; last = count. i. i; } count. l += step; } } void bs_nibble_out( uint8_t * srcData, uint8_t * dstData, int w, int x, int absx, long step) { Fixed count = {0}; int i, k = 0; int j = ( x == absx) ? 0 : ( absx - 1); int inc = ( x == absx) ? 1 : -1; int last = 0; for ( i = 0; i < absx; i++) { if ( count. i. i > last) { if (( k & 1) == 1) srcData++; k++; last = count. i. i; } count. l += step; if ( k & 1) dstData[ j >> 1] |= ( j & 1) ? ( *srcData & 0x0F) : ( *srcData << 4); else dstData[ j >> 1] |= ( j & 1) ? ( *srcData >> 4) : ( *srcData & 0xF0); j += inc; } } void ic_stretch( int type, Byte * srcData, int srcW, int srcH, Byte * dstData, int w, int h, Bool xStretch, Bool yStretch) { int absh = h < 0 ? -h : h; int absw = w < 0 ? -w : w; int srcLine = (( srcW * ( type & imBPP) + 31) / 32) * 4; int dstLine = (( absw * ( type & imBPP) + 31) / 32) * 4; Fixed xstep, ystep, count; int last = 0; int i; int yMin = ( srcH > absh) ? absh : srcH; PStretchProc proc = ( PStretchProc) nil; Byte *srcLast = nil; if ( w == srcW) xStretch = false; if ( h == srcH) yStretch = false; /* transfer case */ if ( !xStretch && !yStretch && ( w > 0)) { int y; int xMin = (( type & imBPP) < 8) ? ( srcLine > dstLine) ? dstLine : srcLine : (((( srcW > absw) ? absw : srcW) * ( type & imBPP)) / 8); if ( srcW < w || srcH < absh) memset( dstData, 0, dstLine * absh); if ( h < 0) { dstData += dstLine * ( yMin - 1); dstLine =- dstLine; } for ( y = 0; y < yMin; y++, srcData += srcLine, dstData += dstLine) memcpy( dstData, srcData, xMin); return; } /* y-only stretch case */ if ( !xStretch && yStretch && ( w > 0)) { int xMin = (( type & imBPP) < 8) ? ( srcLine > dstLine) ? dstLine : srcLine : (((( srcW > absw) ? absw : srcW) * ( type & imBPP)) / 8); count. l = 0; if ( srcW < w) memset( dstData, 0, dstLine * absh); if ( h < 0) { dstData += dstLine * ( absh - 1); dstLine =- dstLine; } if ( absh < srcH) { ystep. l = (double) absh / srcH * UINT16_PRECISION; memcpy( dstData, srcData, xMin); dstData += dstLine; for ( i = 0; i < srcH; i++) { if ( count. i.i > last) { memcpy( dstData, srcData, xMin); dstData += dstLine; last = count.i.i; } count. l += ystep. l; srcData += srcLine; } } else { ystep. l = (double) srcH / absh * UINT16_PRECISION; for ( i = 0; i < absh; i++) { if ( count.i.i > last) { srcData += srcLine; last = count.i.i; } count. l += ystep. l; memcpy( dstData, srcData, xMin); dstData += dstLine; } } return; } /* general actions for x-scaling */ count. l = 0; count. l = 0; if ( srcW < absw || srcH < absh || ( type & imBPP) == imNibble) memset( dstData, 0, dstLine * absh); if ( absw < srcW) xstep. l = (double) absw / srcW * UINT16_PRECISION; else xstep. l = (double) srcW / absw * UINT16_PRECISION; switch( type) { case imMono: case imBW: proc = ( PStretchProc)(( srcW > absw) ? bs_mono_in : bs_mono_out); break; case imNibble: case imNibble|imGrayScale: proc = ( PStretchProc)(( srcW > absw) ? bs_nibble_in : bs_nibble_out); break; case imByte: case im256: proc = ( PStretchProc)(( srcW > absw) ? bs_uint8_t_in : bs_uint8_t_out); break; case imRGB: case imRGB|imGrayScale: proc = ( PStretchProc)(( srcW > absw) ? bs_RGBColor_in : bs_RGBColor_out); break; case imShort: proc = ( PStretchProc)(( srcW > absw) ? bs_int16_t_in : bs_int16_t_out); break; case imLong: proc = ( PStretchProc)(( srcW > absw) ? bs_int32_t_in : bs_int32_t_out); break; case imFloat: proc = ( PStretchProc)(( srcW > absw) ? bs_float_in : bs_float_out); break; case imDouble: proc = ( PStretchProc)(( srcW > absw) ? bs_double_in : bs_double_out); break; case imComplex: case imTrigComplex: proc = ( PStretchProc)(( srcW > absw) ? bs_Complex_in : bs_Complex_out); break; case imDComplex: case imTrigDComplex: proc = ( PStretchProc)(( srcW > absw) ? bs_DComplex_in : bs_DComplex_out); break; default: return; } /* no vertical stretch case */ if ( !yStretch || ( srcH == -h)) { if ( h < 0) { dstData += dstLine * ( yMin - 1); dstLine =- dstLine; } for ( i = 0; i < srcH; i++, srcData += srcLine, dstData += dstLine) proc( srcData, dstData, srcW, w, absw, xstep.l); return; } /* general case */ if ( h < 0) { dstData += dstLine * ( absh - 1); dstLine =- dstLine; } if ( absh < srcH) { ystep. l = (double) absh / srcH * UINT16_PRECISION; proc( srcData, dstData, srcW, w, absw, xstep.l); dstData += dstLine; for ( i = 0; i < srcH; i++) { if ( count. i.i > last) { proc( srcData, dstData, srcW, w, absw, xstep.l); dstData += dstLine; last = count.i.i; } count. l += ystep. l; srcData += srcLine; } } else { ystep. l = (double) srcH / absh * UINT16_PRECISION; for ( i = 0; i < absh; i++) { if ( count.i.i > last) { srcData += srcLine; last = count.i.i; } count. l += ystep. l; if ( srcLast == srcData) { memcpy( dstData, dstData - dstLine, dstLine < 0 ? -dstLine : dstLine); } else { proc( srcData, dstData, srcW, w, absw, xstep.l); srcLast = srcData; } dstData += dstLine; } } } #ifdef __cplusplus } #endif