Win32 C Function for High-Quality Bitmap Shrinking

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



Comments

  • Seems brilliant

    Posted by Ali Imran on 04/01/2007 12:22pm

    This really resizes images perfectly. I hope I can use it in a commercial project, since code has already been publically available. regards

    Reply
  • black and white images

    Posted by Legacy on 10/21/2003 12:00am

    Originally posted by: Tony Tohme

    This seems to work on 24 bit type images, but what if I have a black and white image, when I tried to set the bitcount to 1 in your struct it failed.

    ANyone knows what to do if the image is B/W.
    Thanks

    Reply
  • brief required

    Posted by Legacy on 11/27/2002 12:00am

    Originally posted by: meghana

    going through the code without knowing the algorithm is difficult. can u provide a brief of the algorithm used in the shrinking of image

    Reply
  • thanks

    Posted by Legacy on 11/14/2002 12:00am

    Originally posted by: uri ben manachem

    thanks
    nice to see good programming after messing with windows

    Reply
  • The missing function OpenBitmapForWork

    Posted by Legacy on 08/18/2002 12:00am

    Originally posted by: Peter O.

    // -- start cutting here

    POINT GetBitmapSize (HBITMAP h)
    {
    POINT p;
    BITMAP o;
    GetObject (h,sizeof(o),&o);
    p.x=o.bmWidth;
    p.y=o.bmHeight;
    return (p);
    }

    void OpenBitmapForWork (HBITMAP b,tWorkBMP *w)
    {
    BITMAPINFO s;
    HDC h=GetDC(NULL);
    POINT v=GetBitmapSize(b);
    CreateWorkingBitmap (v.x,v.y,w);
    SetBMIHeader (&s,w->x,w->y);
    GetDIBits (h,b,0,w->y,w->b,&s,DIB_RGB_COLORS);
    ReleaseDC (NULL,h);
    }

    // -- stop cutting here

    The homepage link is no longer valid.

    Reply
  • antialiasing problem

    Posted by Legacy on 04/10/2002 12:00am

    Originally posted by: yuval gross

    does anybody know how to remove the antialiasing from a given bitmap??

    If I mask out the background of a bitmap (say in white)
    and remain with the foreground image which still has the antialiasing pixels - is there a way to get rid of these pixels??

    does anybody know a function or an algorithm to do so?

    Reply
  • How can I save BITMAP in a DataBase

    Posted by Legacy on 02/25/2002 12:00am

    Originally posted by: Macky

    Hello,

    I'm looking for a way to save and extract BITMAP Files in a database.

    I don't know what I can do. May I use an ActiveX or my own code for date.
    And how to speficy a member variable that support BITMAP.

    I need your help.

    Thanks a lot.

    Macky

    Reply
  • How do i convert .bmp files into .jpg file using VC++ code

    Posted by Legacy on 02/04/2002 12:00am

    Originally posted by: Rambhavan Verma

    Dear sir,
    this is rambhavan verma here.
    Please try to give me some suggestions/solutions on the above mentioned page title.
    I have to do one project on the above mentioned topic.If you can help me then try to send me some code or any suggestions on the respective topic.
    Thanking you,
    Rambhavan Verma.

    Reply
  • What about OpenBitmapForWork ?????

    Posted by Legacy on 12/26/2001 12:00am

    Originally posted by: Espinoza

    Hey Dude, what about OpenBitmapForWork ???

    Reply
  • StretchBlt() can do the same image quality but faster!!!

    Posted by Legacy on 08/06/2001 12:00am

    Originally posted by: David King

    If you use SetStretchBltMode(HALFTONE) before calling StretchBlt() then you will have the same image quality as Adobe Photoshop.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date