@Cel Ok so the HMIBMP structure is what I use internally to handle bitmaps.
Its just a conveniant way to handle device independent bitmaps without having to get bogged down with a lot of the unnecessary/unused stuff, although you can still get to the underlying windows structures if you need to.
It has these members:
pFile pointer to the BITMAPFILEHEADER struct
pInfo pointer to the BITMAPINFOHEADER struct
pPal pointer to the palette (if the bitmap has one)
pBits pointer to the pixmap (actual pixel data - depends on the format)
width duh
height duh
bpp bits per pixel (this will be 8 for most WC2 things)
linew internal size in bytes for one line of pixels
usage (pixel color values or palette entries)
size total size of all structures
so if you do:
HMIBMP* MyBmp = make_bitmap(300,200,8);
You will get a handle to a 300x200 8-bit bitmap. All the underlying windows structures are created automatically.
when finished use:
free_bitmap(MyBmp);
to deallocate all the memory.
*** These bitmap functions are not complete for every format, I have just added to them whenever I needed to do something .... most of it works for 8-bit bitmaps - because that's what I mostly play with for WC2 stuff. Some things work for 32 or 24 bit bitmaps. Pretty much none of it will work for 4 or 16 bit bmps (but who cares about that crap lol). ***For WC2 stuff you will just want 8-bit bmps, the only thing you would use any other format for is the size_bitmap() func which will resize an 8-bit bmp and blend the colors then return a 32-bit bitmap of the requested size.
LPVOID MyPud = PUDload("c:\\someMap.pud");
Will return a handle to a linked list of PUDSECT structures, which contain pointers to the actual data for each section.
You can get a pointer to the data for a given section like this:
BYTE* sectionData(LPVOID hPud, DWORD sname){
PUDSECT* sptr = PUDfind_section(hPud,sname);
if (sptr!=NULL) return sptr->data;
return NULL;
}
NOTE: the section name is a DWORD not a string .... all pud section names are 4 bytes, so you want constants like this:
#define sTYPE 0x45505954 // "TYPE"
#define sVER_ 0x20524556 // "VER "
#define sDESC 0x43534544 // "DESC"
#define sOWNR 0x524E574F // "OWNR"
#define sERA_ 0x20415245 // "ERA "
#define sERAX 0x54415245 // "ERAX"
#define sDIM_ 0x204D4944 // "DIM "
#define sUDTA 0x41544455 // "UDTA"
#define sUNIT 0x54494E55 // "UNIT"
#define sUGRD 0x44524755 // "UGRD"
#define sSIDE 0x45444953 // "SIDE"
#define sSGLD 0x444C4753 // "SGLD"
#define sSLBR 0x52424C53 // "SLBR"
#define sSOIL 0x4C494F53 // "SOIL"
#define sAIPL 0x4C504941 // "AIPL"
#define sMTXM 0x4D58544D // "MTXM"
#define sSQM_ 0x204D5153 // "SQM "
#define sOILM 0x4D4C494F // "OILM"
#define sREGM 0x4D474552 // "REGM"
#define sSIGN 0x4E474953 // "SIGN"
#define sALOW 0x574F4C41 // "ALOW"
so you can get the map size of a pud file from the "DIM " section like:
int getPudDim(LPVOID hpud){
WORD* pdim = (WORD*) sectionData(hpud,sDIM_)
if (pdim) return (int) *pdim;
return 0;
}
If you get a "tile" value from the MTXM section you can draw that square of terrain on the bitmap at (x,y) with:
PUDrenderTile(MyBmp, tileValue , int x, int y);
or
PUDrenderMap(MyBmp, MTXM_section, size);
will do the terrain for the whole map - but make sure the bitmap is the right size or you will crash.
The different terrain styles can be selected like this:
#define FOREST 0
#define WINTER 1
#define WASTELAND 2
#define SWAMP 3
PUDtileset(RESgetTileset( WINTER ));
you will also need to set the appropriate palette in your bitmap or the colors will come out wrong.
set_palette(MyBmp , RESgetPalette( WINTER ));
so you should be able to make a bmp file of just the terrain for a PUD file with something like:
// # UNTESTED # - probably has errors/typos
#include <windows.h>
//#include HEADER FILE WITH IMPORT DEFS FROM PREVIOUS POST AND CONSTANT DEFS (ABOVE)
CHAR* pudpath = "myMap.pud";
CHAR* bmppath = "this.bmp";
// load the pud file
LPVOID hPud = PUDload(pudpath);
BYTE* sectionData(LPVOID hpud, DWORD sname){
PUDSECT* sptr = PUDfind_section(hpud,sname);
if (sptr!=NULL) return (BYTE*)sptr->data;
return NULL;
}
int getPudSize(LPVOID hpud){
WORD* pdim = (WORD*) sectionData(hpud,sDIM_);
if(pdim) return (int) *pdim;
return 0;
}
int getTerrainType(LPVOID hpud){
WORD* pter = (WORD*) sectionData(hpud,sERA_);
if(pter) return (int) *pter;
return 0;
}
// get some info from the pud
int mapsize = getPudSize(hPud);
int terrain = getTerrainType(hPud);
// make a bitmap in memory (tiles are 32x32 pixels)
HMIBMP* hbm = make_bitmap(mapsize*32,mapsize*32,8);
// use the tiles for the map terrain type
PUDtileset(RESgetTileset(terrain));
// don't forget this if you are using GRPs, only needs to be done once to initialize
// can't remember if it needs to be done for only the terrain, but it cant hurt lol
GRPinit(RESgetGrp());
//paste all the tile graphics for the pud onto the bitmap
PUDrenderMap( hbm, sectionData(hpud,sMTXM) , mapsize);
// ensure the bmp file has the correct palette for the terrain type
set_palette(hbm , RESgetPalette( terrain ));
// save the bitmap to a file
save_bitmap(bmppath,hbm);
// dispose of the bitmap
free_bitmap(hbm);
// dispose of the pud structure
PUDdestroy(hPud);
Obviously you will also need the two dlls from PUDPIC, #define statements for used constants, and the function import stuff and structure defs from the previous post.
Play with that stuff and let me know how you go .... HF
p.s. also if you want you can display your bitmap (or part of it) on a Windows device context with:
display_image( dc, windowX, windowY, displayWidth, displayHeight, hbm, bmX, bmY, bmW, bmH );
if you pass 0 for the width and height they will default to the bitmap width and height, so:
display_image(dc,0,0,0,0,hbm,0,0,0,0);
will just display the bitmap on the window without any resizing.