It's actually pretty easy, if one is vaguely familiar with image-based programming tasks.
I left a description of the file format in a comment above, though this can be seen from the code below.
I first tried to create the new image and then use GDI+ to save it as a PNG complete with 16 level transparency. Unfortunately, GDI+ saved the colour values as desired, but set all of the alpha bits of the image to 255 - or opaque. :(
Next I remembered some code that will save to a 32 bit BMP file. I tried this on the output from a function that loads the binary file into a HBITMAP and found that the image was saved as expected. Opening it with the Windows Photo Viewer makes it appear as though it's failed, however if I open it with GIMP, it's immediately apparent that the process has functioned as desired. Windows Photo Viewer shows the transparent, black area as being black and opaque.
Given that you have a desire to save them as PNG files, what I'd do would be to setup a small chunk of code that converted all of the binary files to BMP files. I'd then run Irfanview on the folder, converting all of the BMP files to 32bit PNGs.
The conversion should take no time - it may well take longer to download, start and setup Irfanview for the batch conversion.
Anyway, heres the code - you can chuck out all of the GDI+ stuff. I've just left it there as a demo of saving an HBITMAP to a png - also to demonstrate the fact that library code isn't always better than something home-rolled.
It's a console program, linked against the gdi32 and gdiplus libraries.
Without further ado -
#include <cstdio>
#include <cstdlib>
#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma pack(push,1) //// done to prevent gcc from padding the struct - IMPORTANT!
typedef struct
{
unsigned char unknown1;
unsigned short width;
unsigned short height;
unsigned short unknown2;
unsigned short unknown3;
unsigned long dataOffset;
} fileHeader, *pFileHeader;
#pragma pack(pop)
HBITMAP mCreateDibSection(HDC hdc, int width, int height, int bitCount)
{
BITMAPINFO bi;
ZeroMemory(&bi, sizeof(bi));
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = width;
bi.bmiHeader.biHeight = height;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = bitCount;
bi.bmiHeader.biCompression = BI_RGB;
return CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, 0,0,0);
}
void showFileInfo(char *binFilename)
{
fileHeader mHeader;
FILE *fp;
fp = fopen(binFilename, "rb");
fread(&mHeader, sizeof(fileHeader), 1, fp);
fclose(fp);
printf("Width: %d\n", mHeader.width);
printf("Height: %d\n", mHeader.height);
printf("pixelData offset: %ld\n", mHeader.dataOffset);
}
void mPixel(int xPos, int yPos, char r, char g, char b, char a, BITMAP img)
{
char *pixelPtr = (char*)img.bmBits + (yPos * img.bmWidthBytes) + (xPos * (img.bmBitsPixel / 8) );
*pixelPtr++ = b;
*pixelPtr++ = g;
*pixelPtr++ = r;
*pixelPtr++ = a;
}
HBITMAP loadBinaryImg(char *filename)
{
fileHeader mHeader;
FILE *fp;
fp = fopen(filename, "rb");
fread(&mHeader, sizeof(fileHeader), 1, fp);
unsigned short *pixelData;
pixelData = (unsigned short*) calloc( sizeof(short), mHeader.width * mHeader.width );
fseek(fp, mHeader.dataOffset, SEEK_SET);
fread(pixelData, sizeof(short), mHeader.width*mHeader.height, fp);
fclose(fp);
HDC hdc = GetDC(HWND_DESKTOP);
HBITMAP mResult = mCreateDibSection(hdc, mHeader.width, -mHeader.height, 32);
ReleaseDC(HWND_DESKTOP, hdc);
BITMAP bm;
GetObject(mResult, sizeof(bm), &bm);
int xPos, yPos;
for (yPos=0; yPos<mHeader.height; yPos++)
{
for (xPos=0; xPos<mHeader.width; xPos++)
{
unsigned short curPixel;
curPixel = pixelData[xPos + yPos*mHeader.width];
unsigned char r, g, b, a;
b = curPixel & 0xF;
g = (curPixel >> 4) & 0xF;
r = (curPixel >> 8) & 0xF;
a = (curPixel >> 12) & 0xF;
a *= 17; r *= 17; g *= 17; b *= 17;
mPixel(xPos, yPos, r,g,b,a, bm);
}
}
return mResult;
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; UINT size = 0;
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1;
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; }
}
free(pImageCodecInfo);
return -1; }
void saveHbitmapAsPng(HBITMAP img, wchar_t *outputFilename)
{
Bitmap *bitmap = Bitmap::FromHBITMAP(img, NULL);
CLSID encoderClsid;
GetEncoderClsid(L"image/png", &encoderClsid);
bitmap->Save(outputFilename, &encoderClsid, NULL);
delete bitmap;
}
void saveHbitmapAsBmp(HBITMAP img, char *outputFilename)
{
HDC hdcScreen = GetDC(HWND_DESKTOP);
BITMAP bm;
char *lpbitmap;
HANDLE hDIB;
DWORD dwBmpSize, dwSizeofDIB, dwBytesWritten;
HANDLE hFile;
GetObject(img,sizeof(bm),&bm);
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmpSize = ((bm.bmWidth * bi.biBitCount + 31) / 32) * 4 * bm.bmHeight;
hDIB = GlobalAlloc(GHND,dwBmpSize);
lpbitmap = (char *)GlobalLock(hDIB);
GetDIBits(hdcScreen, img, 0,
(UINT)bm.bmHeight,
lpbitmap,
(BITMAPINFO *)&bi, DIB_RGB_COLORS);
hFile = CreateFile(outputFilename,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
bmfHeader.bfSize = dwSizeofDIB;
bmfHeader.bfType = 0x4D42;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
GlobalUnlock(hDIB);
GlobalFree(hDIB);
CloseHandle(hFile);
done:
ReleaseDC(NULL,hdcScreen);
}
int main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HBITMAP someBin = loadBinaryImg("something.bin");
saveHbitmapAsPng(someBin, L"output.png");
saveHbitmapAsBmp(someBin, "output.bmp");
GdiplusShutdown(gdiplusToken);
return 0;
}