Stoppt die Vorratsdatenspeicherung! Jetzt klicken && handeln!Willst du auch bei der Aktion teilnehmen? Hier findest du alle relevanten Infos und Materialien:
 
Windows-Icons
von Plapperkatze am 12.Februar 2006 um 17:50
zurück zur Kategorie "Tutorials"

Es geht darum aus Bitmaps Windows-Icons zu machen. Zur Zeit ist ein solches Icon quadratisch und 16x16, 32x32, 48x48 oder 64x64 Pixel groß.

Wie wir uns erinnern, oder auch nicht, ist ein Bitmap so aufgebaut:
BITMAPFILEHEADER
BITMAPINFOHEADER
PALETTE (nur bei Bitmaps mit höchstens 8 Bit/256 Farben)
DATEN

Ein Icon dagegen, hier eines mit 2 Bitmaps drin, sieht von der Struktur so aus:
ICONDIR
ICONDIRENTRY 1
ICONDIRENTRY 2
PALETTE von Bitmap 1 (nur bei Bitmaps mit höchstens 8 Bit/256 Farben)
DATEN von Bitmap 1
TRANSPARENZMASKE von Bitmap 1 (scheinbar 2 Bit bei <= 256 Farben, sonst 1 Bit)
PALETTE von Bitmap 2 (nur bei Bitmaps mit höchstens 8 Bit/256 Farben)
DATEN von Bitmap 2
TRANSPARENZMASKE von Bitmap 2 (scheinbar 2 Bit bei <= 256 Farben, sonst 1 Bit)

Die Strukturen für ICONDIR, ICONDIRENTRY und ICONIMAGE habe ich hier untergebracht. Vielleicht sind sie in eurem Compiler schon dabei, dann lasst diese Definitionen weg.
// typefs von http://msdn.microsoft.com/library/en-us/dnwui/html/msdn_icons.asp (wahrscheinlich ein toter link...use google)

typedef struct
{
  BITMAPINFOHEADER  infoheader;    // DIB header
  RGBQUAD           icColors[1];   // Color table
  BYTE              icXOR[1];      // DIB bits for XOR mask
  BYTE              icAND[1];      // DIB bits for AND mask
} ICONIMAGE, *LPICONIMAGE;

typedef struct
{
   BYTE        bWidth;             // Width, in pixels, of the image
   BYTE        bHeight;            // Height, in pixels, of the image
   BYTE        bColorCount;        // Number of colors in image (0 if >=8bpp)
   BYTE        bReserved;          // Reserved ( must be 0)
   WORD        wPlanes;            // Color Planes
   WORD        wBitCount;          // Bits per pixel
   DWORD       dwBytesInRes;       // How many bytes in this resource?
   DWORD       dwImageOffset;      // Where in the file is this image?
} ICONDIRENTRY, *LPICONDIRENTRY;

typedef struct
{
   WORD             idReserved;    // Reserved (must be 0)
   WORD             idType;        // Resource Type (1 for icons)
   WORD             idCount;       // How many images?
   //ICONDIRENTRY   idEntries[1];  // An entry for each image (idCount of 'em)
} ICONDIR, *LPICONDIR;

Wir laden also erst einmal ein Bitmap:
#include <windows.h>

BOOL readBmpFile(char *filename)
{
 // dateihandling
 HANDLE hFile;
 DWORD dwRead;
 DWORD dwFileSize;
 // bitmapdaten
 BITMAPFILEHEADER bmfileheader;
 BITMAPINFOHEADER bmiheader;  
 char *buffer;

 // file öffnen
 hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
 OPEN_EXISTING, 0, NULL);
 if(hFile==INVALID_HANDLE_VALUE)return -1;
 // dateigrösse ermitteln
 dwFileSize = GetFileSize(hFile, NULL);
 if(dwFileSize == 0xFFFFFFFF)return -1;
 // speicher allokieren
 buffer = (char *)GlobalAlloc(GPTR, dwFileSize + 1);
 if(buffer == NULL)return -1;
 // bitmapfileheader lesen
 if(!ReadFile(hFile,&bmfileheader,sizeof(BITMAPFILEHEADER),&dwRead,NULL))return -1;
 // bitmapinfoheader lesen
 if(!ReadFile(hFile,&bmiheader,sizeof(BITMAPINFOHEADER),&dwRead,NULL))return -1;
 // bitmapdaten lesen
 if(!ReadFile(hFile,buffer,dwFileSize,&dwRead,NULL))return -1;
 // datei schliessen
 CloseHandle(hFile);
 // Bitmap wurde geladen
 // jetzt irgendwas tun damit

 // ...

 // speicher freigeben
 GlobalFree(buffer);
 return 0;
}

