Click here to Skip to main content
Click here to Skip to main content

A simple method to display a transparent PNG file

, 8 Sep 2008
Rate this:
Please Sign up or sign in to vote.
Introducing a simple method to display a transparent PNG file.

Screenshot - snapshot.gif

Introduction

If you are searching for a component to display a PNG32 image, this code may give you some tips.

Background

Some days ago, I needed a component to display a transparent PNG image in my code. Searching with the keyword "PNG" in CodeProject, I found a demo named PNGView. But, it does not deal with transparent PNGs. So I decided to do it on my own.

The basic idea is to simulate AlplaBlend's behavior, see the following code. In order to fasten the speed of display, the code's core part is optimized by using ASM. I am not very good at ASM, so if there are any shortcomings or bugs in my code, please let me know.

Hope this helps. Thanks for your attention!

Using the code

I have wrapped the code to a static library. The download includes a demo and the static library's source code.

In order to use this code, you should import the lib first, and then you can display a PNG32 image in just three steps.

Step 1: Load a PNG32 image

In order to simplify the code, I only support 32 pixel depth PNG images.

char szFileName[MAX_PATH];
strcpy(szFileName,"*.png")
PNGINFO *pPng=Png32_Load(szFileName);
Step 2: Display the image in a HDC
Png32_Show(pDC->m_hDC,0,0,pPng->nWidth,pPng->nHeight,pPng,0,0);
Step 3: Free the occupied memory
Png32_Free(pPng);

The code

//display a 32 bit deep png image
void Png32_Show(HDC hdc,int xDest,int yDest,int nWidth,int nHeight,
       PNGINFO *pPngInfo,int xSour,int ySour)
{
 if(xSour+nWidth>(int)pPngInfo->nWidth) nWidth=pPngInfo->nWidth-xSour;
 if(ySour+nHeight>(int)pPngInfo->nHeight) nHeight=pPngInfo->nHeight-ySour;
 if(nWidth>0 && nHeight>0)
 {
 HDC hmemdc=0;
 LPBYTE pBitsDest=NULL;
 HBITMAP hbmpDest=0;
 HGDIOBJ hOldBmp=0;
 BITMAPINFO bmi;
 //sour memory
 unsigned char ** row_pointers = 
   pPngInfo->ppbyRow+pPngInfo->nHeight-1-(pPngInfo->nHeight-ySour-nHeight);
 //Do alpla blend
 int nLineTailDest=WIDTHBYTES(24*nWidth)-3*nWidth;
 // Initialize header to 0s.
 ZeroMemory(&bmi, sizeof(bmi));
 // Fill out the fields you care about.
 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 bmi.bmiHeader.biWidth = nWidth;
 bmi.bmiHeader.biHeight = nHeight;
 bmi.bmiHeader.biPlanes = 1;
 bmi.bmiHeader.biBitCount = 24;
 bmi.bmiHeader.biCompression = BI_RGB;
 // Create the surface.
 hmemdc=CreateCompatibleDC(hdc);
 // Get Dest Rectangle memory
 hbmpDest = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, 
            (void **)&pBitsDest, NULL, 0);
 hOldBmp=SelectObject(hmemdc,hbmpDest);
 BitBlt(hmemdc,0,0,nWidth,nHeight,hdc,xDest,yDest,SRCCOPY);
#ifdef ASM_CORE
 __asm
 {
  push esi
  push edi
  push eax
  push ebx
  push ecx
  push edx
  push es
  push ds
  
  mov ax,ds
  mov es,ax
  mov edi,pBitsDest
  mov ecx,nHeight
beginy:
  mov ebx, row_pointers
  mov esi,[ebx]
  ;//offset picture's left margin
  mov eax,xSour
  imul eax,4  ;//4 bytes make up one pixel
  add esi,eax 
  mov eax,nWidth  
beginx:
   ;//get alpla value
   xor ebx,ebx
   mov bl,[esi+3] 
  
   ;//blue
   xor dx,dx
   mov dl,[edi];
   imul dx,bx
   add dh,[esi+2]
   mov [edi],dh ;//save result to *pBitsDest
   inc edi
   ;//green
   xor dx,dx
   mov dl,[edi];
   imul dx,bx
   add dh,[esi+1]
   mov [edi],dh ;//save result to *pBitsDest
   inc edi
   ;//red
   xor dx,dx
   mov dl,[edi];
   imul dx,bx
   add dh,[esi]
   mov [edi],dh ;//save result to *pBitsDest
   inc edi
   add esi,4
   
   dec eax
   cmp eax,0
   jne beginx
  add edi,nLineTailDest
  sub row_pointers,4 ;//next line
  loop beginy
  pop ds
  pop es
  pop edx
  pop ecx
  pop ebx
  pop eax
  pop edi
  pop esi
 } 
#else//ASM_CORE
 {
  int i,j;
  BYTE *p1=pBitsDest;
  for(i=0;i<nHeight;i++)
  {
   BYTE *p2=*(row_pointers--);
   for(j=0;j<nWidth;j++)
   {
    *p1++=((p2[3]*(*p1))>>8)+p2[2];
    *p1++=((p2[3]*(*p1))>>8)+p2[1];
    *p1++=((p2[3]*(*p1))>>8)+p2[0];
    p2+=4;
   }
   p1+=nLineTailDest;
  }
 }
#endif//ASM_CORE
 //render
 BitBlt(hdc,xDest,yDest,nWidth,nHeight,hmemdc,0,0,SRCCOPY);
 SelectObject(hmemdc,hOldBmp);
 //Free memory
 DeleteObject(hbmpDest);
 DeleteDC(hmemdc);
 }
}

Remark

The new version has a new interface, Png32_LoadFromMem, with which you can easily load a 32 bit PNG image form memory. See CMfc_demoDlg::OnInitDialog for an example.

