I'd have preferred to add this code to a comment, but it's just impractical for so many reasons.
Here's the code I had in the project I mentioned earlier. It does seem a bit funky now, some 4 1/2 years on - I think saveBMPfloat would be the easiest/quickest to modify. Just snip/replace the code that normalizes the values before they're saved.
I should also note that it expects a 1D array - i.e a 10x10 img would be
int myImg[10x10], rather than int myImg[10][10]. Same size, I come from a background using assembler (borland's tasm) & have always been used to handling the memory/indexing into arrays myself.
#ifndef myBitmap_H
#define myBitmap_H
#include <windows.h>
typedef struct
{
unsigned char iD[2]; unsigned int filesize; unsigned short reserved1; unsigned short reserved2; unsigned int dataOffset; } myBitmapHeader;
typedef struct
{
long size; long bm_width; long bm_height; short colPlanes; short bitsPerPixel; long compressionType; long imageSize; long horRes; long verRes; long paletteCols; long importantCols; } dibHeader;
HBITMAP myLoadBitmapFromFile(char *fileName);
#endif
myBitmap.c
#include "myBitmap.h"
#include "blenderOceanComplexT.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int saveBMPcomplexImag(char *filename, long xRes, long yRes, int normalize, blenderOceanComplexT *data);
long rowSize(int width, int bitsPixel)
{
return 4 * ceil( (bitsPixel*width) / 32.0 );
}
int saveBMPcomplexImag(char *filename, long xRes, long yRes, int normalize, blenderOceanComplexT *data)
{
myBitmapHeader myHdr;
dibHeader myDibHdr;
FILE *output;
int rowPadCount;
long x, y;
long datIndex;
char pixel[3]; char padPixel = 0;
myHdr.iD[0] = 'B';
myHdr.iD[1] = 'M';
myHdr.reserved1 = 0;
myHdr.reserved2 = 0;
myHdr.dataOffset = 40 + 14; myHdr.filesize = myHdr.dataOffset + (yRes*rowSize(xRes, 24));
rowPadCount = rowSize(xRes, 24) - (xRes*3);
myDibHdr.size = 40;
myDibHdr.bm_width = xRes;
myDibHdr.bm_height = yRes;
myDibHdr.colPlanes = 1;
myDibHdr.bitsPerPixel = 24;
myDibHdr.compressionType = 0;
myDibHdr.imageSize = yRes * rowSize(xRes, 24);
myDibHdr.horRes = 2835; myDibHdr.verRes = 2835;
myDibHdr.paletteCols = 0;
myDibHdr.importantCols = 0;
output = fopen(filename, "w");
if (output == NULL)
return 0;
fwrite(&myHdr.iD, 1, 2, output);
fwrite(&myHdr.filesize, 1, 4, output);
fwrite(&myHdr.reserved1, 1, 2, output);
fwrite(&myHdr.reserved2, 1, 2, output);
fwrite(&myHdr.dataOffset, 1, 4, output);
fwrite(&myDibHdr, 1, sizeof(myDibHdr), output);
float max, min;
if (normalize)
{
max = data[0].imag; min = data[0].imag;
for (datIndex=0; datIndex<xRes*yRes; datIndex++)
{
if (min > data[datIndex].real)
min = data[datIndex].real;
if (max < data[datIndex].real)
max = data[datIndex].real;
}
}
else
{
min = -5.0;
max = 5.0;
}
datIndex = 0;
unsigned char blue, green, red, thisPixel;
for (y=0; y<yRes; y++)
{
for(x=0; x<xRes; x++)
{
thisPixel = (unsigned char) 255.0*((data[datIndex].real - min)/(max-min));
memset(pixel, thisPixel, 3);
fwrite(pixel, 3, 1, output);
datIndex++;
}
if (rowPadCount)
fwrite(&padPixel, 1, rowPadCount, output); }
fclose(output);
return 1;
}
int saveBMPfloat(char *filename, int xRes, int yRes, int normalize, float *data)
{
myBitmapHeader myHdr;
dibHeader myDibHdr;
FILE *output;
int rowPadCount;
long x, y;
long datIndex;
char pixel[3]; char thisPixel;
char padPixel = 0;
myHdr.iD[0] = 'B';
myHdr.iD[1] = 'M';
myHdr.reserved1 = 0;
myHdr.reserved2 = 0;
myHdr.dataOffset = 40 + 14; myHdr.filesize = myHdr.dataOffset + (yRes*rowSize(xRes, 24));
rowPadCount = rowSize(xRes, 24) - (xRes*3);
myDibHdr.size = 40;
myDibHdr.bm_width = xRes;
myDibHdr.bm_height = yRes;
myDibHdr.colPlanes = 1;
myDibHdr.bitsPerPixel = 24;
myDibHdr.compressionType = 0;
myDibHdr.imageSize = yRes * rowSize(xRes, 24);
myDibHdr.horRes = 2835; myDibHdr.verRes = 2835;
myDibHdr.paletteCols = 0;
myDibHdr.importantCols = 0;
output = fopen(filename, "w");
if (output == NULL)
return 0;
fwrite(&myHdr.iD, 1, 2, output);
fwrite(&myHdr.filesize, 1, 4, output);
fwrite(&myHdr.reserved1, 1, 2, output);
fwrite(&myHdr.reserved2, 1, 2, output);
fwrite(&myHdr.dataOffset, 1, 4, output);
fwrite(&myDibHdr, 1, sizeof(myDibHdr), output);
float max, min;
if (normalize)
{
max = data[0]; min = data[0];
for (datIndex=0; datIndex<xRes*yRes; datIndex++)
{
if (min > data[datIndex])
min = data[datIndex];
if (max < data[datIndex])
max = data[datIndex];
}
}
else {
min = -5.0;
max = 5.0;
}
datIndex = 0;
unsigned char blue, green, red;
for (y=0; y<yRes; y++)
{
for(x=0; x<xRes; x++)
{
thisPixel = (unsigned char) 255.0*((data[datIndex] - min)/(max-min));
memset(pixel, thisPixel, 3);
fwrite(pixel, 3, 1, output);
datIndex++;
}
if (rowPadCount)
fwrite(&padPixel, 1, rowPadCount, output); }
fclose(output);
return 1;
}
HBITMAP CreateBitmapFromPixelData( HDC hDC, UINT uWidth, UINT uHeight, UINT uBitsPerPixel, LPVOID pBits )
{
HBITMAP hBitmap = 0;
if ( !uWidth || !uHeight || !uBitsPerPixel )
return hBitmap;
LONG lBmpSize = uWidth * uHeight * (uBitsPerPixel/8) ; BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biBitCount = uBitsPerPixel;
bmpInfo.bmiHeader.biHeight = uHeight;
bmpInfo.bmiHeader.biWidth = uWidth;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
hBitmap = CreateDIBSection( hDC, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS, (void**)&pBits , NULL, 0);
if ( !hBitmap )
return hBitmap; SetBitmapBits( hBitmap, lBmpSize,pBits);
return hBitmap;
}
unsigned char *LoadBitmapFile(char *filename, dibHeader *bitmapInfoHeader)
{
FILE *filePtr; myBitmapHeader bitmapFileHeader; unsigned char *bitmapImage; int imageIdx=0; unsigned char tempRGB; filePtr = fopen(filename,"rb");
if (filePtr == NULL)
return NULL;
fread(&bitmapFileHeader.iD, 2 ,1,filePtr);
fread(&bitmapFileHeader.filesize, 4 ,1,filePtr);
fread(&bitmapFileHeader.reserved1, 2 ,1,filePtr);
fread(&bitmapFileHeader.reserved2, 2 ,1,filePtr);
fread(&bitmapFileHeader.dataOffset, 4 ,1,filePtr);
if ((bitmapFileHeader.iD[0] != 'B')||(bitmapFileHeader.iD[1] != 'M'))
{
fclose(filePtr);
return NULL;
}
fread(bitmapInfoHeader, sizeof(dibHeader),1,filePtr);
fseek(filePtr, bitmapFileHeader.dataOffset, SEEK_SET);
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->imageSize);
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
fread(bitmapImage, 1, bitmapInfoHeader->imageSize, filePtr);
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
for (imageIdx = 0; imageIdx < bitmapInfoHeader->imageSize; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
fclose(filePtr);
return bitmapImage;
}
HBITMAP myLoadBitmapFromFile(char *fileName)
{
dibHeader bmpInfo;
unsigned char *pixelData;
HBITMAP result;
pixelData = LoadBitmapFile(fileName,&bmpInfo);
result = CreateBitmapFromPixelData(NULL, bmpInfo.bm_width, bmpInfo.bm_height, bmpInfo.bitsPerPixel, pixelData);
free(pixelData);
return result;
}