mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-13 00:07:24 +00:00
196 lines
6.5 KiB
C++
196 lines
6.5 KiB
C++
/****************************************************************************
|
|
* MeshLab o o *
|
|
* An extendible mesh processor o o *
|
|
* _ O _ *
|
|
* Copyright(C) 2005, 2009 \/)\/ *
|
|
* Visual Computing Lab /\/| *
|
|
* ISTI - Italian National Research Council | *
|
|
* \ *
|
|
* All rights reserved. *
|
|
* *
|
|
* This program is free software; you can redistribute it 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. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
* for more details. *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
#include <Qt>
|
|
#include <QPixmap>
|
|
#include <bzlib.h>
|
|
#include <vector>
|
|
#include "scalar_image.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
/*
|
|
|
|
Images with bit-depths greater than 8bpp and up to 31bpp are supported by the JJ2000 codec if they are stored in PGX files
|
|
(one file per component). PGX is a custom monochrome file format invented specifically to simplify the use of JPEG 2000
|
|
with images of different bit-depths in the range of 1 to 31 bits per pixel.
|
|
|
|
The file consists of a one line text header followed by the (raw) data.
|
|
|
|
Header: "PG"+ ws +<endianess>+ ws +[sign]+ws + <bit-depth>+" "+<width>+" "+<height>+[compressed_size]'\n'
|
|
|
|
where:
|
|
|
|
* ws (white-spaces) is any combination of characters ' ' and '\t'.
|
|
* endianess equals "LM" or "ML"(resp. little-endian or big-endian)
|
|
* sign equals "+" or "-" (resp. unsigned or signed). If omited, values are supposed to be unsigned.
|
|
* bit-depth that can be any number between 1 and 31. This number must take into account the eventual sign bit.
|
|
* width and height are the image dimensions (in pixels).
|
|
|
|
Data: The image binary values appear one after the other (in raster order) immediately after the last header character ('\n')
|
|
and are byte-aligned (they are packed into 1,2 or 4 bytes per sample, depending upon the bit-depth value).
|
|
*/
|
|
template <>
|
|
bool ScalarImage<float>::Open(const char *filename)
|
|
{
|
|
FILE *fp=fopen(filename,"rb");
|
|
if(!fp) return false;
|
|
char buf[256];
|
|
fgets(buf,255,fp);
|
|
qDebug("Header of %s is '%s'",filename,buf);
|
|
float ll,lh;
|
|
int depth;
|
|
char mode;
|
|
int compressed_size=0;
|
|
sscanf(buf,"PG LM %i %i %i %c %f %f %i",&depth,&w,&h,&mode,&ll,&lh,&compressed_size);
|
|
qDebug("image should be of %i x %i %i depth and with range in %f -- %f in mode %c",w,h,depth,ll,lh,mode);
|
|
if(depth!=16)
|
|
{
|
|
qDebug("Wrong depth of image 16 bit expected");
|
|
return false;
|
|
}
|
|
if (mode != 'l' && mode != 'L')
|
|
{
|
|
qDebug("Wrong mode, expected l or L");
|
|
return false;
|
|
}
|
|
|
|
if (mode == 'l')
|
|
{
|
|
vector<unsigned short> bb(w*h);
|
|
fread(&*bb.begin(),w*h,sizeof(short),fp);
|
|
v.resize(w*h);
|
|
for(int i =0; i<w*h;++i)
|
|
v[i]=ll+(lh-ll)*(float(bb[i])/65536.0f);
|
|
}
|
|
else
|
|
{
|
|
char* compressed_buffer = new char[compressed_size];
|
|
fread(compressed_buffer,compressed_size,1,fp);
|
|
// decompress!
|
|
size_t size = w*h*sizeof(short);
|
|
unsigned char * uncompressed_buffer = new unsigned char[size];
|
|
unsigned int mysize = size;
|
|
BZ2_bzBuffToBuffDecompress((char*)uncompressed_buffer, &mysize, compressed_buffer, compressed_size, 0, 0);
|
|
if (mysize != size)
|
|
{
|
|
qDebug("This is very wrong. The uncompressed size is not the expected size");
|
|
return false;
|
|
}
|
|
int imagesize = w*h;
|
|
unsigned char *correct_buffer = new unsigned char[size];
|
|
|
|
for (int i=0; i<imagesize; ++i)
|
|
{
|
|
for (size_t j=0; j<sizeof(short); ++j)
|
|
{
|
|
correct_buffer[sizeof(short)*i +j] = uncompressed_buffer[imagesize*j + i];
|
|
}
|
|
}
|
|
v.resize(w*h);
|
|
for (int i=0; i<imagesize; ++i)
|
|
{
|
|
float a = *((unsigned short*)&correct_buffer[i*sizeof(short)]);
|
|
v[i] = ll+(lh-ll)*(a/65536.0f);
|
|
}
|
|
|
|
delete [] uncompressed_buffer;
|
|
delete [] compressed_buffer;
|
|
delete [] correct_buffer;
|
|
}
|
|
fclose(fp);
|
|
return true;
|
|
}
|
|
|
|
|
|
template <>
|
|
bool ScalarImage<unsigned char>::Open(const char *filename)
|
|
{
|
|
FILE *fp=fopen(filename,"rb");
|
|
if(!fp) return false;
|
|
char buf[256];
|
|
fgets(buf,255,fp);
|
|
qDebug("Header of %s is '%s'",filename,buf);
|
|
int depth;
|
|
char mode = ' ';
|
|
int compressed_size=0;
|
|
int nrscan = sscanf(buf,"PG LM %i %i %i %c %i",&depth,&w,&h,&mode,&compressed_size);
|
|
if (nrscan == 3)
|
|
qDebug("image should be of %i x %i %i depth ",w,h,depth);
|
|
else
|
|
qDebug("compressed image of %i x %i %i depth ",w,h,depth);
|
|
if(depth!=8)
|
|
{
|
|
qDebug("Wrong depth of image: 8 bit expected");
|
|
return false;
|
|
}
|
|
|
|
if (mode != 'C')
|
|
{
|
|
v.resize(w*h);
|
|
fread(&*v.begin(),w*h,sizeof(unsigned char),fp);
|
|
}
|
|
else
|
|
{
|
|
char* compressed_buffer = new char[compressed_size];
|
|
fread(compressed_buffer,compressed_size,1,fp);
|
|
// decompress!
|
|
unsigned int mysize = w*h;
|
|
v.resize(w*h);
|
|
BZ2_bzBuffToBuffDecompress((char*)&*v.begin(), &mysize, compressed_buffer, compressed_size, 0, 0);
|
|
if (mysize != (unsigned int)(w*h))
|
|
{
|
|
qDebug("This is very wrong. The uncompressed size is not the expected size");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
return true;
|
|
}
|
|
|
|
|
|
template <>
|
|
ScalarImage<unsigned char>::ScalarImage(QImage img)
|
|
{
|
|
resize(img.width(),img.height());
|
|
|
|
for(int y=0;y<h;++y)
|
|
for(int x=0;x<w;++x)
|
|
Val(x,y)=qGray(img.pixel(x,y));
|
|
|
|
}
|
|
|
|
template <class ScalarType>
|
|
bool ScalarImage<ScalarType>::Subsample(const int factor, ScalarImage<ScalarType> &fli)
|
|
{
|
|
resize(fli.w/factor,fli.h/factor);
|
|
|
|
for(int i=0;i<h;++i)
|
|
for(int j=0;j<w;++j)
|
|
Val(i,j)=fli.Val(i*factor,j*factor);
|
|
return true;
|
|
};
|
|
|