Created
June 24, 2013 06:29
sample code for generate a bitmap image at x86_64 GNU/Linux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
// for Linux platform, plz make sure the size of data type is correct for BMP spec. | |
// if you use this on Windows or other platforms, plz pay attention to this. | |
typedef int LONG; | |
typedef unsigned char BYTE; | |
typedef unsigned int DWORD; | |
typedef unsigned short WORD; | |
// __attribute__((packed)) on non-Intel arch may cause some unexpected error, plz be informed. | |
typedef struct tagBITMAPFILEHEADER | |
{ | |
WORD bfType; // 2 /* Magic identifier */ | |
DWORD bfSize; // 4 /* File size in bytes */ | |
WORD bfReserved1; // 2 | |
WORD bfReserved2; // 2 | |
DWORD bfOffBits; // 4 /* Offset to image data, bytes */ | |
} __attribute__((packed)) BITMAPFILEHEADER; | |
typedef struct tagBITMAPINFOHEADER | |
{ | |
DWORD biSize; // 4 /* Header size in bytes */ | |
LONG biWidth; // 4 /* Width of image */ | |
LONG biHeight; // 4 /* Height of image */ | |
WORD biPlanes; // 2 /* Number of colour planes */ | |
WORD biBitCount; // 2 /* Bits per pixel */ | |
DWORD biCompress; // 4 /* Compression type */ | |
DWORD biSizeImage; // 4 /* Image size in bytes */ | |
LONG biXPelsPerMeter; // 4 | |
LONG biYPelsPerMeter; // 4 /* Pixels per meter */ | |
DWORD biClrUsed; // 4 /* Number of colours */ | |
DWORD biClrImportant; // 4 /* Important colours */ | |
} __attribute__((packed)) BITMAPINFOHEADER; | |
/* | |
typedef struct tagRGBQUAD | |
{ | |
unsigned char rgbBlue; | |
unsigned char rgbGreen; | |
unsigned char rgbRed; | |
unsigned char rgbReserved; | |
} RGBQUAD; | |
* for biBitCount is 16/24/32, it may be useless | |
*/ | |
typedef struct | |
{ | |
BYTE b; | |
BYTE g; | |
BYTE r; | |
} RGB_data; // RGB TYPE, plz also make sure the order | |
int bmp_generator(char *filename, int width, int height, unsigned char *data) | |
{ | |
BITMAPFILEHEADER bmp_head; | |
BITMAPINFOHEADER bmp_info; | |
int size = width * height * 3; | |
bmp_head.bfType = 0x4D42; // 'BM' | |
bmp_head.bfSize= size + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // 24 + head + info no quad | |
bmp_head.bfReserved1 = bmp_head.bfReserved2 = 0; | |
bmp_head.bfOffBits = bmp_head.bfSize - size; | |
// finish the initial of head | |
bmp_info.biSize = 40; | |
bmp_info.biWidth = width; | |
bmp_info.biHeight = height; | |
bmp_info.biPlanes = 1; | |
bmp_info.biBitCount = 24; // bit(s) per pixel, 24 is true color | |
bmp_info.biCompress = 0; | |
bmp_info.biSizeImage = size; | |
bmp_info.biXPelsPerMeter = 0; | |
bmp_info.biYPelsPerMeter = 0; | |
bmp_info.biClrUsed = 0 ; | |
bmp_info.biClrImportant = 0; | |
// finish the initial of infohead; | |
// copy the data | |
FILE *fp; | |
if (!(fp = fopen(filename,"wb"))) return 0; | |
fwrite(&bmp_head, 1, sizeof(BITMAPFILEHEADER), fp); | |
fwrite(&bmp_info, 1, sizeof(BITMAPINFOHEADER), fp); | |
fwrite(data, 1, size, fp); | |
fclose(fp); | |
return 1; | |
} | |
int main(int argc, char **argv) | |
{ | |
int i,j; | |
RGB_data buffer[512][512]; | |
memset(buffer, 0, sizeof(buffer)); | |
for (i = 0; i < 256; i++) | |
{ | |
for (j = 0; j < 256; j++) | |
{ | |
buffer[i][j].g = buffer[i][j].b = 0x07; | |
buffer[i][j].r = 0xff; | |
} | |
} | |
bmp_generator("./test.bmp", 512, 512, (BYTE*)buffer); | |
return EXIT_SUCCESS; | |
} |
@umashankarvisionware: That has to do with a negative stride.
stride: also called scan width
The stride is the width of a single row of pixels(a scan line), rounded up to a four-byte boundary.
If the stride is positive, the bitmap is top-down.
If the stride is negative, the bitmap is bottom-up.
From msdn
static void CalculateStride(int width)
{
int Gdi = 0x00020000;
int Format32bppRgb = 9 | (32 << 8) | (int)Gdi;
// https://github.com/dotnet/corefx/blob/master/src/System.Drawing.Common/src/System/Drawing/Imaging/PixelFormat.cs
int format = Format32bppRgb;
int bitsPerPixel = ((int)format & 0xff00) >> 8;
int bytesPerPixel = (bitsPerPixel + 7) / 8;
int stride = 4 * ((width * bytesPerPixel + 3) / 4);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Image save is rotated image save