#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <time.h>
#include <memory.h>
#define Width 512
#define Height 512
unsigned char *ipix;
int h, w;
unsigned char
**bmp;
const size_t BYTES_PER_PIX = 3;
const size_t HEADER_SIZE = 54;
// 處理byte order
inline char* PutWord(char* buf, unsigned
w)
{
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3]
= w >> 24;
return buf + 4;
}
// 假設data每個資料都是一個pixel且使用windows的RGB()編碼
void WriteBMP(const char* fileName, const
unsigned* data, size_t width, size_t height)
{
size_t rowSize = width * BYTES_PER_PIX;
size_t pad = (4 - (rowSize & 0x03)) & 0x03;
size_t dataSize = (rowSize + pad) * height;
char header[HEADER_SIZE] = "BM";
char* ph = header + 2;
ph = PutWord(ph, dataSize + HEADER_SIZE);
ph = PutWord(ph, 0);
ph = PutWord(ph, HEADER_SIZE);
ph
= PutWord(ph, 40);
ph = PutWord(ph, width);
ph = PutWord(ph, height);
*ph++ = 1;
*ph++ = 0;
*ph++ = BYTES_PER_PIX * 8;
*ph++ = 0;
ph = PutWord(ph, 0);
ph = PutWord(ph, dataSize);
ph = PutWord(ph, 0);
ph = PutWord(ph, 0);
ph = PutWord(ph, 0);
ph = PutWord(ph, 0);
FILE* fout = fopen(fileName, "wb");
char* rowData = (char*)
malloc(rowSize + pad);
size_t i, j, k = 0;
fwrite(header, 1, HEADER_SIZE, fout);
memset(rowData, 0, rowSize + pad);
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
char r = data[k];
char g = data[k] >> 8;
char b = data[k] >> 16;
rowData[i*3] = b;
rowData[i*3+1] = g;
rowData[i*3+2] = r;
++k;
}
fwrite(rowData, 1, rowSize + pad, fout);
}
free(rowData);
fclose(fout);
}
int read_bmp(char *filename,
unsigned char
***bmp, int *height, int
*width)
{
printf("\n####################
read_bmp ####################\n");
long
*hed;
int i, j,
k, w;
unsigned char head[1079], l, mod, *tmp_buf;
FILE *f;
hed = (long
*) &head[2];
f = fopen(filename, "rb");
if ((f = fopen(filename, "rb")) == NULL)
return 1;
if
(fread(head, 1, 54, f) != 54)
return 2;
if
(head[0] != 'B' || head[1] != 'M')
// BMP head
return 3;
fseek(f, 0, SEEK_END);
if
(ftell(f) - hed[0])
return 4; // file size != internal record
mod = head[28]; // bit / pixel
if (mod != 1 && mod != 8)
return 5;
// 不是黑白或灰階
if
(head[30])
return 6;
// 不會讀壓縮的BMP
*width = hed[4], *height = hed[5];
printf("hed[4] = %d hed[5] = %d\n",hed[4],hed[5]);
if
((tmp_buf = (unsigned char
*) malloc(hed[8])) == NULL)
return 7;
// Not enough Memory
if (
!(*bmp = (unsigned
char **)malloc(*height *sizeof(**bmp))))
return 8;
// Not enough Memory
if (
(**bmp = (unsigned char
*) malloc(*width * *height + 7)) ==
NULL)
return 9;
// Not enough Memory
printf("*************************
hed[8] = %d\n",hed[8]);
fseek(f, hed[2], SEEK_SET);
// to bmp data start
if
(fread(tmp_buf, 1, (size_t)hed[8]-1, f) != hed[8]-1) //
read error?
return 10;
// 讀檔有問題
for
(w=i=0; i<*height; i++, w+=*width) //
Calculate index for speedup
(*bmp)[i] = &(**bmp)[w];
if (mod
== 1) {
w = (int) ( ((*width-1) >> 5) +1 )
<< 2;
for (i=(int)(*height-1);
i>=0; i--) {
for
(j=0; j<*width-7; j+=8) {
l = tmp_buf[i*w +
(j>>3)];
for
(k=0; k<8; k++) {
(**bmp)[(*height-i-1)**width + j + k] = l & 128 ? 0 : 255;
l <<= 1;
}
}
l = tmp_buf[i*w + (j>>3)];
for
(k=0; k<(*width&7); k++) {
(**bmp)[(*height-i-1)**width
+ j + k] = l & 128 ? 0 : 255;
l <<= 1;
}
}
}
else if (mod == 8)
{
w = (int) (((*width-1)>>2) +1)
<< 2;
for (i=(int)(*height-1);
i>=0; i--)
{
k = *height - i -1;
for
(j=0; j<*width; j++)
(*bmp)[k][j] = tmp_buf[i*w +
j];
}
}
free(tmp_buf);
if
(fclose(f)) return 11; // 不能閉檔
return
0;
// 成功
}
void OnKey(unsigned char key, int x, int y)
{
switch(key) {
case 27:
glutDestroyWindow(
glutGetWindow() );
free(*bmp);
free(bmp);
exit(0);
break;
}
glutPostRedisplay();
//令視窗重繪
}
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glRasterPos2i( -1, -1 );
glDrawPixels(w, h, GL_LUMINANCE, GL_UNSIGNED_BYTE, *bmp);
glutSwapBuffers(); //glutSwapBuffers內含glFlush
}
void
bmpUpsideDown()
{
// BMP倒立
for
(int i=h/2; --i>=0; ) {
int y = h -1 -i;
for (int j=w;
--j>=0; ) {
char c=bmp[i][j];
bmp[i][j] = bmp[y][j]; bmp[y][j] = c;
}
}
}
// main
int main(int argc, char **argv)
{
clock_t start, end;
int i, j;
char filename1[] = "Lena512.bmp";
i=read_bmp(filename1, &bmp, &h,
&w);
if (i == 0)
{
bmpUpsideDown();
char filename2[] = "b.bmp";
WriteBMP(filename2, &bmp, &h, &w);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE |
GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(w, h);
glutInitWindowPosition (100, 100);
glutCreateWindow("Hello");
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glutKeyboardFunc(OnKey);
glutDisplayFunc(display);
glutMainLoop();
}
return 0;
}