To test this domo, you should compile the png32_helper project first, and then compile mfc_demo.

History

  • 2008-04-17

    Add the Png32_LoadFromMem interface.

  • 2007-09-07

    Did pixel pre-multiplication.

  • 2007-07-16

    First submission.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

flyhigh
Software Developer (Senior)
China China
No Biography provided

Comments and Discussions

 
Questionbuild with mfc static lib Pinmemberimlamlam3-Oct-13 22:15 
GeneralBig problem [modified] Pinmemberlrtsenar20-Apr-09 3:15 
GeneralRe: Big problem Pinmemberflyhigh20-Apr-09 14:46 
GeneralCompile problem PinmemberLuiCifer10-Nov-08 23:00 
GeneralRe: Compile problem Pinmemberflyhigh11-Nov-08 14:11 
GeneralRe: Compile problem PinmemberLuiCifer22-Nov-08 2:51 
GeneralRe: Compile problem Pinmemberflyhigh22-Nov-08 18:18 
GeneralProblem in Windows 98 Pinmemberharishdobhal9-Oct-08 19:50 
GeneralRe: Problem in Windows 98 Pinmemberflyhigh11-Oct-08 1:29 
GeneralRe: Problem in Windows 98 Pinmemberharishdobhal11-Oct-08 3:30 
GeneralRe: Problem in Windows 98 Pinmemberflyhigh11-Oct-08 16:03 
GeneralRe: Problem in Windows 98 Pinmemberharishdobhal11-Oct-08 19:49 
GeneralRe: Problem in Windows 98 Pinmemberflyhigh11-Oct-08 23:01 
GeneralRe: Problem in Windows 98 Pinmemberharishdobhal12-Oct-08 20:14 
GeneralAgain the problem Pinmemberharishdobhal6-Oct-08 23:46 
GeneralRe: Again the problem Pinmemberflyhigh7-Oct-08 15:02 
GeneralRe: Again the problem Pinmemberharishdobhal13-Oct-08 0:44 
GeneralRe: Again the problem Pinmemberflyhigh13-Oct-08 14:58 
GeneralRe: Again the problem Pinmemberharishdobhal22-Oct-08 0:33 
GeneralRe: Again the problem Pinmemberflyhigh25-Oct-08 2:20 
GeneralRe: Again the problem Pinmemberharishdobhal3-Nov-08 19:06 
QuestionAdvantage/benchmarks of ASM vs AlphaBlend? 64-bit? PinmemberLeo Davidson9-Sep-08 20:59 
AnswerRe: Advantage/benchmarks of ASM vs AlphaBlend? 64-bit? Pinmemberflyhigh9-Sep-08 22:05 
GeneralPng32_MakeRgn Problem Pinmemberharishdobhal30-Apr-08 6:45 
GeneralRe: Png32_MakeRgn Problem Pinmemberflyhigh30-Apr-08 20:33 
GeneralRe: Png32_MakeRgn Problem Pinmemberharishdobhal1-May-08 21:55 
GeneralRe: Png32_MakeRgn Problem Pinmemberflyhigh1-May-08 22:46 
GeneralRe: Png32_MakeRgn Problem Pinmemberharishdobhal4-May-08 21:46 
GeneralRe: Png32_MakeRgn Problem Pinmemberflyhigh5-May-08 14:35 
Questionpng32_helper.lib ?? PinmemberPrepusMaster5-Apr-08 5:12 
GeneralRe: png32_helper.lib ?? Pinmemberflyhigh5-Apr-08 15:23 
Generalerror LNK2019.... PinmemberConserLin11-Dec-07 22:14 
QuestionIs it possible display a transparent png file from resource file? [modified] Pinmemberjiangjkd13-Sep-07 16:31 
AnswerRe: Is it possible display a transparent png file from resource file? Pinmemberflyhigh19-Sep-07 1:04 
QuestionRe: Is it possible display a transparent png file from resource file? PinmemberRunFer30-Nov-07 8:58 
GeneralRe: Is it possible display a transparent png file from resource file? Pinmemberharishdobhal16-Apr-08 2:28 
GeneralRe: Is it possible display a transparent png file from resource file? Pinmemberflyhigh16-Apr-08 17:04 
GeneralRe: Is it possible display a transparent png file from resource file? Pinmemberflyhigh16-Apr-08 17:03 
GeneralRe: Is it possible display a transparent png file from resource file? Pinmemberharishdobhal17-Apr-08 8:49 
GeneralOptimization PinmemberTeashirt28-Sep-07 16:27 
GeneralRe: Optimization Pinmembermbue9-Sep-07 6:01 
GeneralRe: Optimization Pinmemberflyhigh9-Sep-07 22:23 
GeneralRe: Optimization PinmemberLeo Davidson9-Sep-08 21:01 
GeneralRe: Optimization Pinmemberflyhigh9-Sep-07 22:19 
QuestionIs it possible on controls (eg. buttons) also? Pinmemberbabyc++7-Sep-07 19:38 
AnswerRe: Is it possible on controls (eg. buttons) also? Pinmemberflyhigh7-Sep-07 20:42 
GeneralRe: Is it possible on controls (eg. buttons) also? Pinmemberharishdobhal17-Apr-08 8:57 
GeneralRe: Is it possible on controls (eg. buttons) also? Pinmemberflyhigh17-Apr-08 19:09 
GeneralRe: Is it possible on controls (eg. buttons) also? Pinmemberharishdobhal30-Apr-08 6:20 
GeneralRe: Is it possible on controls (eg. buttons) also? Pinmemberflyhigh30-Apr-08 20:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 9 Sep 2008
Article Copyright 2007 by flyhigh
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid