Win32 C Function for High-Quality Bitmap Shrinking

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Therefore, I wrote my own function (ShrinkBitmap) to give me the ability to shink and expand images in my own application,
yet do so with the same quality I would expect from a graphics package. Take a look at the following table of images
and you’ll see first a large image (the original) and then a comparison of images that have been shrunk using
the StretchBlt function, my ShrinkBitmap function and the an Adobe Photoshop conversion. As you can see, ShrinkBitmap
gives you Adobo Photoshop bitmap shrinking capabilities from within your own application.







This is me in original size and I’m going to shrink myself















Resolution StretchBlt My function Adobe Photoshop
105 × 150
35 × 50

Source Code

Place these macros into the beginning of your program:

#define Alloc(p,t) (t *)malloc((p)*sizeof(t))
#define For(i,n) for ((i)=0;(i)<(n);(i)++)
#define iFor(n) For (i,n)
#define jFor(n) For (j,n)

And also this type-definition:

typedef struct {
 WORD x,y;  // dimensions
 WORD l;    // bytes per scan-line (32-bit allignment)
 BYTE *b;   // bits of bitmap,3 bytes/pixel, BGR
} tWorkBMP;  // 24-bit working bitmap

The functions also require the header file for memory allocation, or you can rewrite them to use keywords new and delete.

#include <malloc.h>

Here’s the actual ShrinkBitmap function


HBITMAP ShrinkBitmap (HBITMAP a,WORD bx,WORD by)
// creates and returns new bitmap with dimensions of
// [bx,by] by shrinking bitmap a both [bx,by] must be less or equal
// than the dims of a, unless the result is nonsense
{
tWorkBMP in,out;
HBITMAP b=CreateEmptyBitmap(bx,by);
OpenBitmapForWork (a,&in);
ShrinkWorkingBitmap (&in,&out,bx,by);
free (in.b);
SaveWorkingBitmap (&out,b);
free (out.b);
return (b);
}

The following functions are just supporting and I recommend treating them in
“black box” fashion. But you have to place them in front of the ShrinkBitmap function
or forward declare them.

void CreateWorkingBitmap (WORD dx,WORD dy,tWorkBMP *w)
{
w->x=dx;
w->y=dy;
w->l=(dx+1)*3&0xfffc;
w->b=Alloc(w->l*dy,BYTE);
}

HBITMAP CreateEmptyBitmap (WORD dx,WORD dy)
{
HDC h=GetDC(NULL);
HBITMAP b=CreateCompatibleBitmap(h,dx,dy);
ReleaseDC (NULL,h);

return (b);
}

void SetBMIHeader (BITMAPINFO *b,short dx,short dy)
{
b->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
b->bmiHeader.biWidth=dx;
b->bmiHeader.biHeight=-dy;
b->bmiHeader.biPlanes=1;
b->bmiHeader.biBitCount=24;
b->bmiHeader.biCompression=BI_RGB;
b->bmiHeader.biSizeImage=0;
b->bmiHeader.biXPelsPerMeter=1;
b->bmiHeader.biYPelsPerMeter=1;
b->bmiHeader.biClrUsed=0;
b->bmiHeader.biClrImportant=0;
}

void SaveWorkingBitmap (tWorkBMP *w,HBITMAP b)
{
BITMAPINFO s;
HDC h=GetDC(NULL);
SetBMIHeader (&s,w->x,w->y);
SetDIBits (h,b,0,w->y,w->b,&s,DIB_RGB_COLORS);
ReleaseDC (NULL,h);
}

void ShrinkWorkingBitmap (tWorkBMP *a,tWorkBMP *b,WORD bx,WORD by)
{
BYTE *uy=a->b,*ux,i;
WORD x,y,nx,ny=0;
DWORD df=3*bx,nf=df*by,j;
float k,qx[2],qy[2],q[4],*f=Alloc(nf,float);

CreateWorkingBitmap (bx,by,b);

jFor (nf) f[j]=0;
j=0;

For (y,a->y) {
ux=uy;
uy+=a->l;
nx=0;
ny+=by;

if (ny>a->y) {

qy[0]=1-(qy[1]=(ny-a->y)/(float)by);

For (x,a->x) {

nx+=bx;

if (nx>a->x) {
qx[0]=1-(qx[1]=(nx-a->x)/(float)bx);

iFor (4) q[i]=qx[i&1]*qy[i>>1];

iFor (3) {
f[j]+=(*ux)*q[0];
f[j+3]+=(*ux)*q[1];
f[j+df]+=(*ux)*q[2];
f[(j++)+df+3]+=(*(ux++))*q[3];
}
}
else iFor (3) {
f[j+i]+=(*ux)*qy[0];
f[j+df+i]+=(*(ux++))*qy[1];
}
if (nx>=a->x) nx-=a->x;
if (!nx) j+=3;
}
}
else {
For (x,a->x) {

nx+=bx;

if (nx>a->x) {
qx[0]=1-(qx[1]=(nx-a->x)/(float)bx);
iFor (3) {
f[j]+=(*ux)*qx[0];
f[(j++)+3]+=(*(ux++))*qx[1];
}
}
else iFor (3) f[j+i]+=*(ux++);

if (nx>=a->x) nx-=a->x;
if (!nx) j+=3;
}
if (ny<a->y) j-=df;
}
if (ny>=a->y) ny-=a->y;
}

nf=0;
k=bx*by/(float)(a->x*a->y);
uy=b->b;

For (y,by) {
jFor (df) uy[j]=f[nf++]*k+.5;
uy+=b->l;
}

free (f);
}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read