#include SG_GLU_H
+#include <math.h>
#include <zlib.h>
#include "texture.hxx"
SGTexture::SGTexture()
: texture_id(0),
texture_data(0),
- num_colors(3)
+ num_colors(3),
+ file(0)
{
}
SGTexture::~SGTexture()
{
- if ( texture_data ) {
- delete texture_data;
- }
+ delete[] texture_data;
if ( texture_id != 0 ) {
free_id();
SGTexture::ImageRec *image;
int y;
- if (texture_data)
- delete texture_data;
+ delete[] texture_data;
image = ImageOpen(name);
if(!image) {
SGTexture::read_rgb_texture(const char *name)
{
GLubyte *ptr;
- GLubyte *rbuf, *gbuf, *bbuf, *abuf;
+ GLubyte *rbuf, *gbuf, *bbuf;
SGTexture::ImageRec *image;
int y;
- if (texture_data)
- delete texture_data;
+ delete[] texture_data;
image = ImageOpen(name);
if(!image) {
texture_width = image->xsize;
texture_height = image->ysize;
- if (image->zsize != 3 && image->zsize != 4) {
+ if (image->zsize < 1 || image->zsize > 4) {
ImageClose(image);
errstr = WRONG_COUNT;
return;
}
- texture_data = new GLubyte[ image->xsize * image->ysize * 3 ];
num_colors = 3;
+ texture_data = new GLubyte[ image->xsize * image->ysize * num_colors ];
rbuf = new GLubyte[ image->xsize ];
gbuf = new GLubyte[ image->xsize ];
bbuf = new GLubyte[ image->xsize ];
- abuf = new GLubyte[ image->xsize ];
- if(!texture_data || !rbuf || !gbuf || !bbuf || !abuf) {
- delete texture_data;
- delete rbuf;
- delete gbuf;
- delete bbuf;
- delete abuf;
+ if(!texture_data || !rbuf || !gbuf || !bbuf) {
+ delete[] texture_data;
+ delete[] rbuf;
+ delete[] gbuf;
+ delete[] bbuf;
errstr = OUT_OF_MEMORY;
return;
}
ptr = texture_data;
for(y=0; y<image->ysize; y++) {
- if(image->zsize == 4) {
+ if(image->zsize == 4 || image->zsize == 3) {
ImageGetRow(image,rbuf,y,0);
ImageGetRow(image,gbuf,y,1);
ImageGetRow(image,bbuf,y,2);
- ImageGetRow(image,abuf,y,3); // discard
- rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
- ptr += (image->xsize * 3);
} else {
ImageGetRow(image,rbuf,y,0);
- ImageGetRow(image,gbuf,y,1);
- ImageGetRow(image,bbuf,y,2);
- rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
- ptr += (image->xsize * 3);
+ memcpy(gbuf,rbuf,image->xsize);
+ memcpy(bbuf,rbuf,image->xsize);
}
+ rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
+ ptr += (image->xsize * num_colors);
}
ImageClose(image);
- delete rbuf;
- delete gbuf;
- delete bbuf;
- delete abuf;
+ delete[] rbuf;
+ delete[] gbuf;
+ delete[] bbuf;
}
SGTexture::ImageRec *image;
int y;
- if (texture_data)
- delete texture_data;
+ delete[] texture_data;
image = ImageOpen(name);
if(!image) {
texture_width = image->xsize;
texture_height = image->ysize;
- if (image->zsize != 3 && image->zsize != 4) {
+ if (image->zsize < 1 || image->zsize > 4) {
ImageClose(image);
errstr = WRONG_COUNT;
return;
}
- texture_data = new GLubyte[ image->xsize * image->ysize * 4 ];
num_colors = 4;
+ texture_data = new GLubyte[ image->xsize * image->ysize * num_colors ];
rbuf = new GLubyte[ image->xsize ];
gbuf = new GLubyte[ image->xsize ];
bbuf = new GLubyte[ image->xsize ];
abuf = new GLubyte[ image->xsize ];
if(!texture_data || !rbuf || !gbuf || !bbuf || !abuf) {
- delete texture_data;
- delete rbuf;
- delete gbuf;
- delete bbuf;
- delete abuf;
+ delete[] texture_data;
+ delete[] rbuf;
+ delete[] gbuf;
+ delete[] bbuf;
+ delete[] abuf;
errstr = OUT_OF_MEMORY;
return;
}
ptr = texture_data;
- memset(abuf, 255, image->xsize);
for(y=0; y<image->ysize; y++) {
if(image->zsize == 4) {
ImageGetRow(image,rbuf,y,0);
ImageGetRow(image,gbuf,y,1);
ImageGetRow(image,bbuf,y,2);
ImageGetRow(image,abuf,y,3);
- rgbatorgba(rbuf,gbuf,bbuf,abuf,ptr,image->xsize);
- ptr += (image->xsize * 4);
- } else {
+ } else if(image->zsize == 3) {
ImageGetRow(image,rbuf,y,0);
ImageGetRow(image,gbuf,y,1);
ImageGetRow(image,bbuf,y,2);
- rgbatorgba(rbuf,gbuf,bbuf,abuf,ptr,image->xsize);
- ptr += (image->xsize * 3);
+ memset(abuf, 255, image->xsize);
+ } else if(image->zsize == 2) {
+ ImageGetRow(image,rbuf,y,0);
+ memcpy(gbuf,rbuf,image->xsize);
+ memcpy(bbuf,rbuf,image->xsize);
+ ImageGetRow(image,abuf,y,1);
+ } else {
+ ImageGetRow(image,rbuf,y,0);
+ memcpy(gbuf,rbuf,image->xsize);
+ memcpy(bbuf,rbuf,image->xsize);
+ memset(abuf, 255, image->xsize);
}
+ rgbatorgba(rbuf,gbuf,bbuf,abuf,ptr,image->xsize);
+ ptr += (image->xsize * num_colors);
}
ImageClose(image);
- delete rbuf;
- delete gbuf;
- delete bbuf;
- delete abuf;
+ delete[] rbuf;
+ delete[] gbuf;
+ delete[] bbuf;
+ delete[] abuf;
}
void
SGTexture::ImageRec *image;
int y;
- if (texture_data)
- delete texture_data;
+ delete[] texture_data;
image = RawImageOpen(name);
ptr = texture_data;
for(y=0; y<256; y++) {
- gzread(image->gzfile, ptr, 256*3);
+ gzread(image->file, ptr, 256*3);
ptr+=256*3;
}
ImageClose(image);
SGTexture::ImageRec *image;
int xy;
- if (texture_data)
- delete texture_data;
+ delete[] texture_data;
//it wouldn't make sense to write a new function ...
image = RawImageOpen(name);
ptr = texture_data;
for(xy=0; xy<(256*256); xy++) {
- gzread(image->gzfile, c, 1);
+ gzread(image->file, c, 1);
//look in the table for the right colours
ptr[0]=msfs_colour[c[0]][0];
void
SGTexture::write_texture(const char *name) {
- SGTexture::ImageRec *image;
- int x, y;
-
- image=ImageWriteOpen(name);
-
- GLubyte *ptr = texture_data;
- for (y=0; y<texture_height; y++) {
- for (x=0; x<texture_width; x++) {
- image->tmp[x]=*ptr;
- ptr = ptr + num_colors;
- }
- fwrite(image->tmp, 1, texture_width, image->file);
- }
-
- if (num_colors > 1) {
- ptr = texture_data + 1;
- for (y=0; y<texture_height; y++) {
- for (x=0; x<texture_width; x++) {
- image->tmp[x]=*ptr;
- ptr = ptr + num_colors;
- }
- fwrite(image->tmp, 1, texture_width, image->file);
- }
-
- if (num_colors > 2) {
- ptr = texture_data + 2;
- for (y=0; y<texture_height; y++) {
- for (x=0; x<texture_width; x++) {
- image->tmp[x]=*ptr;
- ptr = ptr + num_colors;
- }
- fwrite(image->tmp, 1, texture_width, image->file);
- }
-
- if (num_colors > 3) {
- ptr = texture_data + 3;
- for (y=0; y<texture_height; y++) {
- for (x=0; x<texture_width; x++) {
- image->tmp[x]=*ptr;
- ptr = ptr + num_colors;
- }
- fwrite(image->tmp, 1, texture_width, image->file);
- }
+ SGTexture::ImageRec *image = ImageWriteOpen(name);
+
+ for (int c=0; c<num_colors; c++) {
+ GLubyte *ptr = texture_data + c;
+ for (int y=0; y<texture_height; y++) {
+ for (int x=0; x<texture_width; x++) {
+ image->tmp[x]=*ptr;
+ ptr = ptr + num_colors;
}
+ fwrite(image->tmp, 1, texture_width, file);
}
}
void
-SGTexture::set_pixel(GLuint x, GLuint y, sgVec3 &c)
+SGTexture::set_pixel(GLuint x, GLuint y, GLubyte *c)
{
if (!texture_data) {
errstr = NO_TEXTURE;
return;
}
- unsigned int pos = (x + y*texture_width)*3;
- texture_data[pos] = (unsigned char)(c[0] * 256);
- texture_data[pos+1] = (unsigned char)(c[1] * 256);
- texture_data[pos+2] = (unsigned char)(c[2] * 256);
+ unsigned int pos = (x + y*texture_width) * num_colors;
+ memcpy(texture_data+pos, c, num_colors);
}
-float *
+GLubyte *
SGTexture::get_pixel(GLuint x, GLuint y)
{
- static sgVec3 c;
+ static GLubyte c[4] = {0, 0, 0, 0};
- sgSetVec3(c, 0, 0, 0);
if (!texture_data) {
errstr = NO_TEXTURE;
return c;
}
- unsigned int pos = (x + y*texture_width)*3;
-
- sgSetVec3(c, texture_data[pos], texture_data[pos+1], texture_data[pos+2]);
+ unsigned int pos = (x + y*texture_width)*num_colors;
+ memcpy(c, texture_data + pos, num_colors);
return c;
}
}
image = new SGTexture::ImageRec;
+ memset(image, 0, sizeof(SGTexture::ImageRec));
if (image == 0) {
errstr = OUT_OF_MEMORY;
return 0;
}
- if ((image->gzfile = gzopen(fileName, "rb")) == 0) {
+ if ((image->file = gzopen(fileName, "rb")) == 0) {
errstr = FILE_OPEN_ERROR;
return 0;
}
- gzread(image->gzfile, image, 12);
+ gzread(image->file, image, 12);
if (swapFlag) {
ConvertShort(&image->imagic, 6);
return 0;
}
image->rleEnd = 512 + (2 * x);
- gzseek(image->gzfile, 512, SEEK_SET);
- gzread(image->gzfile, image->rowStart, x);
- gzread(image->gzfile, image->rowSize, x);
+ gzseek(image->file, 512, SEEK_SET);
+ gzread(image->file, image->rowStart, x);
+ gzread(image->file, image->rowSize, x);
if (swapFlag) {
ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
void
SGTexture::ImageClose(SGTexture::ImageRec *image) {
- if (image->gzfile) gzclose(image->gzfile);
- if (image->file) fclose(image->file);
- delete image->tmp;
+ if (image->file) gzclose(image->file);
+ if (file) fclose(file);
+ delete[] image->tmp;
+ delete[] image->rowStart;
+ delete[] image->rowSize;
delete image;
}
}
image = new SGTexture::ImageRec;
+ memset(image, 0, sizeof(SGTexture::ImageRec));
if (image == 0) {
errstr = OUT_OF_MEMORY;
return 0;
}
- if ((image->gzfile = gzopen(fileName, "rb")) == 0) {
+ if ((image->file = gzopen(fileName, "rb")) == 0) {
errstr = FILE_OPEN_ERROR;
return 0;
}
- gzread(image->gzfile, image, 12);
+ gzread(image->file, image, 12);
if (swapFlag) {
ConvertShort(&image->imagic, 6);
//just allocate a pseudo value as I'm too lazy to change ImageClose()...
- image->tmp = new GLubyte;
+ image->tmp = new GLubyte[1];
if (image->tmp == 0) {
errstr = OUT_OF_MEMORY;
}
image = new SGTexture::ImageRec;
+ memset(image, 0, sizeof(SGTexture::ImageRec));
if (image == 0) {
errstr = OUT_OF_MEMORY;
return 0;
}
- if ((image->file = fopen(fileName, "w")) == 0) {
+ if ((file = fopen(fileName, "wb")) == 0) {
errstr = FILE_OPEN_ERROR;
return 0;
}
image->imagic = 474;
image->type = 0x0001;
- image->dim = 0;
+ image->dim = (num_colors > 1) ? 3 : 2;
image->xsize = texture_width;
image->ysize = texture_height;
image->zsize = num_colors;
- fwrite(image, 1, 12, image->file);
-
- fseek(image->file, 512, SEEK_SET);
if (swapFlag) {
ConvertShort(&image->imagic, 6);
}
+ fwrite(image, 1, 12, file);
+ fseek(file, 512, SEEK_SET);
+
image->tmp = new GLubyte[ image->xsize * 256 ];
if (image->tmp == 0) {
errstr = OUT_OF_MEMORY;
return 0;
}
image->rleEnd = 512 + (2 * x);
- fseek(image->file, 512, SEEK_SET);
- fread(image->rowStart, 1, x, image->file);
- fread(image->rowSize, 1, x, image->file);
+ fseek(file, 512, SEEK_SET);
+ fread(image->rowStart, 1, x, file);
+ fread(image->rowSize, 1, x, file);
if (swapFlag) {
ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
}
}
+
return image;
}
int count;
if ((image->type & 0xFF00) == 0x0100) {
- gzseek(image->gzfile, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
- gzread(image->gzfile, image->tmp,
- (unsigned int)image->rowSize[y+z*image->ysize]);
+ gzseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
+ int size = image->rowSize[y+z*image->ysize];
+ gzread(image->file, image->tmp, size);
iPtr = image->tmp;
oPtr = buf;
- for (;;) {
+ for (GLubyte *limit = iPtr + size; iPtr < limit;) {
pixel = *iPtr++;
count = (int)(pixel & 0x7F);
if (!count) {
return;
}
if (pixel & 0x80) {
- while (count--) {
+ while (iPtr < limit && count--) {
*oPtr++ = *iPtr++;
}
- } else {
+ } else if (iPtr < limit) {
pixel = *iPtr++;
while (count--) {
*oPtr++ = pixel;
}
}
} else {
- gzseek(image->gzfile, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
+ gzseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
SEEK_SET);
- gzread(image->gzfile, buf, image->xsize);
+ gzread(image->file, buf, image->xsize);
}
}
int count;
if ((image->type & 0xFF00) == 0x0100) {
- fseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
+ fseek(file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
fread( image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
- image->file);
+ file);
iPtr = image->tmp;
oPtr = buf;
}
}
} else {
- fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
+ fseek(file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
SEEK_SET);
- fread(buf, 1, image->xsize, image->file);
+ fread(buf, 1, image->xsize, file);
}
}
}
}
+
+void
+SGTexture::make_monochrome(float contrast, GLubyte r, GLubyte g, GLubyte b) {
+
+ if (num_colors >= 3)
+ return;
+
+ GLubyte ap[3];
+ for (int y=0; y<texture_height; y++)
+ for (int x=0; x<texture_width; x++)
+ {
+ GLubyte *rgb = get_pixel(x,y);
+ GLubyte avg = (rgb[0] + rgb[1] + rgb[2]) / 3;
+
+ if (contrast != 1.0) {
+ float pixcol = -1.0 + (avg/128);
+ avg = 128 + int(128*pow(pixcol, contrast));
+ }
+
+ ap[0] = avg*r/255;
+ ap[1] = avg*g/255;
+ ap[2] = avg*b/255;
+
+ set_pixel(x,y,ap);
+ }
+}
+
+
+void
+SGTexture::make_grayscale(float contrast) {
+ if (num_colors < 3)
+ return;
+
+ int colors = (num_colors == 3) ? 1 : 2;
+ GLubyte *map = new GLubyte[ texture_width * texture_height * colors ];
+
+ for (int y=0; y<texture_height; y++)
+ for (int x=0; x<texture_width; x++)
+ {
+ GLubyte *rgb = get_pixel(x,y);
+ GLubyte avg = (rgb[0] + rgb[1] + rgb[2]) / 3;
+
+ if (contrast != 1.0) {
+ float pixcol = -1.0 + (avg/128);
+ avg = 128 + int(128*pow(pixcol, contrast));
+ }
+
+ int pos = (x + y*texture_width)*colors;
+ map[pos] = avg;
+ if (colors > 1)
+ map[pos+1] = rgb[3];
+ }
+
+ delete[] texture_data;
+ texture_data = map;
+ num_colors = colors;
+}
+
+
+void
+SGTexture::make_maxcolorwindow() {
+ GLubyte minmaxc[2] = {255, 0};
+
+ int pos = 0;
+ int max = num_colors;
+ if (num_colors == 2) max = 1;
+ if (num_colors == 4) max = 3;
+ while (pos < texture_width * texture_height * num_colors) {
+ for (int i=0; i < max; i++) {
+ GLubyte c = texture_data[pos+i];
+ if (c < minmaxc[0]) minmaxc[0] = c;
+ if (c > minmaxc[1]) minmaxc[1] = c;
+ }
+ pos += num_colors;
+ }
+
+ GLubyte offs = minmaxc[0];
+ float factor = 255.0 / float(minmaxc[1] - minmaxc[0]);
+ // printf("Min: %i, Max: %i, Factor: %f\n", offs, minmaxc[1], factor);
+
+ pos = 0;
+ while (pos < texture_width * texture_height * num_colors) {
+ for (int i=0; i < max; i++) {
+ texture_data[pos+i] -= offs;
+ texture_data[pos+i] = int(factor * texture_data[pos+i]);
+ }
+ pos += num_colors;
+ }
+}
+
+
+void
+SGTexture::make_normalmap(float brightness, float contrast) {
+ make_grayscale(contrast);
+ make_maxcolorwindow();
+
+ int colors = (num_colors == 1) ? 3 : 4;
+ bool alpha = (colors > 3);
+ int tsize = texture_width * texture_height * colors;
+ GLubyte *map = new GLubyte[ tsize ];
+
+ int mpos = 0, dpos = 0;
+ for (int y=0; y<texture_height; y++) {
+ int ytw = y*texture_width;
+
+ for (int x=0; x<texture_width; x++)
+ {
+ int xp1 = (x < (texture_width-1)) ? x+1 : 0;
+ int yp1 = (y < (texture_height-1)) ? y+1 : 0;
+ int posxp1 = (xp1 + ytw)*num_colors;
+ int posyp1 = (x + yp1*texture_width)*num_colors;
+
+ GLubyte c = texture_data[dpos];
+ GLubyte cx1 = texture_data[posxp1];
+ GLubyte cy1 = texture_data[posyp1];
+
+ if (alpha) {
+ GLubyte a = texture_data[dpos+1];
+ GLubyte ax1 = texture_data[posxp1+1];
+ GLubyte ay1 = texture_data[posyp1+1];
+
+ c = (c + a)/2;
+ cx1 = (cx1 + ax1)/2;
+ cy1 = (cy1 + ay1)/2;
+
+ map[mpos+3] = a;
+ }
+
+ map[mpos+0] = (128+(cx1-c)/2);
+ map[mpos+1] = (128+(cy1-c)/2);
+ map[mpos+2] = 127+int(brightness*128); // 255-c/2;
+
+ mpos += colors;
+ dpos += num_colors;
+ }
+ }
+
+ delete[] texture_data;
+ texture_data = map;
+ num_colors = colors;
+}
+
+
+void
+SGTexture::make_bumpmap(float brightness, float contrast) {
+ make_grayscale(contrast);
+
+ int colors = (num_colors == 1) ? 1 : 2;
+ GLubyte *map = new GLubyte[ texture_width * texture_height * colors ];
+
+ for (int y=0; y<texture_height; y++)
+ for (int x=0; x<texture_width; x++)
+ {
+ int mpos = (x + y*texture_width)*colors;
+ int dpos = (x + y*texture_width)*num_colors;
+
+ int xp1 = (x < (texture_width-1)) ? x+1 : 0;
+ int yp1 = (y < (texture_height-1)) ? y+1 : 0;
+ int posxp1 = (xp1 + y*texture_width)*num_colors;
+ int posyp1 = (x + yp1*texture_width)*num_colors;
+
+ map[mpos] = (127 - ((texture_data[dpos]-texture_data[posxp1]) -
+ ((texture_data[dpos]-texture_data[posyp1]))/4))/2;
+ if (colors > 1)
+ map[mpos+1] = texture_data[dpos+1];
+ }
+
+ delete[] texture_data;
+ texture_data = map;
+ num_colors = colors;
+}
+