source: nanovis/trunk/imgLoaders/BMPImageLoaderImpl.cpp @ 4923

Last change on this file since 4923 was 2947, checked in by ldelgass, 12 years ago

Fix bitmap loader - green channel wasn't being copied when src and dst had
different number of components. Also set full opacity on images with 8 bit
source data. Note that loader still loads images from top to bottom rather
than OpenGLs bottom to top, so images will be flipped if copied into a GL
texture.

  • Property svn:eol-style set to native
File size: 4.7 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2#include <stdio.h>
3#include <memory.h>
4#include <stdlib.h>
5
6#include "BMPImageLoaderImpl.h"
7#include "Image.h"
8#include "Trace.h"
9
10BMPImageLoaderImpl::BMPImageLoaderImpl()
11{
12}
13
14BMPImageLoaderImpl::~BMPImageLoaderImpl()
15{
16}
17
18// I referred to cjbackhouse@hotmail.com                www.backhouse.tk
19Image *BMPImageLoaderImpl::load(const char *fileName)
20{
21    TRACE("BMP loader\n");
22    Image *image = NULL;
23
24    TRACE("opening image file \"%s\"\n", fileName);
25    FILE *f = fopen(fileName, "rb");
26
27    if (!f)  {
28        TRACE("File not found\n");
29        return 0;
30    }
31
32    char header[54];
33    if (fread(&header, 54, 1, f) != 1) {
34        TRACE("can't read header of BMP file\n");
35        return 0;
36    }
37
38    if (header[0] != 'B' ||  header[1] != 'M') {
39        TRACE("File is not BMP format\n");
40        return 0;
41    }
42
43    //it seems gimp sometimes makes its headers small, so we have to do
44    //this. hence all the fseeks
45    int offset = *(unsigned int*)(header+10);
46
47    const unsigned int width = *(int*)(header+18);
48    const unsigned int height = *(int*)(header+22);
49
50    int bits = int(header[28]);           //colourdepth
51
52    TRACE("image width = %d height = %d bits=%d\n", width, height, bits);
53
54    image = new Image(width, height, _targetImageFormat,
55                      Image::IMG_UNSIGNED_BYTE, NULL);
56
57    TRACE("image created\n");
58
59    unsigned char *bytes = (unsigned char *)image->getImageBuffer();
60    memset(bytes, 0, sizeof(unsigned char) * width * height * _targetImageFormat);
61
62    TRACE("reset image buffer\n");
63
64    unsigned int x, y;
65    unsigned char cols[256*4];  //colourtable
66    switch (bits) {
67    case 24:
68        fseek(f, offset, SEEK_SET);
69        if (_targetImageFormat == Image::IMG_RGB) {
70            if (fread(bytes, width*height*3, 1, f) != 1) {
71                ERROR("can't read image data\n");
72            }
73            for (x = 0; x < width*height*3; x += 3)  { //except the format is BGR, grr
74                unsigned char temp = bytes[x];
75                bytes[x] = bytes[x+2];
76                bytes[x+2] = temp;
77            }
78        } else if (_targetImageFormat == Image::IMG_RGBA) {
79            unsigned char *buff = (unsigned char*)malloc(width * height * sizeof(unsigned char) * 3);
80            if (fread(buff, width*height*3, 1, f) != 1) {
81                ERROR("can't read BMP image data\n");
82            }
83            for (x = 0, y = 0; x < width*height*3; x += 3, y += 4) {       //except the format is BGR, grr
84                bytes[y] = buff[x+2];
85                bytes[y+1] = buff[x+1];
86                bytes[y+2] = buff[x];
87                bytes[y+3] = 255;
88            }
89            free(buff);
90        }
91        break;
92    case 32:
93        fseek(f, offset, SEEK_SET);
94        if (_targetImageFormat == Image::IMG_RGBA) {
95            if (fread(bytes, width*height*4, 1, f) != 1) {
96                ERROR("can't read image data\n");
97            }
98            for (x = 0; x < width*height*4; x += 4)  { //except the format is BGR, grr
99                unsigned char temp = bytes[x];
100                bytes[x] = bytes[x+2];
101                bytes[x+2] = temp;
102            }
103        } else if (_targetImageFormat == Image::IMG_RGB) {
104            unsigned char *buff = (unsigned char*)malloc(width * height * sizeof(unsigned char) * 4);
105            if (fread(buff, width*height*4, 1, f) != 1) {
106                ERROR("can't read BMP image data\n");
107            }
108            for (x = 0, y = 0; x < width*height*4; x += 4, y += 3) {       //except the format is BGR, grr
109                bytes[y] = buff[x+2];
110                bytes[y+1] = buff[x+1];
111                bytes[y+2] = buff[x];
112            }
113            free(buff);
114        }
115        break;
116    case 8:
117        if (fread(cols, 256 * 4, 1, f) != 1) {
118            ERROR("can't read colortable from BMP file\n");
119        }
120        fseek(f,offset,SEEK_SET); 
121        for (y = 0; y < height; ++y) {  //(Notice 4bytes/col for some reason)
122            for (x = 0; x < width; ++x) {
123                unsigned char byte;                 
124                if (fread(&byte, 1, 1, f) != 1) {
125                    ERROR("error reading BMP file\n");
126                }
127                for (int c = 0; c < 3; ++c) {
128                    //bytes[(y*width+x)*3+c] = cols[byte*4+2-c];        //and look up in the table
129                    bytes[(y*width+x)*_targetImageFormat + c] = cols[byte*4+2-c];       //and look up in the table
130                }
131                if (_targetImageFormat == Image::IMG_RGBA) {
132                    bytes[(y*width+x)*_targetImageFormat + 3] = 255;
133                }
134            }
135        }
136        break;
137    }
138
139    TRACE("image initialized\n");
140    return image;
141}
Note: See TracBrowser for help on using the repository browser.