📄 imageresample.cpp
字号:
#include "ImageResample.h"
ImageResample::ImageResample() :
m_buffer( 0 )
{
}
ImageResample::~ImageResample()
{
deinit();
}
void ImageResample::init( int bufferSize )
{
m_buffer.resize( bufferSize );
}
void ImageResample::deinit()
{
m_buffer.clear();
}
uint8_t* ImageResample::getBuffer()
{
return m_buffer.begin();
}
uint8_t* ImageResample::getBuffer( int size )
{
if ( m_buffer.size() < size )
{
m_buffer.resize( size );
}
return m_buffer.begin();
}
void ImageResample::resampleHalf( uint8_t* dst,
const int width, const int height, const int pitch,
const int /*sourceWidth*/, const int sourceHeight, const int sourcePitch,
const uint16_t* palette, const int paletteEntryCount,
int sourceFrameHeight )
{
assert( ( sourcePitch * sourceHeight ) <= m_buffer.size() );
resampleHalf( dst, m_buffer.begin(),
width, height, pitch,
-1, sourceHeight, sourcePitch,
palette, paletteEntryCount,
sourceFrameHeight );
}
void ImageResample::resampleHalf( uint8_t* dst, const uint8_t* src,
const int width, const int height, const int pitch,
const int /*sourceWidth*/, const int sourceHeight, const int sourcePitch,
const uint16_t* palette, const int paletteEntryCount,
int sourceFrameHeight )
{
// Resample half x half
//- Assumes A4R4G4B4 format
//- If the data is palettized, the palette must be 8-bit
//- The source data size must be 200% of the destination data size
int sd00, sd01, sd10, sd11;
int alpha, red, green, blue;
int a, f;
int pAlpha, pRed, pGreen, pBlue;
int alphaDist, redDist, greenDist, blueDist;
int colorDistSqr, minColorDistSqr;
int si = 0, di = 0;
int nearestEntry;
int sourceLineWidth = sourcePitch;
int lineWidth = pitch;
if ( !palette )
{
//2 bytes per pixel
sourceLineWidth >>= 1;
lineWidth >>= 1;
}
bool cropFrames = ( ( sourceFrameHeight > 0 ) && ( ( sourceFrameHeight & 1 ) != 0 ) ); //Odd frame height in source => crop
if ( sourceFrameHeight < 1 ) sourceFrameHeight = sourceHeight;
int frameHeight = sourceFrameHeight >> 1;
for ( int dsty = 0; dsty < height; dsty++ )
{
for ( int dstx = 0; dstx < width; dstx++ )
{
//Get the average color of the resampling area
//-------
if ( palette )
{
sd00 = palette[ src[ si ] ];
sd10 = palette[ src[ si + 1 ] ];
sd01 = palette[ src[ si + sourceLineWidth ] ];
sd11 = palette[ src[ si + sourceLineWidth + 1 ] ];
}
else
{
sd00 = ((uint16_t*) src)[ si ];
sd10 = ((uint16_t*) src)[ si + 1 ];
sd01 = ((uint16_t*) src)[ si + sourceLineWidth ];
sd11 = ((uint16_t*) src)[ si + sourceLineWidth + 1 ];
}
//-------
a = ( sd00 >> 12 ) & 0xF;
red = ( ( sd00 >> 8 ) & 0xF ) * a;
green = ( ( sd00 >> 4 ) & 0xF ) * a;
blue = ( sd00 & 0xF ) * a;
alpha = a;
a = ( sd10 >> 12 ) & 0xF;
red += ( ( sd10 >> 8 ) & 0xF ) * a;
green += ( ( sd10 >> 4 ) & 0xF ) * a;
blue += ( sd10 & 0xF ) * a;
alpha += a;
a = ( sd01 >> 12 ) & 0xF;
red += ( ( sd01 >> 8 ) & 0xF ) * a;
green += ( ( sd01 >> 4 ) & 0xF ) * a;
blue += ( sd01 & 0xF ) * a;
alpha += a;
a = ( sd11 >> 12 ) & 0xF;
red += ( ( sd11 >> 8 ) & 0xF ) * a;
green += ( ( sd11 >> 4 ) & 0xF ) * a;
blue += ( sd11 & 0xF ) * a;
alpha += a;
if ( alpha > 0 )
{
//Fixed point multiplication by 1 / x (with rounding)
f = ( 1 << 16 ) / alpha;
red = ( red * f + ( 1 << 15 ) + 64 ) >> 16;
green = ( green * f + ( 1 << 15 ) + 64 ) >> 16;
blue = ( blue * f + ( 1 << 15 ) + 64 ) >> 16;
}
else
{
red = 0;
green = 0;
blue = 0;
}
alpha >>= 2;
if ( palette )
{
//Find the nearest color in the palette
minColorDistSqr = -1;
nearestEntry = -1;
for ( int entry = 0; entry < paletteEntryCount; entry++ )
{
pAlpha = ( palette[ entry ] >> 12 ) & 0xF;
if ( pAlpha > 0 )
{
pRed = ( palette[ entry ] >> 8 ) & 0xF;
pGreen = ( palette[ entry ] >> 4 ) & 0xF;
pBlue = palette[ entry ] & 0xF;
}
else
{
//Full transparency: remove the significance of color
pAlpha = 0;
pRed = 0;
pGreen = 0;
pBlue = 0;
}
alphaDist = pAlpha - alpha;
redDist = pRed - red;
greenDist = pGreen - green;
blueDist = pBlue - blue;
colorDistSqr = alphaDist * alphaDist;
colorDistSqr += redDist * redDist + greenDist * greenDist + blueDist * blueDist;
if ( ( minColorDistSqr < 0 ) || ( colorDistSqr < minColorDistSqr ) )
{
minColorDistSqr = colorDistSqr;
nearestEntry = entry;
}
}
//Store
dst[ di ] = (uint8_t) nearestEntry;
}
else
{
//Store
((uint16_t*) dst)[ di ] = (uint16_t) ( ( ( alpha & 0xF ) << 12 ) + ( ( red & 0xF ) << 8 ) + ( ( green & 0xF ) << 4 ) + ( blue & 0xF ) );
}
//Advance
si += 2;
di++;
}
//Next scan line
si += ( sourceLineWidth << 1 ) - ( width << 1 );
di += lineWidth - width;
if ( cropFrames && ( ( ( dsty + 1 ) % frameHeight ) == 0 ) )
{
//The last odd line of a source frame must be cropped to maintain frames in resize
si += sourceLineWidth;
}
}
}
// End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -