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);

__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
psllq   mm5, 16
// convert ddu to 64 bit

mov     edx, [pixels]
cmp     eax, edx
mov     eax, edx

cmp     ebx, edx
mov     ebx, edx

cmp     ecx, edx
mov     ecx, edx

cmp     edx, [pixels]
mov     edx, [pixels]

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

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

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

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

packuswb mm5, mm7

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

}
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?