Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

icon.cpp

Go to the documentation of this file.
00001 /* $Id: icon.cpp,v 1.14 2002/01/07 11:17:52 sandervl Exp $ */
00002 
00003 /*
00004  * Win32 icon conversion functions for OS/2
00005  *
00006  * Copyright 1998 Sander van Leeuwen
00007  *
00008  *
00009  * Project Odin Software License can be found in LICENSE.TXT
00010  *
00011  */
00012 #define INCL_GPIBITMAPS
00013 #define INCL_BITMAPFILEFORMAT
00014 #define INCL_DOSFILEMGR          /* File Manager values      */
00015 #define INCL_DOSERRORS           /* DOS Error values         */
00016 #define INCL_DOSPROCESS          /* DOS Process values       */
00017 #define INCL_DOSMISC             /* DOS Miscellanous values  */
00018 #define INCL_WIN
00019 #include <os2wrap.h>    //Odin32 OS/2 api wrappers
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include <stdlib.h>
00023 #include <iostream.h>
00024 #include <string.h>
00025 
00026 #include <win32api.h>
00027 #include <win32type.h>
00028 #include "dib.h"
00029 #include <winicon.h>
00030 #include <misc.h>
00031 
00032 #define DBG_LOCALLOG    DBG_icon
00033 #include "dbglocal.h"
00034 
00035 #define DIB_RGB_COLORS_W   0
00036 #define DIB_PAL_COLORS_W   1
00037 #define CBM_INIT_W         4
00038 
00039 
00040 //******************************************************************************
00041 //******************************************************************************
00042 ULONG QueryConvertedIconSize(WINBITMAPINFOHEADER *bmpHdr, int size, BOOL fResizeTo40x40 = FALSE)
00043 {
00044  int bwsize, colorsize, rgbsize, iconsize;
00045 
00046   if(fResizeTo40x40) {
00047       bwsize    = DIB_GetDIBImageBytes(40, 40, 1);
00048       colorsize = DIB_GetDIBImageBytes(40, 40, bmpHdr->biBitCount);
00049   }
00050   else {
00051       bwsize    = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), 1);
00052       colorsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), bmpHdr->biBitCount);
00053   }
00054 
00055   if(bmpHdr->biBitCount <= 8)
00056         rgbsize = (1<<bmpHdr->biBitCount)*sizeof(RGB2);
00057   else  rgbsize = 0;
00058 
00059   if(bmpHdr->biSizeImage == 0 && bmpHdr->biCompression == 0) {
00060         bmpHdr->biSizeImage = bwsize + colorsize;
00061   }
00062 
00063   //SvL: 28-09-'98: cllngenu.dll has an incorrect size in the header
00064   if(bmpHdr->biSizeImage < colorsize) {
00065         bmpHdr->biSizeImage = colorsize;
00066   }
00067   //bitmapfileheader for AndXor mask + 2 RGB structs + bitmapfileheader
00068   //for color bitmap + RGB structs for all the colors
00069   //SvL, 3-3-98: 2*bwsize
00070   iconsize = 2*sizeof(BITMAPFILEHEADER2) + 2*sizeof(RGB2) +
00071              rgbsize + 2*bwsize + colorsize;
00072 
00073   return iconsize;
00074 }
00075 //******************************************************************************
00076 //NOTE: offsetBits is the value added to the offBits bitmap structure members
00077 //      (handy for converting icon groups)
00078 //******************************************************************************
00079 void *ConvertIcon(WINBITMAPINFOHEADER *bmpHdr, int size, int *os2size, int offsetBits,
00080                   BOOL fResizeTo40x40 = FALSE)
00081 {
00082  RGBQUAD *rgb;
00083  RGB2    *os2rgb;
00084  int bwsize, i, colorsize, rgbsize, iconsize, orgbwsize, orgcolorsize;
00085  BITMAPFILEHEADER2 *iconhdr;
00086  BITMAPFILEHEADER2 *iconhdr2;
00087  char *pAnd, *pXor;
00088 
00089   if(fResizeTo40x40) {
00090       orgbwsize    = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), 1);
00091       orgcolorsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), bmpHdr->biBitCount);
00092       bwsize       = DIB_GetDIBImageBytes(40, 40, 1);
00093       colorsize    = DIB_GetDIBImageBytes(40, 40, bmpHdr->biBitCount);
00094   }
00095   else {
00096       bwsize    = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), 1);
00097       colorsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), bmpHdr->biBitCount);
00098   }
00099   //SvL: 28-09-'98: only for <= 8
00100   if(bmpHdr->biBitCount <= 8)
00101         rgbsize = (1<<bmpHdr->biBitCount)*sizeof(RGB2);
00102   else  rgbsize = 0;
00103 
00104   if(bmpHdr->biSizeImage == 0 && bmpHdr->biCompression == 0) {
00105         bmpHdr->biSizeImage = bwsize + colorsize;
00106   }
00107   dprintf(("Icon size    : %d", bmpHdr->biSizeImage));
00108   dprintf(("Icon Width   : %d", bmpHdr->biWidth));
00109   //height for both the XOR and AND bitmap (color & BW)
00110   dprintf(("Height       : %d", bmpHdr->biHeight));
00111   dprintf(("Icon Bitcount: %d", bmpHdr->biBitCount));
00112   dprintf(("Icon Compress: %d", bmpHdr->biCompression));
00113 
00114   //SvL: 28-09-'98: cllngenu.dll has an incorrect size in the header
00115   if(bmpHdr->biSizeImage < colorsize) {
00116         bmpHdr->biSizeImage = colorsize;
00117   }
00118   //bitmapfileheader for AndXor mask + 2 RGB structs + bitmapfileheader
00119   //for color bitmap + RGB structs for all the colors
00120   //SvL, 3-3-98: 2*bwsize
00121   iconsize = 2*sizeof(BITMAPFILEHEADER2) + 2*sizeof(RGB2) +
00122              rgbsize + 2*bwsize + colorsize;
00123 
00124   iconhdr  = (BITMAPFILEHEADER2 *)malloc(iconsize);
00125   memset(iconhdr, 0, iconsize);
00126   iconhdr->usType        = BFT_COLORICON;
00127   iconhdr->cbSize        = sizeof(BITMAPFILEHEADER2);
00128   iconhdr->xHotspot      = 0;
00129   iconhdr->yHotspot      = 0;
00130   iconhdr->offBits       = 2*sizeof(BITMAPFILEHEADER2) +
00131                            2*sizeof(RGB2) + rgbsize + offsetBits;
00132   iconhdr->bmp2.cbFix    = sizeof(BITMAPINFOHEADER2);
00133   if(fResizeTo40x40) {
00134       iconhdr->bmp2.cx   = (USHORT)40;
00135       iconhdr->bmp2.cy   = (USHORT)80;
00136   }
00137   else {
00138       iconhdr->bmp2.cx   = (USHORT)bmpHdr->biWidth;
00139       iconhdr->bmp2.cy   = (USHORT)bmpHdr->biHeight;
00140   }
00141   iconhdr->bmp2.cPlanes  = 1;
00142   iconhdr->bmp2.cBitCount= 1;
00143   iconhdr->bmp2.cbImage  = 2*bwsize;
00144   iconhdr->bmp2.cclrUsed = 2;
00145   iconhdr->bmp2.cclrImportant = 2;
00146   iconhdr->bmp2.ulCompression   = BCA_UNCOMP;
00147   iconhdr->bmp2.ulColorEncoding = BCE_RGB;
00148   os2rgb                 = (RGB2 *)(iconhdr+1);
00149   memset(os2rgb, 0, sizeof(RGB2));
00150   memset(os2rgb+1, 0xff, sizeof(RGB)); //not reserved byte!
00151   iconhdr2               = (BITMAPFILEHEADER2 *)(os2rgb+2);
00152   iconhdr2->usType       = BFT_COLORICON;
00153   iconhdr2->cbSize       = sizeof(BITMAPFILEHEADER2);
00154   iconhdr2->xHotspot     = 0;
00155   iconhdr2->yHotspot     = 0;
00156   iconhdr2->offBits      = 2*sizeof(BITMAPFILEHEADER2) +
00157                            2*sizeof(RGB2) + rgbsize + 2*bwsize + offsetBits;
00158   iconhdr2->bmp2.cbFix   = sizeof(BITMAPINFOHEADER2);
00159   if(fResizeTo40x40) {
00160       iconhdr2->bmp2.cx  = (USHORT)40;
00161       iconhdr2->bmp2.cy  = (USHORT)40;
00162   }
00163   else {
00164       iconhdr2->bmp2.cx  = (USHORT)bmpHdr->biWidth;
00165       iconhdr2->bmp2.cy  = (USHORT)(bmpHdr->biHeight/2);
00166   }
00167   iconhdr2->bmp2.cPlanes = bmpHdr->biPlanes;
00168   iconhdr2->bmp2.cBitCount= bmpHdr->biBitCount;
00169   iconhdr2->bmp2.cbImage  = colorsize;
00170   iconhdr2->bmp2.cclrUsed = bmpHdr->biClrUsed;
00171   iconhdr2->bmp2.cclrImportant = bmpHdr->biClrImportant;
00172   iconhdr2->bmp2.ulCompression   = BCA_UNCOMP;
00173   iconhdr2->bmp2.ulColorEncoding = BCE_RGB;
00174   os2rgb                 = (RGB2 *)(iconhdr2+1);
00175   rgb                    = (RGBQUAD *)(bmpHdr+1);
00176   if(bmpHdr->biBitCount <= 8) {
00177         for(i=0;i<(1<<bmpHdr->biBitCount);i++) {
00178                 os2rgb->bRed   = rgb->red;
00179                 os2rgb->bBlue  = rgb->blue;
00180                 os2rgb->bGreen = rgb->green;
00181                 os2rgb++;
00182                 rgb++;
00183         }
00184   }
00185 
00186   if(fResizeTo40x40) 
00187   {
00188       BYTE *src, *dest;
00189       int linesizesrc, linesizedest;
00190 
00191       pXor = (char *)os2rgb;
00192       pAnd = (char *)os2rgb + bwsize;
00193 
00194       if ((size - (bmpHdr->biSize + rgbsize + orgcolorsize + orgbwsize)) == orgbwsize) 
00195       {//this means an AND and XOR mask is present (interleaved; and/xor)
00196         char *q;
00197         int i, linesize;
00198 
00199         //TODO:
00200         dprintf(("TODO: icon conversion not correct"));
00201         linesize = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
00202         q = (char *)rgb + orgcolorsize;
00203         for (i = 0; i < bmpHdr->biHeight/2; i++) {
00204           memcpy (pAnd, q, linesize);
00205           pAnd += linesize;
00206           q += linesize;
00207 
00208           memcpy (pXor, q, linesize);
00209           pXor += linesize;
00210           q += linesize;
00211         }
00212       } 
00213       else {
00214         linesizesrc  = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
00215         linesizedest = DIB_GetDIBWidthBytes(40, 1);
00216 
00217         src  = (BYTE *)rgb + orgcolorsize;
00218         dest = (BYTE *)pAnd + 4*linesizedest; //skip 4 lines
00219         memset((char *)pAnd, 0xFF, bwsize);
00220         for (i = 0; i < bmpHdr->biHeight/2; i++) {
00221             for(int j=0;j<linesizesrc;j++) {
00222                 //must skip 4 pixels (4 bits)
00223                 dest[j]   = (dest[j] & 0xF0) | ((src[j] >> 4));
00224                 dest[j+1] = (dest[j+1] & 0x0F) | ((src[j] & 0xF) << 4);
00225             }
00226             dest += linesizedest;
00227             src  += linesizesrc;
00228         }
00229         memset (pXor, 0, bwsize);
00230       }
00231       linesizesrc  = DIB_GetDIBWidthBytes(32, bmpHdr->biBitCount);
00232       linesizedest = DIB_GetDIBWidthBytes(40, bmpHdr->biBitCount);
00233       int skipsize = (4*bmpHdr->biBitCount)/8; //must skip 4 pixels
00234       src  = (BYTE *)rgb;
00235       dest = (BYTE *)os2rgb+2*bwsize + 4*linesizedest; //skip 4 rows
00236 
00237       for (i = 0; i < 32; i++) {
00238           memcpy(dest+skipsize, src, linesizesrc);
00239           dest += linesizedest;
00240           src  += linesizesrc;
00241       }
00242   }
00243   else {
00244       pXor = (char *)os2rgb;
00245       pAnd = (char *)os2rgb + bwsize;
00246 
00247       if ((size - (bmpHdr->biSize + rgbsize + colorsize + bwsize)) == bwsize) 
00248       {//this means an AND and XOR mask is present (interleaved; and/xor)
00249         char *q;
00250         int i, linesize;
00251 
00252         linesize = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
00253         q = (char *)rgb + orgcolorsize;
00254         for (i = 0; i < bmpHdr->biHeight/2; i++) {
00255           memcpy (pAnd, q, linesize);
00256           pAnd += linesize;
00257           q += linesize;
00258 
00259           memcpy (pXor, q, linesize);
00260           pXor += linesize;
00261           q += linesize;
00262         }
00263       } 
00264       else {
00265         memcpy (pAnd, (char *)rgb + colorsize, bwsize);
00266         memset (pXor, 0, bwsize);
00267       }
00268       memcpy((char *)os2rgb+2*bwsize, (char *)rgb, colorsize);
00269   }
00270   *os2size = iconsize;
00271   return (void *)iconhdr;
00272 }
00273 //******************************************************************************
00274 //******************************************************************************
00275 void * WIN32API ConvertIconGroup(void *hdr, HINSTANCE hInstance, DWORD *ressize)
00276 {
00277  IconHeader *ihdr = (IconHeader *)hdr;
00278  ResourceDirectory *rdir = (ResourceDirectory *)(ihdr + 1);
00279  int i, groupsize = 0, os2iconsize;
00280  BITMAPARRAYFILEHEADER2 *bafh, *orgbafh;
00281  WINBITMAPINFOHEADER    *iconhdr;
00282  void                   *os2icon;
00283  HRSRC                   hRes;
00284  int                     nricons = 0;
00285 
00286   dprintf(("Icon Group type :%d", ihdr->wType));
00287   dprintf(("Icon Group count:%d", ihdr->wCount));
00288   for(i=0;i<ihdr->wCount;i++) {
00289         dprintf2(("Icon    : %d", rdir->wNameOrdinal));
00290         dprintf2(("Width   : %d", (int)rdir->bWidth));
00291         dprintf2(("Height  : %d", (int)rdir->bHeight));
00292         dprintf2(("Colors  : %d", (int)rdir->bColorCount));
00293         dprintf2(("Bits    : %d", rdir->wBitCount));
00294         dprintf2(("ResBytes: %d", rdir->lBytesInRes));
00295         hRes = FindResourceA(hInstance, 
00296                              (LPCSTR)rdir->wNameOrdinal, (LPSTR)NTRT_ICON);
00297 
00298         groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes)),
00299                                             SizeofResource(hInstance, hRes));
00300         //add centered icon if size is 32x32
00301         if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4) 
00302         {
00303             groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes)),
00304                                                 SizeofResource(hInstance, hRes), TRUE);
00305             //extra pixels
00306             groupsize += (40*8 + 8*32)*rdir->wBitCount/8;
00307             nricons++;
00308         }
00309         nricons++;
00310         rdir++;
00311   }
00312   groupsize = groupsize+nricons*(sizeof(BITMAPARRAYFILEHEADER2) - sizeof(BITMAPFILEHEADER2));
00313   bafh    = (BITMAPARRAYFILEHEADER2 *)malloc(groupsize);
00314   memset(bafh, 0, groupsize);
00315   orgbafh = bafh;
00316 
00317   rdir = (ResourceDirectory *)(ihdr + 1);
00318   for(i=0;i<ihdr->wCount;i++) {
00319         bafh->usType    = BFT_BITMAPARRAY;
00320         bafh->cbSize    = sizeof(BITMAPARRAYFILEHEADER2);
00321         bafh->cxDisplay = 0;
00322         bafh->cyDisplay = 0;
00323         hRes = FindResourceA(hInstance, 
00324                              (LPCSTR)rdir->wNameOrdinal, (LPSTR)NTRT_ICON);
00325         if(hRes == NULL) {
00326                 dprintf(("Can't find icon!"));
00327                 rdir++;
00328                 continue;
00329         }
00330         iconhdr = (WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes));
00331         os2icon = ConvertIcon(iconhdr, SizeofResource(hInstance, hRes), &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2));
00332         if(os2icon == NULL) {
00333                 dprintf(("Can't convert icon!"));
00334                 rdir++;
00335                 continue;
00336         }
00337 
00338         if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4) 
00339         {
00340                 //add 40x40 icon by centering 32x32 icon in 40x40 grid
00341                 //(resize is really ugly)
00342                 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
00343                 memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
00344                 free(os2icon);
00345 
00346                 bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
00347 
00348                 os2icon = ConvertIcon(iconhdr, SizeofResource(hInstance, hRes), &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2), TRUE);
00349                 if(os2icon == NULL) {
00350                         dprintf(("Can't convert icon!"));
00351                         rdir++;
00352                         continue;
00353                 }
00354         }
00355 
00356         if(i != ihdr->wCount -1) {
00357                 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
00358         }
00359         else    bafh->offNext = 0;
00360 
00361         memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
00362         free(os2icon);
00363 
00364         bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
00365 
00366         rdir++;
00367   }
00368   *ressize = groupsize;
00369   return (void *)orgbafh;
00370 }
00371 //******************************************************************************
00372 //******************************************************************************

Generated on Wed Jan 23 23:17:32 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001