Nun müsste man eigentlich prüfen, ob es sich um ein geeignetes Bitmap handelt, etc. Ich lasse das hier weg, und komme sofort zum Umwandeln in ein Icon.
int writeIcon(char *buffer, int w, int h, int planes, int bppx)
{

 ICONIMAGE iconimage;
 ICONDIRENTRY icondirentry;
 ICONDIR icondir;

 HANDLE hFile;
 DWORD byteswritten=0,bw;
 char mask[4096];//

 // farbanzahl aus bits per pixel bestimmen

 long colors;
 int masksize;
 switch(bppx)
 {
   break;
   case 1:  
     colors=2;
     masksize=2;
   break;
   case 4:
     colors=16;
     masksize=2;
   break;
   case 8:
     colors=256;
     masksize=2;
   break;
   default:
     colors=0;
     masksize=1;
   break;
 }

 // icondirentry struktur füllen

 icondirentry.bWidth=w;             // Width, in pixels, of the image
 icondirentry.bHeight=h;            // Height, in pixels, of the image
 icondirentry.bColorCount=colors;   // Number of colors in image (0 if >=8bpp)
 icondirentry.bReserved=0;          // Reserved ( must be 0)
 icondirentry.wPlanes=planes;       // Color Planes
 icondirentry.wBitCount=bppx;       // Bits per pixel

 // gesamtgrösse des icons: header+palette+bilddaten+maske
 icondirentry.dwBytesInRes=40+colors*4+bppx*w*h/8+masksize*w*h/8;

 // offset des bitmaps vom dateianfang
 icondirentry.dwImageOffset=6+16;   // Where in the file is this image?

 // icondirentry struktur füllen

 icondir.idReserved=0;   // Reserved (must be 0)
 icondir.idType=1;       // Resource Type (1 for icons)
 icondir.idCount=1;      // How many images?
 //icondir.idEntries[0]=.... (wir schreiben diesen icondirentry selbst ins file)

 // bitmapinfoheader nicht identisch: höhe doppelt (wegen maske)

 iconimage.infoheader.biSize=sizeof(BITMAPINFOHEADER);
 iconimage.infoheader.biWidth=w;
 iconimage.infoheader.biHeight=h*2;  
 iconimage.infoheader.biPlanes=planes;
 iconimage.infoheader.biBitCount=bppx;
 iconimage.infoheader.biSizeImage=bppx*w*h/8;

 // diese werte des infoheaders müssen auf 0 gesetzt sein:

 iconimage.infoheader.biCompression=0;
 iconimage.infoheader.biXPelsPerMeter=0;
 iconimage.infoheader.biYPelsPerMeter=0;
 iconimage.infoheader.biClrUsed=0;
 iconimage.infoheader.biClrImportant=0;

 // datei "bla.ico" erzeugen

 hFile = CreateFile("bla.ico", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                     FILE_ATTRIBUTE_NORMAL, NULL);
 if(hFile==INVALID_HANDLE_VALUE)return -1;

 // datei schreiben: icondir, icondirentry, iconimage-header, geladene daten, maske, EOF  

 memset(mask,0,4096);
 WriteFile(hFile,(void *)&icondir,sizeof(ICONDIR),&bw,NULL);byteswritten+=bw;
 WriteFile(hFile,(void *)&icondirentry,sizeof(ICONDIRENTRY),&bw,NULL);byteswritten+=bw;
 WriteFile(hFile,(void *)&iconimage,sizeof(BITMAPINFOHEADER),&bw,NULL);byteswritten+=bw;
 WriteFile(hFile,buffer,bppx*w*h/8+colors*4,&bw,NULL);byteswritten+=bw;
 WriteFile(hFile,mask,masksize*w*h/8,&bw,NULL);byteswritten+=bw;

 // datei schiessen
 CloseHandle(hFile);
 
 //fertig.
 
 return 0;
}

Nun, das war eigentlich alles. Fügt den Code zusammen (und vor allem, guckt ihn euch an), und ihr könnt eure Icons selbst erstellen, statt euch mit Shareware-Trials herumzuärgern.

Ihr könnt in readBmpFile, nachdem das Bitmap geladen wurde, folgendes einfügen, um sofort WriteIcon aufzurufen:
WriteIcon(buffer,bmiheader.biWidth,bmiheader.biHeight,bmiheader.biPlanes,bmiheader.biBitCount);


Ich werde das Tutorial weiter ausbauen, sobald Fragen, Hinweise oder Bugs aufgetreten sind. Kommentare sind gern gesehen.

gruesse, die plapperkatz

zurück zur Kategorie "Tutorials"
[0 Kommentare]

Name


Kommentar




Bitte abtippen


 
(C) 2006-20012 Plapperkatze - 215314 Besucher seit dem 23.01.2012 Login