I want a fast image scale(zoom) function in my real-time image processing project.

I know there is a algorithm called Bilinear Interpolation Algorithm, can anyone provide a implementation that runs fast

thanks!
Posted on 2003-09-15 21:33:29 by lovelypp
Here's one that a friend of mine did.. It uses C++ and inline asm with mmx and I have no idea how fast it actually is, but he usually produces quite fast code. You could probably optimize it a lot if you put in some prefetching stuff...
void MTImage::ResizeTo( MTImage *pDestImg )

{
int dx = (m_nWidth << 16) / pDestImg->m_nWidth;
int dy = (m_nHeight << 16) / pDestImg->m_nHeight;
int pixels = (m_nWidth*m_nHeight) - 1;

int startx = 0;
int starty = 0;

int ccy = starty;
DWORD *target = pDestImg->GetPtr();
DWORD *text = m_pData;

for( int yy=0; yy<pDestImg->m_nHeight; yy++ )
{
int ty = (ccy >> 16) * m_nWidth;
int ccx = startx;
DWORD *tar = target;

__int64 ddv = ((ccy) >> 8) & 255;
ddv += (ddv << 32) + (ddv << 16);

for( int xx=0; xx<pDestImg->m_nWidth; xx++ )
{
int ad1 = ty + (ccx >> 16);
int ad2 = ad1 + 1;
int ad3 = ad1 + m_nWidth;
int ad4 = ad2 + m_nWidth;

__asm
{
// for packing/unpacking
pxor mm7, mm7
mov eax, [ccx]
shr eax, 8
and eax, 255
movd mm4, eax
movq mm5, mm4
psllq mm5, 16
paddd mm4, mm5
psllq mm5, 16
// convert ddu to 64 bit
paddd mm4, mm5

mov edx, [pixels]
mov eax, [ad1]
cmp eax, edx
jl noclipad1
mov eax, edx

noclipad1:
mov ebx, [ad2]
cmp ebx, edx
jl noclipad2
mov ebx, edx

noclipad2:
mov ecx, [ad3]
cmp ecx, edx
jl noclipad3
mov ecx, edx

noclipad3:
mov edx, [ad4]
cmp edx, [pixels]
jl noclipad4
mov edx, [pixels]

noclipad4:
mov esi, [text]

///////////////////////////////////////////////////////

// mm5 = color1 + (ddu * (color2 - color1));
movd mm5, [esi + eax * 4] // color1
movd mm1, [esi + ebx * 4] // color2

punpcklbw mm5, mm7 // convert to 64 bit
punpcklbw mm1, mm7 // convert to 64 bit

movq mm3, mm5 // save color1 for later

pmullw mm1, mm4 // mul color2 with ddu(mm4)
psrlw mm1, 8 // div by 256
paddb mm5, mm1 // add to color1

pmullw mm3, mm4 // mul color1 with ddu(mm4)
psrlw mm3, 8 // div by 256
psubb mm5, mm3 // sub from color1...

///////////////////////////////////////////////////////

// mm6 = color3 + (ddu * (color4 - color3));
movd mm6, [esi + ecx * 4] // color3
movd mm1, [esi + edx * 4] // color4

punpcklbw mm6, mm7 // convert to 64 bit
punpcklbw mm1, mm7 // convert to 64 bit

movq mm3, mm6 // save color3 for later

pmullw mm1, mm4 // mul color4 with ddu
psrlw mm1, 8 // div by 256
paddb mm6, mm1 // add to color3

pmullw mm3, mm4 // mul color3 with ddu(mm4)
psrlw mm3, 8 // div by 256
psubb mm6, mm3 // sub from color3...

//////////////////////////////////////////////////////

movq mm4, [ddv]

movq mm3, mm5

pmullw mm6, mm4
psrlw mm6, 8
paddb mm5, mm6

pmullw mm3, mm4
psrlw mm3, 8
psubb mm5, mm3

packuswb mm5, mm7

mov esi, [tar]
movd [esi], mm5 // done!

add tar, 4
}
ccx += dx;
}
ccy += dy;
target += pDestImg->m_nWidth;
}
__asm emms;
}

edit: I just saw that some comments don't make sense. I directly translated his comments into english so don't blame the messenger ;)
Posted on 2003-10-06 07:52:44 by snq
it is used for a 32bit data buf, but in my project, i usually us 8bit grayscale image or 24bit rgb colorful image.

how to change it so it can be apply to a 24bit or 8bit image?

I'am a newie, help please.
Posted on 2003-10-12 23:28:54 by lovelypp