home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 February
/
Chip_2001-02_cd1.bin
/
bonus
/
demos
/
CS
/
exp
/
SOURCES
/
GLENGINE
/
image.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-08-20
|
11KB
|
478 lines
#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include "image.h"
#define IMAGE_TEXT_OUT 1
Image::Image () {
paleta = 0;
bitmap = 0;
h = w = 0;
form = OGL_IMAGE_NULL;
}
Image::Image (const char* filename) {
paleta = 0;
bitmap = 0;
h = w = 0;
form = OGL_IMAGE_NULL;
Load(filename);
}
Image::~Image () {
delete[] paleta;
delete[] bitmap;
}
void Image::Scale(int sirka, int vyska)
{
int elementsize = 0;
switch(format()) {
case OGL_IMAGE_RGBA8888:
case OGL_IMAGE_ARGB8888:
elementsize = 4;
break;
case OGL_IMAGE_RGB888:
elementsize = 3;
break;
case OGL_IMAGE_INDEX8:
case OGL_IMAGE_LUMINANCE8:
elementsize = 1;
break;
default:
return;
}
// vyska=h;
// sirka=w;
unsigned char* n_bitmap = new unsigned char[vyska*sirka*elementsize];
unsigned char* n=n_bitmap;
unsigned char* p, *pp;
float xx=0.0,yy=0.0;
float dx=float(w)/sirka;
float dy=float(h)/vyska;
for (int y=0; y<vyska;y++)
{
p=bitmap+(int(yy))*elementsize*w;
for (int x=0; x<sirka;x++)
{
pp=p+(int(xx))*elementsize;
for(int i=elementsize;i;i--) *n++=*pp++;
xx+=dx;
}
xx=0.0;
yy+=dy;
}
delete[] bitmap;
bitmap=n_bitmap;
w=sirka;
h=vyska;
}
void Image::FlipVertical () {
int elementsize = 0;
switch(format()) {
case OGL_IMAGE_RGBA8888:
case OGL_IMAGE_ARGB8888:
elementsize = 4;
break;
case OGL_IMAGE_RGB888:
elementsize = 3;
break;
case OGL_IMAGE_INDEX8:
case OGL_IMAGE_LUMINANCE8:
elementsize = 1;
break;
default:
return;
}
unsigned char *p1, *p2, *pp1, *pp2;
unsigned char x;
int linewidth = width()*elementsize;
p1 = data();
p2 = p1 + linewidth*(height()-1);
int half = height()/2;
for(int i=half; i; i--) {
pp1 = p1;
pp2 = p2;
for(int j=linewidth; j; j--) {
x = *pp1;
*pp1 = *pp2;
*pp2 = x;
pp1++;
pp2++;
}
p1+=linewidth;
p2-=linewidth;
}
}
int Image::LoadBMP (const char* filename)
{
int f;
struct stat *st;
st = (struct stat *) malloc(sizeof(*st));
f = open(filename, O_BINARY|O_RDONLY);
if (f==(-1))
return 0;
fstat(f,st);
int filesize = st->st_size;
unsigned char *buffer = new unsigned char[filesize];
read(f, buffer, filesize);
close(f);
free(st);
header.bfType = *(short*)buffer;
if(header.bfType!=0x4d42)
return 0;
header.bfSize = *(long*)(buffer+2);
header.bfReserved1 = *(short*)(buffer+6);
header.bfReserved2 = *(short*)(buffer+8);
header.bfOffBits = *(long*)(buffer+10);
header.biSize = *(long*)(buffer+14);
header.biWidth = *(long*)(buffer+18);
header.biHeight = *(long*)(buffer+22);
header.biPlanes = *(short*)(buffer+26);
header.biBitCount = *(short*)(buffer+28);
header.biCompression = *(long*)(buffer+30);
header.biSizeImage = *(long*)(buffer+34);
header.biXPelsPerMeter = *(long*)(buffer+38);
header.biYPelsPerMeter = *(long*)(buffer+42);
header.biClrUsed = *(long*)(buffer+46);
header.biClrImportant = *(long*)(buffer+50);
/*
if (IMAGE_TEXT_OUT) printf("bmp size: %ld\n", header.bfSize);
if (IMAGE_TEXT_OUT) printf("width: %ld\n",header.biWidth);
if (IMAGE_TEXT_OUT) printf("height: %ld\n",header.biHeight);
if (IMAGE_TEXT_OUT) printf("planes: %hd\n",header.biPlanes);
if (IMAGE_TEXT_OUT) printf("bpp: %hd\n",header.biBitCount);
if (IMAGE_TEXT_OUT) printf("compression: %ld\n",header.biCompression);
header.biClrUsed ? if (IMAGE_TEXT_OUT) printf(" colors used: %ld, ",header.biClrUsed)
: if (IMAGE_TEXT_OUT) printf(" colors used: ALL, ");
header.biClrImportant ? if (IMAGE_TEXT_OUT) printf("colors important: %ld\n",header.biClrImportant)
: if (IMAGE_TEXT_OUT) printf("colors important: ALL\n");
*/
w = header.biWidth;
h = header.biHeight;
bpp = header.biBitCount;
unsigned char *data;
unsigned char *map, *map2;
unsigned char *pal;
int actualcolors;
switch(bpp) {
// Monochromatic
case 1:
break;
// Indexed 16 color
case 4:
break;
// Indexed 256 color
case 8:
form = OGL_IMAGE_INDEX8;
paleta = new unsigned long[256];
pal = buffer + 54;
actualcolors = header.biClrUsed ? header.biClrUsed : 256;
for(int i=0; i<actualcolors; i++, pal+=4)
paleta[i] = (*pal) | (*(pal+1)<<8) | (*(pal+2)<<16);
data = buffer + header.bfOffBits;
bitmap = new unsigned char[h*w];
switch(header.biCompression) {
case BMP_RGB:
map = bitmap + w*(h-1);
for(int i=h; i; i--)
{
map2=map;
for(int j=w; j; j--)
*map2++ = *data++;
map -= w;
}
break;
case BMP_RLE8:
break;
case BMP_RLE4:
break;
}
break;
// 24bpp images
case 24:
form = OGL_IMAGE_RGBA8888;
data = buffer + header.bfOffBits;
bitmap = new unsigned char[(h*w)<<2];
map = bitmap;
for(int i=h*w; i; i--)
{
*map++ = *(data+2);
*map++ = *(data+1);
*map++ = *data;
*map++ = 255;
data+=3;
// *map++ = *data++;
// *map++ = *data++;
// *map++ = *data++;
// *map++ = 255;
}
FlipVertical();
break;
}
free(buffer);
return 1;
}
int Image::LoadPNG (const char* filename) {
FILE *fp = fopen(filename, "rb");
if(!fp)
{
if (IMAGE_TEXT_OUT) printf("file %s not found\n", filename);
return 0;
}
png_structp png_ptr = png_create_read_struct
(PNG_LIBPNG_VER_STRING, (png_voidp)0,
0, 0);
if (!png_ptr)
{
if (IMAGE_TEXT_OUT) printf("png read structure cannot be created\n");
fclose(fp);
return 0;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
if (IMAGE_TEXT_OUT) printf("png info structure cannot be created\n");
png_destroy_read_struct(&png_ptr,
(png_infopp)0, (png_infopp)0);
fclose(fp);
return 0;
}
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info)
{
png_destroy_read_struct(&png_ptr, &info_ptr,
(png_infopp)0);
fclose(fp);
return 0;
}
png_init_io(png_ptr, fp);
png_read_info(png_ptr, info_ptr);
w = png_get_image_width(png_ptr, info_ptr);
h = png_get_image_height(png_ptr, info_ptr);
png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
png_byte color_type = png_get_color_type(png_ptr, info_ptr);
if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_PALETTE)
{
form = OGL_IMAGE_INDEX8;
png_bytep rowpointers[h];
bitmap = new unsigned char[h*w];
paleta = new unsigned long[256];
png_colorp pngpal;
int num_palette;
bpp=bit_depth;
png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette);
for(png_uint_16 i=0; i<num_palette; i++)
paleta[i] = (pngpal[i].red<<16)|(pngpal[i].green<<8)|(pngpal[i].blue);
for(long i=0; i<h; i++)
rowpointers[i] = (png_bytep)(bitmap+i*w);
png_read_image(png_ptr, rowpointers);
png_read_end(png_ptr, end_info);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return 1;
}
if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_GRAY)
{
// if (IMAGE_TEXT_OUT) printf("Grayscale ");
form = OGL_IMAGE_LUMINANCE8;
png_bytep rowpointers[h];
bitmap = new unsigned char[h*w];
bpp=bit_depth;
for(long i=0; i<h; i++)
rowpointers[i] = (png_bytep)(bitmap+i*w);
png_read_image(png_ptr, rowpointers);
png_read_end(png_ptr, end_info);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
// if (IMAGE_TEXT_OUT) printf("%s\n",filename);
fclose(fp);
return 1;
}
if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB)
{
form = OGL_IMAGE_RGBA8888;
png_bytep rowpointers[h];
bitmap = new unsigned char[h*w*4];
bpp=bit_depth;
for(long i=0; i<h; i++)
rowpointers[i] = (png_bytep)(bitmap+i*w*4);
// png_set_bgr(png_ptr);
png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
png_read_update_info(png_ptr, info_ptr);
png_read_image(png_ptr, rowpointers);
png_read_end(png_ptr, end_info);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return 1;
}
if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
form = OGL_IMAGE_RGBA8888;
png_bytep rowpointers[h];
bitmap = new unsigned char[h*w*4];
bpp=bit_depth;
for(long i=0; i<h; i++)
rowpointers[i] = (png_bytep)(bitmap+i*w*4);
// png_set_bgr(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_read_image(png_ptr, rowpointers);
png_read_end(png_ptr, end_info);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return 1;
}
png_read_end(png_ptr, end_info);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return 0;
}
int Image::LoadJPG(const char *filename)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile; /* source file */
int row_stride; /* physical row width in output buffer */
if ((infile = fopen(filename, "rb")) == 0) {
if (IMAGE_TEXT_OUT) fprintf(stderr, "can't open %s\n", filename);
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
row_stride = cinfo.output_width * cinfo.output_components;
if (IMAGE_TEXT_OUT) cout<<"width: " << cinfo.output_width << ",";
if (IMAGE_TEXT_OUT) cout<<"height: " << cinfo.output_height << ",";
if (IMAGE_TEXT_OUT) cout<<"components: " <<cinfo.output_components << endl;
bitmap = new unsigned char[row_stride*cinfo.output_height];
w = cinfo.output_width;
h = cinfo.output_height;
form = OGL_IMAGE_RGB888;
bpp = cinfo.output_components << 3;
JSAMPROW row_pointer[1];
int i=0;
while (cinfo.output_scanline < cinfo.output_height) {
row_pointer[0] = bitmap+i*row_stride;
i++;
jpeg_read_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return 1;
}
const char *getext(const char *str) {
const char *ext = 0;
while(*str)
{
if(*str==46) ext=str+1;
str++;
}
if(*ext==0)
ext = 0;
return ext;
}
int Image::Load(const char *filename)
{
const char *extension = getext(filename);
if(stricmp(extension, "bmp")==0) {
return LoadBMP(filename);
}
if(stricmp(extension, "png")==0) {
return LoadPNG(filename);
}
if(stricmp(extension, "jpg")==0) {
return LoadJPG(filename);
}
return 0;
}