mirror of
https://github.com/glest/glest-source.git
synced 2025-09-30 01:18:58 +02:00
Fixed the god-awful indentation
This commit is contained in:
@@ -22,350 +22,354 @@
|
||||
using std::runtime_error;
|
||||
using std::ios;
|
||||
|
||||
namespace Shared{ namespace Graphics{
|
||||
namespace Shared {
|
||||
namespace Graphics {
|
||||
|
||||
// =====================================================
|
||||
// Callbacks for PNG-decompression
|
||||
// =====================================================
|
||||
// =====================================================
|
||||
// Callbacks for PNG-decompression
|
||||
// =====================================================
|
||||
|
||||
static void user_read_data(png_structp read_ptr, png_bytep data, png_size_t length) {
|
||||
ifstream& is = *((ifstream*)png_get_io_ptr(read_ptr));
|
||||
is.read((char*)data,(std::streamsize)length);
|
||||
static bool bigEndianSystem = Shared::PlatformByteOrder::isBigEndian();
|
||||
if(bigEndianSystem == true) {
|
||||
Shared::PlatformByteOrder::fromEndianTypeArray<png_byte>(data,length);
|
||||
}
|
||||
static void user_read_data(png_structp read_ptr, png_bytep data, png_size_t length) {
|
||||
ifstream& is = *((ifstream*) png_get_io_ptr(read_ptr));
|
||||
is.read((char*) data, (std::streamsize)length);
|
||||
static bool bigEndianSystem = Shared::PlatformByteOrder::isBigEndian();
|
||||
if (bigEndianSystem == true) {
|
||||
Shared::PlatformByteOrder::fromEndianTypeArray<png_byte>(data, length);
|
||||
}
|
||||
|
||||
if (!is.good()) {
|
||||
png_error(read_ptr,"Could not read from png-file");
|
||||
}
|
||||
}
|
||||
|
||||
//static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length) {}
|
||||
|
||||
//static void user_flush_data(png_structp png_ptr) {}
|
||||
|
||||
/**Get Extension array, initialised*/
|
||||
//static inline const string* getExtensionsPng() {
|
||||
static inline std::vector<string> getExtensionsPng() {
|
||||
//static const string extensions[] = {"png", ""};
|
||||
static std::vector<string> extensions;
|
||||
if(extensions.empty() == true) {
|
||||
extensions.push_back("png");
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class PNGReader
|
||||
// =====================================================
|
||||
|
||||
PNGReader::PNGReader(): FileReader<Pixmap2D>(getExtensionsPng()) {}
|
||||
|
||||
Pixmap2D* PNGReader::read(ifstream& is, const string& path, Pixmap2D* ret) const {
|
||||
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
throw megaglest_runtime_error("Loading graphics in headless server mode not allowed!");
|
||||
}
|
||||
|
||||
//Read file
|
||||
is.seekg(0, ios::end);
|
||||
//size_t length = is.tellg();
|
||||
is.seekg(0, ios::beg);
|
||||
uint8 *buffer = new uint8[8];
|
||||
is.read((char*)buffer, 8);
|
||||
static bool bigEndianSystem = Shared::PlatformByteOrder::isBigEndian();
|
||||
if(bigEndianSystem == true) {
|
||||
Shared::PlatformByteOrder::fromEndianTypeArray<uint8>(buffer,8);
|
||||
}
|
||||
|
||||
if (png_sig_cmp(buffer, 0, 8) != 0) {
|
||||
delete [] buffer;
|
||||
//This is not a PNG file - could be used for fast checking whether file is supported or not
|
||||
throw megaglest_runtime_error(path +" is not a png",true);
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
delete [] buffer;
|
||||
throw megaglest_runtime_error(path +" is a corrupt(1) png",true);
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL,(png_infopp)NULL);
|
||||
delete [] buffer;
|
||||
throw megaglest_runtime_error(path +" is a corrupt(2) png",true);
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr,(png_infopp)NULL);
|
||||
delete [] buffer;
|
||||
//Error during init_io
|
||||
throw megaglest_runtime_error(path +" is a corrupt(3) png",true);
|
||||
}
|
||||
png_set_read_fn(png_ptr, &is, user_read_data);
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
int width = png_get_image_width(png_ptr,info_ptr);
|
||||
|
||||
int height = png_get_image_height(png_ptr,info_ptr);
|
||||
int color_type = png_get_color_type(png_ptr,info_ptr);
|
||||
//int bit_depth = info_ptr->bit_depth;
|
||||
|
||||
//We want RGB, 24 bit
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE ||
|
||||
(color_type == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr,info_ptr) < 8) ||
|
||||
(png_get_valid(png_ptr, info_ptr,PNG_INFO_tRNS))) {
|
||||
png_set_expand(png_ptr);
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
|
||||
//int number_of_passes = png_set_interlace_handling(png_ptr);
|
||||
png_set_interlace_handling(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
png_bytep* row_pointers = new png_bytep[height];
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
delete[] row_pointers;
|
||||
delete [] buffer;
|
||||
//error during read_image
|
||||
throw megaglest_runtime_error(path +" is a corrupt(4) png",true);
|
||||
}
|
||||
for (int y = 0; y < height; ++y) {
|
||||
row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
size_t fileComponents = png_get_rowbytes(png_ptr, info_ptr)/width;
|
||||
size_t picComponents = (ret->getComponents()==-1)?fileComponents:ret->getComponents();
|
||||
//std::cout << "PNG-Components: Pic: " << picComponents << " old: " << (ret->getComponents()) << " File: " << fileComponents << std::endl;
|
||||
//picComponents = 4;
|
||||
//Copy image
|
||||
ret->init(width,height,(int)picComponents);
|
||||
uint8* pixels = ret->getPixels();
|
||||
const size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
size_t location = 0;
|
||||
for (int y = height-1; y >= 0; --y) { //you have to somehow invert the lines
|
||||
if (picComponents == fileComponents) {
|
||||
memcpy(pixels+location,row_pointers[y],rowbytes);
|
||||
} else {
|
||||
int r,g,b,a,l;
|
||||
for (size_t xPic = 0, xFile = 0; xFile < rowbytes; xPic+= picComponents, xFile+= fileComponents) {
|
||||
switch(fileComponents) {
|
||||
case 3:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile+1];
|
||||
b = row_pointers[y][xFile+2];
|
||||
l = (r+g+b+2)/3;
|
||||
a = 255;
|
||||
break;
|
||||
case 4:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile+1];
|
||||
b = row_pointers[y][xFile+2];
|
||||
l = (r+g+b+2)/3;
|
||||
a = row_pointers[y][xFile+3];
|
||||
break;
|
||||
default:
|
||||
// Possible Error
|
||||
case 1:
|
||||
r = g = b = l = row_pointers[y][xFile];
|
||||
a = 255;
|
||||
break;
|
||||
}
|
||||
switch (picComponents) {
|
||||
case 1:
|
||||
pixels[location+xPic] = l;
|
||||
break;
|
||||
case 4:
|
||||
pixels[location+xPic+3] = a; //Next case
|
||||
case 3:
|
||||
pixels[location+xPic] = r;
|
||||
pixels[location+xPic+1] = g;
|
||||
pixels[location+xPic+2] = b;
|
||||
break;
|
||||
default:
|
||||
//just so at least something works
|
||||
for (unsigned int i = 0; i < picComponents; ++i) {
|
||||
pixels[location+xPic+i] = l;
|
||||
}
|
||||
break;
|
||||
// Possible Error
|
||||
}
|
||||
if (!is.good()) {
|
||||
png_error(read_ptr, "Could not read from png-file");
|
||||
}
|
||||
}
|
||||
location += picComponents * width;
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
delete [] row_pointers[y];
|
||||
}
|
||||
delete[] row_pointers;
|
||||
//static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length) {}
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
//static void user_flush_data(png_structp png_ptr) {}
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PNGReader3D::PNGReader3D(): FileReader<Pixmap3D>(getExtensionsPng()) {}
|
||||
|
||||
Pixmap3D* PNGReader3D::read(ifstream& is, const string& path, Pixmap3D* ret) const {
|
||||
//Read file
|
||||
is.seekg(0, ios::end);
|
||||
//size_t length = is.tellg();
|
||||
is.seekg(0, ios::beg);
|
||||
uint8 *buffer = new uint8[8];
|
||||
is.read((char*)buffer, 8);
|
||||
static bool bigEndianSystem = Shared::PlatformByteOrder::isBigEndian();
|
||||
if(bigEndianSystem == true) {
|
||||
Shared::PlatformByteOrder::fromEndianTypeArray<uint8>(buffer,8);
|
||||
}
|
||||
|
||||
if (png_sig_cmp(buffer, 0, 8) != 0) {
|
||||
delete [] buffer;
|
||||
//This is not a PNG file - could be used for fast checking whether file is supported or not
|
||||
throw megaglest_runtime_error(path +" is not a png(2)",true);
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
delete [] buffer;
|
||||
throw megaglest_runtime_error(path +" is a corrupt(5) png",true);
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL,(png_infopp)NULL);
|
||||
delete [] buffer;
|
||||
throw megaglest_runtime_error(path +" is a corrupt(6) png",true);
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr,(png_infopp)NULL);
|
||||
delete [] buffer;
|
||||
//Error during init_io
|
||||
throw megaglest_runtime_error(path +" is a corrupt(7) png",true);
|
||||
}
|
||||
png_set_read_fn(png_ptr, &is, user_read_data);
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
int width = png_get_image_width(png_ptr,info_ptr);
|
||||
int height = png_get_image_height(png_ptr,info_ptr);
|
||||
int color_type = png_get_color_type(png_ptr,info_ptr);
|
||||
//int bit_depth = info_ptr->bit_depth;
|
||||
|
||||
//We want RGB, 24 bit
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE ||
|
||||
(color_type == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr,info_ptr) < 8) ||
|
||||
(png_get_valid(png_ptr, info_ptr,PNG_INFO_tRNS))) {
|
||||
png_set_expand(png_ptr);
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
|
||||
//int number_of_passes = png_set_interlace_handling(png_ptr);
|
||||
png_set_interlace_handling(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
png_bytep* row_pointers = new png_bytep[height];
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
delete[] row_pointers;
|
||||
delete [] buffer;
|
||||
//error during read_image
|
||||
throw megaglest_runtime_error(path +" is a corrupt(8) png",true);
|
||||
}
|
||||
for (int y = 0; y < height; ++y) {
|
||||
row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
size_t fileComponents = png_get_rowbytes(png_ptr, info_ptr)/width;
|
||||
size_t picComponents = (ret->getComponents()==-1)?fileComponents:ret->getComponents();
|
||||
const int d = ret->getD();
|
||||
const int slice = ret->getSlice();
|
||||
if(ret->getPixels() == NULL){
|
||||
ret->init(width,height,d, (int)picComponents);
|
||||
}
|
||||
|
||||
//std::cout << "PNG-Components: Pic: " << picComponents << " old: " << (ret->getComponents()) << " File: " << fileComponents << std::endl;
|
||||
//picComponents = 4;
|
||||
//Copy image
|
||||
//printf("pixmap3d loading path [%s] w = %d h = %d d = %d comp = %d\n",path.c_str(),width,height,ret->getD(),picComponents);
|
||||
uint8* pixels = ret->getPixels();
|
||||
if(slice > 0) {
|
||||
pixels = &pixels[slice*width*height*picComponents];
|
||||
}
|
||||
|
||||
const size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
size_t location = 0;
|
||||
for (int y = height-1; y >= 0; --y) { //you have to somehow invert the lines
|
||||
if (picComponents == fileComponents) {
|
||||
memcpy(pixels+location,row_pointers[y],rowbytes);
|
||||
} else {
|
||||
int r,g,b,a,l;
|
||||
for (size_t xPic = 0, xFile = 0; xFile < rowbytes; xPic+= picComponents, xFile+= fileComponents) {
|
||||
switch(fileComponents) {
|
||||
case 3:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile+1];
|
||||
b = row_pointers[y][xFile+2];
|
||||
l = (r+g+b+2)/3;
|
||||
a = 255;
|
||||
break;
|
||||
case 4:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile+1];
|
||||
b = row_pointers[y][xFile+2];
|
||||
l = (r+g+b+2)/3;
|
||||
a = row_pointers[y][xFile+3];
|
||||
break;
|
||||
default:
|
||||
// Possible Error
|
||||
case 1:
|
||||
r = g = b = l = row_pointers[y][xFile];
|
||||
a = 255;
|
||||
break;
|
||||
}
|
||||
switch (picComponents) {
|
||||
case 1:
|
||||
pixels[location+xPic] = l;
|
||||
break;
|
||||
case 4:
|
||||
pixels[location+xPic+3] = a; //Next case
|
||||
case 3:
|
||||
pixels[location+xPic] = r;
|
||||
pixels[location+xPic+1] = g;
|
||||
pixels[location+xPic+2] = b;
|
||||
break;
|
||||
default:
|
||||
//just so at least something works
|
||||
for (unsigned int i = 0; i < picComponents; ++i) {
|
||||
pixels[location+xPic+i] = l;
|
||||
}
|
||||
break;
|
||||
// Possible Error
|
||||
}
|
||||
/**Get Extension array, initialised*/
|
||||
//static inline const string* getExtensionsPng() {
|
||||
static inline std::vector<string> getExtensionsPng() {
|
||||
//static const string extensions[] = {"png", ""};
|
||||
static std::vector<string> extensions;
|
||||
if (extensions.empty() == true) {
|
||||
extensions.push_back("png");
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
location += picComponents * width;
|
||||
|
||||
// =====================================================
|
||||
// class PNGReader
|
||||
// =====================================================
|
||||
|
||||
PNGReader::PNGReader() : FileReader<Pixmap2D>(getExtensionsPng()) {
|
||||
}
|
||||
|
||||
Pixmap2D* PNGReader::read(ifstream& is, const string& path, Pixmap2D* ret) const {
|
||||
if (GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
throw megaglest_runtime_error("Loading graphics in headless server mode not allowed!");
|
||||
}
|
||||
|
||||
//Read file
|
||||
is.seekg(0, ios::end);
|
||||
//size_t length = is.tellg();
|
||||
is.seekg(0, ios::beg);
|
||||
uint8 *buffer = new uint8[8];
|
||||
is.read((char*) buffer, 8);
|
||||
static bool bigEndianSystem = Shared::PlatformByteOrder::isBigEndian();
|
||||
if (bigEndianSystem == true) {
|
||||
Shared::PlatformByteOrder::fromEndianTypeArray<uint8>(buffer, 8);
|
||||
}
|
||||
|
||||
if (png_sig_cmp(buffer, 0, 8) != 0) {
|
||||
delete[] buffer;
|
||||
//This is not a PNG file - could be used for fast checking whether file is supported or not
|
||||
throw megaglest_runtime_error(path + " is not a png", true);
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
delete[] buffer;
|
||||
throw megaglest_runtime_error(path + " is a corrupt(1) png", true);
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
|
||||
delete[] buffer;
|
||||
throw megaglest_runtime_error(path + " is a corrupt(2) png", true);
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||
delete[] buffer;
|
||||
//Error during init_io
|
||||
throw megaglest_runtime_error(path + " is a corrupt(3) png", true);
|
||||
}
|
||||
png_set_read_fn(png_ptr, &is, user_read_data);
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
int width = png_get_image_width(png_ptr, info_ptr);
|
||||
|
||||
int height = png_get_image_height(png_ptr, info_ptr);
|
||||
int color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
//int bit_depth = info_ptr->bit_depth;
|
||||
|
||||
//We want RGB, 24 bit
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE ||
|
||||
(color_type == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr, info_ptr) < 8) ||
|
||||
(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) {
|
||||
png_set_expand(png_ptr);
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
|
||||
//int number_of_passes = png_set_interlace_handling(png_ptr);
|
||||
png_set_interlace_handling(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
png_bytep* row_pointers = new png_bytep[height];
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
delete[] row_pointers;
|
||||
delete[] buffer;
|
||||
//error during read_image
|
||||
throw megaglest_runtime_error(path + " is a corrupt(4) png", true);
|
||||
}
|
||||
for (int y = 0; y < height; ++y) {
|
||||
row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
size_t fileComponents = png_get_rowbytes(png_ptr, info_ptr) / width;
|
||||
size_t picComponents = (ret->getComponents() == -1) ? fileComponents : ret->getComponents();
|
||||
//std::cout << "PNG-Components: Pic: " << picComponents << " old: " << (ret->getComponents()) << " File: " << fileComponents << std::endl;
|
||||
//picComponents = 4;
|
||||
//Copy image
|
||||
ret->init(width, height, (int) picComponents);
|
||||
uint8* pixels = ret->getPixels();
|
||||
const size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
size_t location = 0;
|
||||
for (int y = height - 1; y >= 0; --y) { //you have to somehow invert the lines
|
||||
if (picComponents == fileComponents) {
|
||||
memcpy(pixels + location, row_pointers[y], rowbytes);
|
||||
} else {
|
||||
int r, g, b, a, l;
|
||||
for (size_t xPic = 0, xFile = 0; xFile < rowbytes; xPic += picComponents, xFile += fileComponents) {
|
||||
switch (fileComponents) {
|
||||
case 3:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile + 1];
|
||||
b = row_pointers[y][xFile + 2];
|
||||
l = (r + g + b + 2) / 3;
|
||||
a = 255;
|
||||
break;
|
||||
case 4:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile + 1];
|
||||
b = row_pointers[y][xFile + 2];
|
||||
l = (r + g + b + 2) / 3;
|
||||
a = row_pointers[y][xFile + 3];
|
||||
break;
|
||||
default:
|
||||
// Possible Error
|
||||
case 1:
|
||||
r = g = b = l = row_pointers[y][xFile];
|
||||
a = 255;
|
||||
break;
|
||||
}
|
||||
switch (picComponents) {
|
||||
case 1:
|
||||
pixels[location + xPic] = l;
|
||||
break;
|
||||
case 4:
|
||||
pixels[location + xPic + 3] = a; //Next case
|
||||
case 3:
|
||||
pixels[location + xPic] = r;
|
||||
pixels[location + xPic + 1] = g;
|
||||
pixels[location + xPic + 2] = b;
|
||||
break;
|
||||
default:
|
||||
//just so at least something works
|
||||
for (unsigned int i = 0; i < picComponents; ++i) {
|
||||
pixels[location + xPic + i] = l;
|
||||
}
|
||||
break;
|
||||
// Possible Error
|
||||
}
|
||||
}
|
||||
}
|
||||
location += picComponents * width;
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
delete[] row_pointers[y];
|
||||
}
|
||||
delete[] row_pointers;
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PNGReader3D::PNGReader3D() : FileReader<Pixmap3D>(getExtensionsPng()) {
|
||||
}
|
||||
|
||||
Pixmap3D* PNGReader3D::read(ifstream& is, const string& path, Pixmap3D* ret) const {
|
||||
//Read file
|
||||
is.seekg(0, ios::end);
|
||||
//size_t length = is.tellg();
|
||||
is.seekg(0, ios::beg);
|
||||
uint8 *buffer = new uint8[8];
|
||||
is.read((char*) buffer, 8);
|
||||
static bool bigEndianSystem = Shared::PlatformByteOrder::isBigEndian();
|
||||
if (bigEndianSystem == true) {
|
||||
Shared::PlatformByteOrder::fromEndianTypeArray<uint8>(buffer, 8);
|
||||
}
|
||||
|
||||
if (png_sig_cmp(buffer, 0, 8) != 0) {
|
||||
delete[] buffer;
|
||||
//This is not a PNG file - could be used for fast checking whether file is supported or not
|
||||
throw megaglest_runtime_error(path + " is not a png(2)", true);
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
delete[] buffer;
|
||||
throw megaglest_runtime_error(path + " is a corrupt(5) png", true);
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
|
||||
delete[] buffer;
|
||||
throw megaglest_runtime_error(path + " is a corrupt(6) png", true);
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||
delete[] buffer;
|
||||
//Error during init_io
|
||||
throw megaglest_runtime_error(path + " is a corrupt(7) png", true);
|
||||
}
|
||||
png_set_read_fn(png_ptr, &is, user_read_data);
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
int width = png_get_image_width(png_ptr, info_ptr);
|
||||
int height = png_get_image_height(png_ptr, info_ptr);
|
||||
int color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
//int bit_depth = info_ptr->bit_depth;
|
||||
|
||||
//We want RGB, 24 bit
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE ||
|
||||
(color_type == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr, info_ptr) < 8) ||
|
||||
(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) {
|
||||
png_set_expand(png_ptr);
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
|
||||
//int number_of_passes = png_set_interlace_handling(png_ptr);
|
||||
png_set_interlace_handling(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
png_bytep* row_pointers = new png_bytep[height];
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
delete[] row_pointers;
|
||||
delete[] buffer;
|
||||
//error during read_image
|
||||
throw megaglest_runtime_error(path + " is a corrupt(8) png", true);
|
||||
}
|
||||
for (int y = 0; y < height; ++y) {
|
||||
row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
size_t fileComponents = png_get_rowbytes(png_ptr, info_ptr) / width;
|
||||
size_t picComponents = (ret->getComponents() == -1) ? fileComponents : ret->getComponents();
|
||||
const int d = ret->getD();
|
||||
const int slice = ret->getSlice();
|
||||
if (ret->getPixels() == NULL) {
|
||||
ret->init(width, height, d, (int) picComponents);
|
||||
}
|
||||
|
||||
//std::cout << "PNG-Components: Pic: " << picComponents << " old: " << (ret->getComponents()) << " File: " << fileComponents << std::endl;
|
||||
//picComponents = 4;
|
||||
//Copy image
|
||||
//printf("pixmap3d loading path [%s] w = %d h = %d d = %d comp = %d\n",path.c_str(),width,height,ret->getD(),picComponents);
|
||||
uint8* pixels = ret->getPixels();
|
||||
if (slice > 0) {
|
||||
pixels = &pixels[slice*width*height*picComponents];
|
||||
}
|
||||
|
||||
const size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
size_t location = 0;
|
||||
for (int y = height - 1; y >= 0; --y) { //you have to somehow invert the lines
|
||||
if (picComponents == fileComponents) {
|
||||
memcpy(pixels + location, row_pointers[y], rowbytes);
|
||||
} else {
|
||||
int r, g, b, a, l;
|
||||
for (size_t xPic = 0, xFile = 0; xFile < rowbytes; xPic += picComponents, xFile += fileComponents) {
|
||||
switch (fileComponents) {
|
||||
case 3:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile + 1];
|
||||
b = row_pointers[y][xFile + 2];
|
||||
l = (r + g + b + 2) / 3;
|
||||
a = 255;
|
||||
break;
|
||||
case 4:
|
||||
r = row_pointers[y][xFile];
|
||||
g = row_pointers[y][xFile + 1];
|
||||
b = row_pointers[y][xFile + 2];
|
||||
l = (r + g + b + 2) / 3;
|
||||
a = row_pointers[y][xFile + 3];
|
||||
break;
|
||||
default:
|
||||
// Possible Error
|
||||
case 1:
|
||||
r = g = b = l = row_pointers[y][xFile];
|
||||
a = 255;
|
||||
break;
|
||||
}
|
||||
switch (picComponents) {
|
||||
case 1:
|
||||
pixels[location + xPic] = l;
|
||||
break;
|
||||
case 4:
|
||||
pixels[location + xPic + 3] = a; //Next case
|
||||
case 3:
|
||||
pixels[location + xPic] = r;
|
||||
pixels[location + xPic + 1] = g;
|
||||
pixels[location + xPic + 2] = b;
|
||||
break;
|
||||
default:
|
||||
//just so at least something works
|
||||
for (unsigned int i = 0; i < picComponents; ++i) {
|
||||
pixels[location + xPic + i] = l;
|
||||
}
|
||||
break;
|
||||
// Possible Error
|
||||
}
|
||||
}
|
||||
}
|
||||
location += picComponents * width;
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
delete[] row_pointers[y];
|
||||
}
|
||||
delete[] row_pointers;
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
delete [] row_pointers[y];
|
||||
}
|
||||
delete[] row_pointers;
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}} //end namespace
|
||||
} //end namespace
|
||||
|
Reference in New Issue
Block a user