// ============================================================== // This file is part of Glest Shared Library (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #include "math_wrapper.h" #include "pixmap.h" #include #include #include #include "util.h" #include "math_util.h" #include "randomgen.h" #include "FileReader.h" #include "ImageReaders.h" #include #include #include #include #include "opengl.h" #include "leak_dumper.h" using namespace Shared::Util; using namespace std; using namespace Shared::Graphics::Gl; namespace Shared{ namespace Graphics{ using namespace Util; // ===================================================== // file structs // ===================================================== #pragma pack(push, 1) struct BitmapFileHeader{ uint8 type1; uint8 type2; uint32 size; uint16 reserved1; uint16 reserved2; uint32 offsetBits; }; struct BitmapInfoHeader{ uint32 size; int32 width; int32 height; uint16 planes; uint16 bitCount; uint32 compression; uint32 sizeImage; int32 xPelsPerMeter; int32 yPelsPerMeter; uint32 clrUsed; uint32 clrImportant; }; struct TargaFileHeader{ int8 idLength; int8 colourMapType; int8 dataTypeCode; int16 colourMapOrigin; int16 colourMapLength; int8 colourMapDepth; int16 xOrigin; int16 yOrigin; int16 width; int16 height; int8 bitsPerPixel; int8 imageDescriptor; }; #pragma pack(pop) const int tgaUncompressedRgb= 2; const int tgaUncompressedBw= 3; void CalculatePixelsCRC(uint8 *pixels,uint64 pixelByteCount, Checksum &crc) { // crc = Checksum(); // for(uint64 i = 0; i < pixelByteCount; ++i) { // crc.addByte(pixels[i]); // } } // ===================================================== // class PixmapIoTga // ===================================================== PixmapIoTga::PixmapIoTga() { file= NULL; } PixmapIoTga::~PixmapIoTga() { if(file != NULL) { fclose(file); file=NULL; } } void PixmapIoTga::openRead(const string &path) { #ifdef WIN32 file= _wfopen(utf8_decode(path).c_str(), L"rb"); #else file= fopen(path.c_str(),"rb"); #endif if (file == NULL) { throw runtime_error("Can't open TGA file: "+ path); } //read header TargaFileHeader fileHeader; size_t readBytes = fread(&fileHeader, sizeof(TargaFileHeader), 1, file); //check that we can load this tga file if(fileHeader.idLength != 0) { throw runtime_error(path + ": id field is not 0"); } if(fileHeader.dataTypeCode != tgaUncompressedRgb && fileHeader.dataTypeCode != tgaUncompressedBw) { throw runtime_error(path + ": only uncompressed BW and RGB targa images are supported"); } //check bits per pixel if(fileHeader.bitsPerPixel != 8 && fileHeader.bitsPerPixel != 24 && fileHeader.bitsPerPixel !=32) { throw runtime_error(path + ": only 8, 24 and 32 bit targa images are supported"); } h= fileHeader.height; w= fileHeader.width; components= fileHeader.bitsPerPixel / 8; } void PixmapIoTga::read(uint8 *pixels) { read(pixels, components); } void PixmapIoTga::read(uint8 *pixels, int components) { for(int i=0; icomponents == 1) { size_t readBytes = fread(&l, 1, 1, file); r= l; g= l; b= l; a= 255; } else { size_t readBytes = fread(&b, 1, 1, file); readBytes = fread(&g, 1, 1, file); readBytes = fread(&r, 1, 1, file); if(this->components == 4) { readBytes = fread(&a, 1, 1, file); } else { a= 255; } l= (r+g+b)/3; } switch(components) { case 1: pixels[i]= l; break; case 3: pixels[i]= r; pixels[i+1]= g; pixels[i+2]= b; break; case 4: pixels[i]= r; pixels[i+1]= g; pixels[i+2]= b; pixels[i+3]= a; break; } } } void PixmapIoTga::openWrite(const string &path, int w, int h, int components) { this->w= w; this->h= h; this->components= components; #ifdef WIN32 file= _wfopen(utf8_decode(path).c_str(), L"wb"); #else file= fopen(path.c_str(),"wb"); #endif if (file == NULL) { throw runtime_error("Can't open TGA file: "+ path); } TargaFileHeader fileHeader; memset(&fileHeader, 0, sizeof(TargaFileHeader)); fileHeader.dataTypeCode= components==1? tgaUncompressedBw: tgaUncompressedRgb; fileHeader.bitsPerPixel= components*8; fileHeader.width= w; fileHeader.height= h; fileHeader.imageDescriptor= components==4? 8: 0; fwrite(&fileHeader, sizeof(TargaFileHeader), 1, file); } void PixmapIoTga::write(uint8 *pixels) { if(components == 1) { fwrite(pixels, h*w, 1, file); } else { for(int i=0; iw= w; this->h= h; this->components= components; #ifdef WIN32 file= _wfopen(utf8_decode(path).c_str(), L"wb"); #else file= fopen(path.c_str(),"wb"); #endif if (file == NULL) { throw runtime_error("Can't open BMP file for writing: "+ path); } BitmapFileHeader fileHeader; fileHeader.type1='B'; fileHeader.type2='M'; fileHeader.offsetBits=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader); fileHeader.size=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader)+3*h*w; fwrite(&fileHeader, sizeof(BitmapFileHeader), 1, file); //info header BitmapInfoHeader infoHeader; infoHeader.bitCount=24; infoHeader.clrImportant=0; infoHeader.clrUsed=0; infoHeader.compression=0; infoHeader.height= h; infoHeader.planes=1; infoHeader.size=sizeof(BitmapInfoHeader); infoHeader.sizeImage=0; infoHeader.width= w; infoHeader.xPelsPerMeter= 0; infoHeader.yPelsPerMeter= 0; fwrite(&infoHeader, sizeof(BitmapInfoHeader), 1, file); } void PixmapIoBmp::write(uint8 *pixels) { for (int i=0; ipath = path; this->w= w; this->h= h; this->components= components; #ifdef WIN32 file= _wfopen(utf8_decode(path).c_str(), L"wb"); #else file= fopen(path.c_str(),"wb"); #endif if (file == NULL) { throw runtime_error("Can't open PNG file for writing: "+ path); } } void PixmapIoPng::write(uint8 *pixels) { // initialize stuff std::auto_ptr imrow(new png_byte*[h]); for(int i = 0; i < h; ++i) { imrow.get()[i] = pixels+(h-1-i) * w * components; } png_structp imgp = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0); png_infop infop = png_create_info_struct(imgp); png_init_io(imgp, file); int color_type = PNG_COLOR_TYPE_RGB; if(components == 4) { color_type = PNG_COLOR_TYPE_RGBA; } png_set_IHDR(imgp, infop, w, h, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // write file png_write_info(imgp, infop); png_write_image(imgp, imrow.get()); png_write_end(imgp, NULL); /* // Allocate write & info structures png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { fclose(file); throw runtime_error("OpenGlDevice::saveImageAsPNG() - out of memory creating write structure"); } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(file); throw runtime_error("OpenGlDevice::saveImageAsPNG() - out of memery creating info structure"); } // setjmp() must be called in every function that calls a PNG-writing // libpng function, unless an alternate error handler was installed-- // but compatible error handlers must either use longjmp() themselves // (as in this program) or exit immediately, so here we go: if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(file); throw runtime_error("OpenGlDevice::saveImageAsPNG() - setjmp problem"); } // make sure outfile is (re)opened in BINARY mode png_init_io(png_ptr, file); // set the compression levels--in general, always want to leave filtering // turned on (except for palette images) and allow all of the filters, // which is the default; want 32K zlib window, unless entire image buffer // is 16K or smaller (unknown here)--also the default; usually want max // compression (NOT the default); and remaining compression flags should // be left alone //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION); // // this is default for no filtering; Z_FILTERED is default otherwise: // png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); // these are all defaults: // png_set_compression_mem_level(png_ptr, 8); // png_set_compression_window_bits(png_ptr, 15); // png_set_compression_method(png_ptr, 8); // Set some options: color_type, interlace_type int color_type=0, interlace_type=0, numChannels=0; // color_type = PNG_COLOR_TYPE_GRAY; // color_type = PNG_COLOR_TYPE_GRAY_ALPHA; color_type = PNG_COLOR_TYPE_RGBA; numChannels = 4; // color_type = PNG_COLOR_TYPE_RGB_ALPHA; interlace_type = PNG_INTERLACE_NONE; // interlace_type = PNG_INTERLACE_ADAM7; int bit_depth = 8; png_set_IHDR(png_ptr, info_ptr, this->w, this->h, bit_depth, color_type, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // Optional gamma chunk is strongly suggested if you have any guess // as to the correct gamma of the image. (we don't have a guess) // // png_set_gAMA(png_ptr, info_ptr, image_gamma); //png_set_strip_alpha(png_ptr); // write all chunks up to (but not including) first IDAT png_write_info(png_ptr, info_ptr); //png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL ); // set up the row pointers for the image so we can use png_write_image png_bytep* row_pointers = new png_bytep[this->h]; if (row_pointers == 0) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(file); throw runtime_error("OpenGlDevice::failed to allocate memory for row pointers"); } unsigned int row_stride = this->w * numChannels; unsigned char *rowptr = (unsigned char*) pixels; for (int row = this->h-1; row >=0 ; row--) { row_pointers[row] = rowptr; rowptr += row_stride; } // now we just write the whole image; libpng takes care of interlacing for us png_write_image(png_ptr, row_pointers); // since that's it, we also close out the end of the PNG file now--if we // had any text or time info to write after the IDATs, second argument // would be info_ptr, but we optimize slightly by sending NULL pointer: png_write_end(png_ptr, info_ptr); // // clean up after the write // free any memory allocated & close the file // png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; */ } // ===================================================== // class PixmapIoJpg // ===================================================== PixmapIoJpg::PixmapIoJpg() { file= NULL; } PixmapIoJpg::~PixmapIoJpg() { if(file!=NULL){ fclose(file); file=NULL; } } void PixmapIoJpg::openRead(const string &path) { throw runtime_error("PixmapIoJpg::openRead not implemented!"); } void PixmapIoJpg::read(uint8 *pixels) { throw runtime_error("PixmapIoJpg::read not implemented!"); } void PixmapIoJpg::read(uint8 *pixels, int components) { throw runtime_error("PixmapIoJpg::read #2 not implemented!"); } void PixmapIoJpg::openWrite(const string &path, int w, int h, int components) { this->path = path; this->w= w; this->h= h; this->components= components; #ifdef WIN32 file= _wfopen(utf8_decode(path).c_str(), L"wb"); #else file= fopen(path.c_str(),"wb"); #endif if (file == NULL) { throw runtime_error("Can't open JPG file for writing: "+ path); } } void PixmapIoJpg::write(uint8 *pixels) { /* * alpha channel is not supported for jpeg. strip it. */ unsigned char * tmpbytes = NULL; if(components == 4) { int n = w * h; unsigned char *dst = tmpbytes = (unsigned char *) malloc(n*3); const unsigned char *src = pixels; for (int i = 0; i < n; i++) { *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; src++; } components = 3; } struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; /* this is a pointer to one row of image data */ JSAMPROW row_pointer[1]; cinfo.err = jpeg_std_error( &jerr ); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, file); /* Setting the parameters of the output file here */ cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = 3; // no alpha channel for jpeg cinfo.in_color_space = JCS_RGB; /* default compression parameters, we shouldn't be worried about these */ jpeg_set_defaults( &cinfo ); /* Now do the compression .. */ jpeg_start_compress( &cinfo, TRUE ); /* use stripped alpha channel bytes */ if(tmpbytes) { pixels = tmpbytes; } // OpenGL writes from bottom to top. // libjpeg goes from top to bottom. // flip lines. uint8 *flip = (uint8 *)malloc(sizeof(uint8) * w * h * 3); for (int y = 0;y < h; ++y) { for (int x = 0;x < w; ++x) { flip[(y * w + x) * 3] = pixels[((h - 1 - y) * w + x) * 3]; flip[(y * w + x) * 3 + 1] = pixels[((h - 1 - y) * w + x) * 3 + 1]; flip[(y * w + x) * 3 + 2] = pixels[((h - 1 - y) * w + x) * 3 + 2]; } } /* like reading a file, this time write one row at a time */ while( cinfo.next_scanline < cinfo.image_height ) { row_pointer[0] = &flip[ cinfo.next_scanline * cinfo.image_width * cinfo.input_components]; jpeg_write_scanlines( &cinfo, row_pointer, 1 ); } if (tmpbytes) { free(tmpbytes); tmpbytes=NULL; } free(flip); flip=NULL; /* similar to read file, clean up after we're done compressing */ jpeg_finish_compress( &cinfo ); jpeg_destroy_compress( &cinfo ); //fclose( outfile ); /* success code is 1! */ } // ===================================================== // class Pixmap1D // ===================================================== // ===================== PUBLIC ======================== Pixmap1D::Pixmap1D() { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); w= -1; components= -1; pixels= NULL; } Pixmap1D::Pixmap1D(int components) { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); init(components); } Pixmap1D::Pixmap1D(int w, int components) { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); init(w, components); } void Pixmap1D::init(int components){ this->w= -1; this->components= components; pixels= NULL; CalculatePixelsCRC(pixels,0, crc); } void Pixmap1D::init(int w, int components){ this->w= w; this->components= components; pixels= new uint8[(std::size_t)getPixelByteCount()]; CalculatePixelsCRC(pixels,0, crc); } uint64 Pixmap1D::getPixelByteCount() const { return (w * components); } void Pixmap1D::deletePixels() { delete [] pixels; pixels = NULL; } Pixmap1D::~Pixmap1D(){ deletePixels(); } void Pixmap1D::load(const string &path) { string extension= path.substr(path.find_last_of('.')+1); if(extension=="bmp") { loadBmp(path); } else if(extension=="tga") { loadTga(path); } else { throw runtime_error("Unknown pixmap extension: " + extension); } this->path = path; CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap1D::loadBmp(const string &path) { this->path = path; PixmapIoBmp plb; plb.openRead(path); //init if(plb.getH()==1) { w= plb.getW(); } else if(plb.getW()==1) { w= plb.getH(); } else { throw runtime_error("One of the texture dimensions must be 1"); } if(components == -1) { components= 3; } if(pixels == NULL) { pixels= new uint8[(std::size_t)getPixelByteCount()]; } //data plb.read(pixels, components); } void Pixmap1D::loadTga(const string &path) { this->path = path; PixmapIoTga plt; plt.openRead(path); //init if(plt.getH()==1) { w= plt.getW(); } else if(plt.getW()==1) { w= plt.getH(); } else { throw runtime_error("One of the texture dimensions must be 1"); } int fileComponents= plt.getComponents(); if(components == -1) { components= fileComponents; } if(pixels == NULL) { pixels= new uint8[(std::size_t)getPixelByteCount()]; } //read data plt.read(pixels, components); } // ===================================================== // class Pixmap2D // ===================================================== // ===================== PUBLIC ======================== Pixmap2D::Pixmap2D() { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); h= -1; w= -1; components= -1; pixels= NULL; } Pixmap2D::Pixmap2D(int components) { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); h= -1; w= -1; this->components= -1; pixels= NULL; init(components); } Pixmap2D::Pixmap2D(int w, int h, int components) { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); this->h= 0; this->w= -1; this->components= -1; pixels= NULL; init(w, h, components); } void Pixmap2D::init(int components) { this->w= -1; this->h= -1; this->components= components; deletePixels(); pixels= NULL; CalculatePixelsCRC(pixels,0, crc); } void Pixmap2D::init(int w, int h, int components) { this->w= w; this->h= h; this->components= components; deletePixels(); if(getPixelByteCount() <= 0 || (h <= 0 || w <= 0 || components <= 0)) { char szBuf[1024]; sprintf(szBuf,"Invalid pixmap dimensions for [%s], h = %d, w = %d, components = %d\n",path.c_str(),h,w,components); throw runtime_error(szBuf); } pixels= new uint8[(std::size_t)getPixelByteCount()]; CalculatePixelsCRC(pixels,0, crc); } uint64 Pixmap2D::getPixelByteCount() const { return (h * w * components); } void Pixmap2D::deletePixels() { if(pixels) { delete [] pixels; pixels = NULL; } } Pixmap2D::~Pixmap2D() { deletePixels(); } void Pixmap2D::Scale(int format, int newW, int newH) { int useComponents = this->getComponents(); uint8 *newpixels= new uint8[newW * newH * useComponents]; glPixelStorei(GL_PACK_ALIGNMENT, 1); int error = gluScaleImage( format, w, h, GL_UNSIGNED_BYTE, pixels, newW, newH, GL_UNSIGNED_BYTE, newpixels); if(error != GL_NO_ERROR) { init(newW,newH,this->components); pixels = newpixels; } else { assertGl(); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } Pixmap2D* Pixmap2D::loadPath(const string& path) { //printf("Loading Pixmap2D [%s]\n",path.c_str()); Pixmap2D *pixmap = FileReader::readPath(path); if(pixmap != NULL) { pixmap->path = path; CalculatePixelsCRC(pixmap->pixels,pixmap->getPixelByteCount(), pixmap->crc); } return pixmap; } void Pixmap2D::load(const string &path) { //printf("Loading Pixmap2D [%s]\n",path.c_str()); FileReader::readPath(path,this); CalculatePixelsCRC(pixels,getPixelByteCount(), crc); this->path = path; } void Pixmap2D::save(const string &path) { string extension= path.substr(path.find_last_of('.')+1); if(toLower(extension) == "bmp") { saveBmp(path); } else if(toLower(extension) == "tga") { saveTga(path); } else if(toLower(extension) == "jpg") { saveJpg(path); } else if(toLower(extension) == "png") { savePng(path); } else { throw runtime_error("Unknown pixmap extension: " + extension); } } void Pixmap2D::saveBmp(const string &path) { PixmapIoBmp psb; psb.openWrite(path, w, h, components); psb.write(pixels); } void Pixmap2D::saveTga(const string &path) { PixmapIoTga pst; pst.openWrite(path, w, h, components); pst.write(pixels); } void Pixmap2D::saveJpg(const string &path) { PixmapIoJpg pst; pst.openWrite(path, w, h, components); pst.write(pixels); } void Pixmap2D::savePng(const string &path) { PixmapIoPng pst; pst.openWrite(path, w, h, components); pst.write(pixels); } void Pixmap2D::getPixel(int x, int y, uint8 *value) const { for(int i=0; i(value[i]*255.f); } CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap2D::setComponent(int x, int y, int component, uint8 value) { int index = (w*y+x)*components+component; pixels[index] = value; CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap2D::setComponent(int x, int y, int component, float32 value) { int index = (w*y+x)*components+component; pixels[index]= static_cast(value*255.f); CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } //vector set void Pixmap2D::setPixel(int x, int y, const Vec3f &p) { for(int i = 0; i < components && i < 3; ++i) { int index = (w*y+x)*components+i; pixels[index]= static_cast(p.ptr()[i]*255.f); } CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap2D::setPixel(int x, int y, const Vec4f &p) { for(int i = 0; i < components && i < 4; ++i) { int index = (w*y+x)*components+i; pixels[index]= static_cast(p.ptr()[i]*255.f); } CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap2D::setPixel(int x, int y, float p) { int index = (w*y+x)*components; pixels[index]= static_cast(p*255.f); CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap2D::setPixels(const uint8 *value){ for(int i=0; iavg? 0: ((avg-distLu))*random.randRange(0.5f, 1.0f); float ru= distRu>avg? 0: ((avg-distRu))*random.randRange(0.5f, 1.0f); float ld= distLd>avg? 0: ((avg-distLd))*random.randRange(0.5f, 1.0f); float rd= distRd>avg? 0: ((avg-distRd))*random.randRange(0.5f, 1.0f); float total= lu+ru+ld+rd; Vec4f pix= (leftUp->getPixel4f(i, j)*lu+ rightUp->getPixel4f(i, j)*ru+ leftDown->getPixel4f(i, j)*ld+ rightDown->getPixel4f(i, j)*rd)*(1.0f/total); setPixel(i, j, pix); } } } void Pixmap2D::lerp(float t, const Pixmap2D *pixmap1, const Pixmap2D *pixmap2){ if( !doDimensionsAgree(pixmap1) || !doDimensionsAgree(pixmap2)) { throw runtime_error("Pixmap2D::lerp: pixmap dimensions don't agree"); } for(int i=0; igetPixel4f(i, j).lerp(t, pixmap2->getPixel4f(i, j))); } } } void Pixmap2D::copy(const Pixmap2D *sourcePixmap){ assert(components==sourcePixmap->getComponents()); if(w!=sourcePixmap->getW() || h!=sourcePixmap->getH()){ throw runtime_error("Pixmap2D::copy() dimensions must agree"); } memcpy(pixels, sourcePixmap->getPixels(), w*h*sourcePixmap->getComponents()); this->path = sourcePixmap->path; CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap2D::subCopy(int x, int y, const Pixmap2D *sourcePixmap){ assert(components==sourcePixmap->getComponents()); if(wgetW() && hgetH()){ throw runtime_error("Pixmap2D::subCopy(), bad dimensions"); } uint8 *pixel= new uint8[components]; for(int i=0; igetW(); ++i){ for(int j=0; jgetH(); ++j){ sourcePixmap->getPixel(i, j, pixel); setPixel(i+x, j+y, pixel); } } CalculatePixelsCRC(pixels,getPixelByteCount(), crc); delete [] pixel; } bool Pixmap2D::doDimensionsAgree(const Pixmap2D *pixmap){ return pixmap->getW() == w && pixmap->getH() == h; } // ===================================================== // class Pixmap3D // ===================================================== Pixmap3D::Pixmap3D() { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); w= -1; h= -1; d= -1; components= -1; pixels = NULL; slice=0; } Pixmap3D::Pixmap3D(int w, int h, int d, int components) { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); pixels = NULL; slice=0; init(w, h, d, components); } Pixmap3D::Pixmap3D(int d, int components) { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); pixels = NULL; slice=0; init(d, components); } void Pixmap3D::init(int w, int h, int d, int components){ this->w= w; this->h= h; this->d= d; this->components= components; pixels= new uint8[(std::size_t)getPixelByteCount()]; CalculatePixelsCRC(pixels,0, crc); } uint64 Pixmap3D::getPixelByteCount() const { return (h * w * d * components); } void Pixmap3D::init(int d, int components){ this->w= -1; this->h= -1; this->d= d; this->components= components; pixels= NULL; CalculatePixelsCRC(pixels,0, crc); } void Pixmap3D::init(int components) { this->w= -1; this->h= -1; this->d= -1; this->components= components; pixels= NULL; CalculatePixelsCRC(pixels,0, crc); } void Pixmap3D::deletePixels() { delete [] pixels; pixels = NULL; } Pixmap3D::~Pixmap3D() { deletePixels(); } void Pixmap3D::loadSlice(const string &path, int slice) { this->slice = slice; string extension= path.substr(path.find_last_of('.') + 1); if(extension == "png") { loadSlicePng(path, slice); } else if(extension == "bmp") { loadSliceBmp(path, slice); } else if(extension == "tga") { loadSliceTga(path, slice); } else { throw runtime_error("Unknown pixmap extension: "+extension); } this->path = path; CalculatePixelsCRC(pixels,getPixelByteCount(), crc); } void Pixmap3D::loadSlicePng(const string &path, int slice) { this->path = path; //deletePixels(); //Pixmap3D *pixmap = FileReader::readPath(path,this); FileReader::readPath(path,this); //printf("Loading 3D pixmap PNG [%s] pixmap [%p] this [%p]\n",path.c_str(),pixmap, this); } void Pixmap3D::loadSliceBmp(const string &path, int slice){ this->path = path; PixmapIoBmp plb; plb.openRead(path); //init w= plb.getW(); h= plb.getH(); if(components==-1){ components= 3; } if(pixels==NULL){ pixels= new uint8[(std::size_t)getPixelByteCount()]; } //data plb.read(&pixels[slice*w*h*components], components); } void Pixmap3D::loadSliceTga(const string &path, int slice){ this->path = path; //deletePixels(); FileReader::readPath(path,this); //printf("Loading 3D pixmap TGA [%s] this [%p]\n",path.c_str(),this); /* PixmapIoTga plt; plt.openRead(path); //header int fileComponents= plt.getComponents(); //init w= plt.getW(); h= plt.getH(); if(components==-1){ components= fileComponents; } if(pixels==NULL){ pixels= new uint8[(std::size_t)getPixelByteCount()]; } //read data plt.read(&pixels[slice*w*h*components], components); */ } // ===================================================== // class PixmapCube // ===================================================== PixmapCube::PixmapCube() { assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false); } PixmapCube::~PixmapCube() { } void PixmapCube::init(int w, int h, int components) { for(int i=0; i<6; ++i) { faces[i].init(w, h, components); } } void PixmapCube::init(int components) { for(int i=0; i<6; ++i) { faces[i].init(components); } } uint64 PixmapCube::getPixelByteCount() const { uint64 result = 0; for(int i=0; i<6; ++i) { result += faces[i].getPixelByteCount(); } return result; } //load & save void PixmapCube::loadFace(const string &path, int face) { this->path[face] = path; faces[face].load(path); } void PixmapCube::deletePixels() { for(int i=0; i<6; ++i){ faces[i].deletePixels(); } } }}//end namespace