#include "Image.h" #include "JPGImageType.h" #include "X3DTypes.h" #include using namespace std; namespace X3DTK { Image::Image() : _data(0), _glFormat(0), _type(0), _width(0), _height(0) { } Image::Image(const char *fileName) : _data(0), _glFormat(0), _type(0), _width(0), _height(0) { SFString file(fileName); if ((file.getExtension() == "jpg") || (file.getExtension() == "JPG")) { if (JPGImageType::load(fileName, this)) return; } cx3d << "sorry, " << file.getExtension() << " format not yet supported!" << endl; } Image::~Image() { release(); } void Image::saveAs(const char *fileName, float quality) { SFString file(fileName); if ((file.getExtension() == "jpg") || (file.getExtension() == "JPG")) { if (JPGImageType::save(fileName, this, quality)) return; } } void Image::resize(unsigned short width, unsigned short height, GLenum GLType) { unsigned char *res = resizeData(width, height, GLType); if (_data != 0) delete [] _data; _data = res; } unsigned char *Image::resizeData(unsigned short width, unsigned short height, GLenum GLType) { int oldPixelSize = computePixelSize(_glFormat, _type); GLenum oldType = _type; GLenum newType = (GLType == GL_NONE ? oldType : GLType); int pixelSize = computePixelSize(_glFormat, newType); _type = newType; unsigned char *newData = new unsigned char[pixelSize*width*height]; unsigned char *dataPtr = _data; unsigned char *newDataPtr = newData; unsigned short rowStride = oldPixelSize*_width; unsigned short newRowStride = pixelSize*width; unsigned short copyRowStride = oldPixelSize*(width > _width ? _width : width); unsigned short copyHeight = (height > _height ? _height : height); int res; switch (_glFormat) { case GL_LUMINANCE: res = 1; break; case GL_LUMINANCE_ALPHA: res = 2; break; case GL_RGB: res = 3; break; case GL_RGBA: res = 4; break; default: res = 0; } for (unsigned short i = 0; i < copyHeight; ++i) { if (oldType == _type) memcpy(newDataPtr, dataPtr, copyRowStride); else convert(oldType, newType, newDataPtr, dataPtr, res*(width > _width ? _width : width)); dataPtr += rowStride; newDataPtr += newRowStride; } _width = width; _height = height; return newData; } void Image::resizeGL(float (& textureTransform)[16]) { // 1E-3 needed. Just try with width=128 and see ! unsigned short newWidth = 1<<(unsigned short)(1+log(_width -1+1E-3)/log(2.0)); unsigned short newHeight = 1<<(unsigned short)(1+log(_height-1+1E-3)/log(2.0)); //set the ratios for the next geometry node textureTransform[0] = (float)(_width)/(float)(newWidth); textureTransform[1] = 0.0f; textureTransform[2] = 0.0f; textureTransform[3] = 0.0f; textureTransform[4] = 0.0f; textureTransform[5] = (float)(_height)/(float)(newHeight); textureTransform[6] = 0.0f; textureTransform[7] = 0.0f; textureTransform[8] = 0.0f; textureTransform[9] = 0.0f; textureTransform[10] = 1.0f; textureTransform[11] = 0.0f; textureTransform[12] = 0.0f; textureTransform[13] = 0.0f; textureTransform[14] = 0.0f; textureTransform[15] = 1.0f; resize(newWidth, newHeight); } void Image::release() { _glFormat = 0; _width = 0; _height = 0; _type = 0; if (_data != 0) { delete [] _data; _data = 0; } } bool Image::allocate(unsigned short width, unsigned short height, GLenum GLFormat, GLenum GLType) { release(); int pixelSize = computePixelSize(GLFormat, GLType); _glFormat = GLFormat; _type = GLType; _width = width; _height = height; _data = new unsigned char[pixelSize*width*height]; return (_data != 0); } int Image::computePixelSize(GLenum GLFormat, GLenum GLType) { int res; unsigned char elementSize = 0; switch (GLType) { case GL_UNSIGNED_BYTE: elementSize = 1; break; case GL_BYTE: elementSize = 1; break; case GL_UNSIGNED_SHORT: elementSize = 2; break; case GL_SHORT: elementSize = 2; break; case GL_UNSIGNED_INT: elementSize = 4; break; case GL_INT: elementSize = 4; break; case GL_FLOAT: elementSize = 4; break; default: elementSize = 0; } switch (GLFormat) { case GL_LUMINANCE: res = elementSize; break; case GL_LUMINANCE_ALPHA: res = 2*elementSize; break; case GL_RGB: res = 3*elementSize; break; case GL_RGBA: res = 4*elementSize; break; default: res = 0; } return res; } void Image::convert(GLenum oldType, GLenum newType, unsigned char *newData, unsigned char *data, unsigned int length) { if (oldType == GL_UNSIGNED_BYTE) { if (newType == GL_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_INT) ImageConverter::make(newData, data, length); if (newType == GL_INT) ImageConverter::make(newData, data, length); if (newType == GL_FLOAT) ImageConverter::make(newData, data, length); } if (oldType == GL_BYTE) { if (newType == GL_UNSIGNED_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_INT) ImageConverter::make(newData, data, length); if (newType == GL_INT) ImageConverter::make(newData, data, length); if (newType == GL_FLOAT) ImageConverter::make(newData, data, length); } if (oldType == GL_UNSIGNED_SHORT) { if (newType == GL_UNSIGNED_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_INT) ImageConverter::make(newData, data, length); if (newType == GL_INT) ImageConverter::make(newData, data, length); if (newType == GL_FLOAT) ImageConverter::make(newData, data, length); } if (oldType == GL_SHORT) { if (newType == GL_UNSIGNED_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_INT) ImageConverter::make(newData, data, length); if (newType == GL_INT) ImageConverter::make(newData, data, length); if (newType == GL_FLOAT) ImageConverter::make(newData, data, length); } if (oldType == GL_UNSIGNED_INT) { if (newType == GL_UNSIGNED_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_INT) ImageConverter::make(newData, data, length); if (newType == GL_FLOAT) ImageConverter::make(newData, data, length); } if (oldType == GL_INT) { if (newType == GL_UNSIGNED_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_INT) ImageConverter::make(newData, data, length); if (newType == GL_FLOAT) ImageConverter::make(newData, data, length); } if (oldType == GL_FLOAT) { if (newType == GL_UNSIGNED_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_BYTE) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_SHORT) ImageConverter::make(newData, data, length); if (newType == GL_UNSIGNED_INT) ImageConverter::make(newData, data, length); if (newType == GL_INT) ImageConverter::make(newData, data, length); } } }