# HG changeset patch # User viric@llimona # Date 1169423157 -3600 # Node ID 9cbf4c7e79869817b89ca550bcaff428828a5520 # Parent 327eef3fe747d2c231f432a872d1616beefa56cf First classes for the qjpeg project. diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/FloatPlane.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/FloatPlane.cpp Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,113 @@ +#include "FloatPlane.h" +#include + +extern "C" { +#include +#include +} + +FloatPlane::FloatPlane() +{ + setMaxMinValue(); + ready = false; +} + +void FloatPlane::setMaxMinValue(unsigned int max, unsigned int min) +{ + MAXVALUE=max; + MINVALUE=min; +} + +FloatPlane::FloatPlane(float *_ptr) +{ + ptr = _ptr; + setMaxMinValue(); + ready = true; +} + +FloatPlane::FloatPlane(const unsigned int _width, const unsigned int _height) +{ + allocate(_width, _height); + + setMaxMinValue(); + ready = true; +} + +void FloatPlane::allocate(const unsigned int _width, const unsigned int _height) +{ + width = _width; + height = _height; + ptr = new float[width*height]; + ready = true; +} + +void FloatPlane::writePGM(const char * filename) +{ + struct pam outpam; + unsigned int row; + tuple *tuplerow; + + FILE* file; + + if (!ready) + return; + + file = fopen(filename, "wb"); + if (file == NULL) + return; + + outpam.size = sizeof(outpam); + outpam.len = outpam.size; + outpam.file = file; + outpam.format = PGM_FORMAT; + outpam.plainformat = 0; /* false */ + outpam.width = width; + outpam.height = height; + outpam.depth = 1; /* Grayscale - 1 sample per tuple */ + outpam.allocation_depth = 0; /* Same as depth. */ + outpam.maxval = MAXVALUE; + std::strcpy(outpam.tuple_type, "GRAYSCALE"); /* PGM non transparent */ + + /* needs size,len,file,format,height,width,depth,maxval, tuple_type */ + pnm_writepaminit(&outpam); + + tuplerow = pnm_allocpamrow(&outpam); + + for (row = 0; row < height; row++) { + unsigned int column; + for (column = 0; column < width; ++column) { + /* Only one plane */ + /* float to int! */ + tuplerow[column][0] = ptr[column+width*row]; + } + pnm_writepamrow(&outpam, tuplerow); + } + + pnm_freepamrow(tuplerow); + fclose(file); +} + +unsigned int FloatPlane::getMaxValue() +{ + return MAXVALUE; +} + +unsigned int FloatPlane::getWidth() +{ + return width; +} + +unsigned int FloatPlane::getHeight() +{ + return height; +} + +float * FloatPlane::getPtr() +{ + return ptr; +} + +void FloatPlane::free() +{ + delete[] ptr; +} diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/FloatPlane.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/FloatPlane.h Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,27 @@ +class FloatPlane +{ + unsigned int width; + unsigned int height; + + int MAXVALUE; + int MINVALUE; + + bool ready; + + void setMaxMinValue(unsigned int max = 255, unsigned int min = 0); + +public: + float *ptr; + + FloatPlane(); + FloatPlane(float *_ptr); + FloatPlane(const unsigned int _width, const unsigned int _height); + + void allocate(const unsigned int _width, const unsigned int _height); + unsigned int getWidth(); + float * getPtr(); + unsigned int getHeight(); + unsigned int getMaxValue(); + void writePGM(const char * filename); + void free(); +}; diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/Image.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/Image.cpp Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,126 @@ +#include "Image.h" +#include "FloatPlane.h" +#include +extern "C" { +#include +#include +} + +Image::Image() +{ + ready = false; +} + + +Image::Image(FloatPlane _plane[], const unsigned int _components) +{ + components = _components; + plane = new FloatPlane[3]; + /* Copy FloatPlanes */ + for(unsigned int i=0; i +#include + +extern "C" +{ +#include +#include +} + +#include "FloatPlane.h" +#include "Image.h" +#include "JPEGFile.h" + +JPEGFile::JPEGFile(const char *_filename) +{ + using namespace std; + filename = new char[std::strlen(_filename) + 1]; + std::strcpy(filename, _filename); + srcinfo = new jpeg_decompress_struct; + jsrcerr = new jpeg_error_mgr; +} + +void JPEGFile::readHeader() +{ + srcinfo->err = jpeg_std_error(jsrcerr); + + jpeg_create_decompress(srcinfo); + + inputh = fopen(filename, "rb"); + + jpeg_stdio_src(srcinfo, inputh); + jpeg_read_header(srcinfo, TRUE); +} + +Image *JPEGFile::getiDCTImage() +{ + readHeader(); + + /* Set our JPEG decompression parameters */ + srcinfo->dct_method = JDCT_FLOAT; + + /* jpeglib don't do any postprocessing (scaling/colorq). */ + srcinfo->raw_data_out = TRUE; + + /* Start decompression of pixels */ + jpeg_start_decompress(srcinfo); + + unsigned int nplanes = srcinfo->num_components; + + /* Create the planes */ + FloatPlane *planes = new FloatPlane[nplanes]; + unsigned int width[nplanes]; + unsigned int height[nplanes]; + unsigned int max_width_in_blocks = 0; + + /* Get the pointers to the planes */ + float *bmp[srcinfo->out_color_components]; + for (unsigned int i=0; i < nplanes; i++) + { + /* get the dimensions for every plane*/ + width[i] = srcinfo->comp_info[i].downsampled_width; + height[i] = srcinfo->comp_info[i].downsampled_height; + + if (srcinfo->comp_info[i].width_in_blocks > max_width_in_blocks) + max_width_in_blocks = srcinfo->comp_info[i].width_in_blocks; + /* Allocate and prepare bmp[] */ + planes[i].allocate(width[i], height[i]); + bmp[i] = planes[i].ptr; + } + + /* The function jpeg_read_raw_data will return an MCU per call */ + int nscanlines = srcinfo->max_v_samp_factor*DCTSIZE; + + /* Get memory for the buffer scanline pointers */ + JSAMPARRAY *scanplanes = new JSAMPARRAY[nplanes]; + + /* Get memory for each scanline in the buffer */ + for (unsigned int plane = 0; plane < nplanes; ++plane) + { + scanplanes[plane] = new JSAMPROW[nscanlines]; + for (int isl = 0; isl < nscanlines; ++isl) + scanplanes[plane][isl] = new JSAMPLE[max_width_in_blocks * DCTSIZE]; + } + + unsigned int row[nplanes]; + unsigned int div_v_factor[nplanes]; + for (unsigned int plane = 0; plane < nplanes; ++plane) + { + row[plane] = 0; + div_v_factor[plane] = srcinfo->max_v_samp_factor / + srcinfo->comp_info[plane].v_samp_factor; + } + + while (srcinfo->output_scanline < srcinfo->output_height) { + int read_scanlines = + jpeg_read_raw_data(srcinfo, scanplanes, nscanlines); + for (unsigned int plane = 0; plane < nplanes; ++plane) + { + if (row[plane] >= height[plane]) + continue; + for (int isl = 0; isl < (read_scanlines / (int) div_v_factor[plane]); ++isl) + { + for (unsigned int column = 0; column < width[plane]; + ++column) { + bmp[plane][row[plane] * width[plane] + column] = + scanplanes[plane][isl][column]; + } + ++row[plane]; + } + } + } + + jpeg_destroy_decompress(srcinfo); + + fclose(inputh); + + Image *i = new Image(planes, nplanes); + + delete[] planes; + for (unsigned int plane = 0; plane < nplanes; ++plane) + { + for (int isl = 0; isl < nscanlines; ++isl) + delete[] scanplanes[plane][isl]; + delete[] scanplanes[plane]; + } + delete[] scanplanes; + + return i; +} + +Image *JPEGFile::getUnpackedImage() +{ + readHeader(); + + /* Set our JPEG decompression parameters */ + srcinfo->do_fancy_upsampling = 1; + srcinfo->dct_method = JDCT_FLOAT; + + /* Get the number of planes */ + if (srcinfo->num_components == 1 && + srcinfo->jpeg_color_space == JCS_GRAYSCALE) { + srcinfo->out_color_components = 1; + srcinfo->out_color_space = JCS_GRAYSCALE; + } + else { + srcinfo->out_color_components = 3; + srcinfo->out_color_space = JCS_RGB; + } + + /* Start decompression of pixels */ + jpeg_start_decompress(srcinfo); + + unsigned int nplanes = srcinfo->out_color_components; + + /* Create the planes */ + FloatPlane *planes = new FloatPlane[nplanes]; + + /* Get the pointers to the planes */ + float *bmp[srcinfo->out_color_components]; + for (unsigned int i=0; i < nplanes; i++) + { + planes[i].allocate(srcinfo->output_width, srcinfo->output_height); + bmp[i] = planes[i].ptr; + } + + /* Get the recommended number of buffer scanlines */ + int nscanlines = srcinfo->rec_outbuf_height; + + /* Get memory for the buffer scanline pointers */ + JSAMPROW *scanlines = new JSAMPROW[nscanlines]; + + /* Get memory for each scanline in the buffer */ + for (int isl = 0; isl < nscanlines; ++isl) + { + scanlines[isl] = new JSAMPLE[srcinfo->output_width * nplanes]; + } + + int row = 0; + while (srcinfo->output_scanline < srcinfo->output_height) { + int read_scanlines = + jpeg_read_scanlines(srcinfo, scanlines, nscanlines); + for (int isl = 0; isl < read_scanlines; ++isl) + { + for (unsigned int column = 0; column < srcinfo->output_width; + ++column) { + for (unsigned int plane = 0; plane < nplanes; plane++) + bmp[plane][row * srcinfo->output_width + column] = + scanlines[isl][column * srcinfo->out_color_components + + plane]; + } + ++row; + } + } + + jpeg_destroy_decompress(srcinfo); + + fclose(inputh); + + Image *i = new Image(planes, nplanes); + + delete[] planes; + for (int isl = 0; isl < nscanlines; ++isl) + delete[] scanlines[isl]; + delete[] scanlines; + + return i; +} + +JPEGFile::~JPEGFile() +{ + delete[] filename; + delete srcinfo; + delete jsrcerr; +} diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/JPEGFile.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/JPEGFile.h Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,29 @@ +#include + +class Image; + +extern "C" { +struct jpeg_decompress_struct; +struct jpeg_error_mgr; +} + +class JPEGFile +{ + char * filename; + Image *iDCTImage; + Image *unpackedImage; + + FILE *inputh; + + struct jpeg_decompress_struct *srcinfo; + struct jpeg_error_mgr *jsrcerr; + + void readHeader(); + +public: + JPEGFile (const char *_filename); + ~JPEGFile(); + + Image * getiDCTImage(); + Image * getUnpackedImage(); +}; diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/Makefile Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,23 @@ +CXXFLAGS?=-Wall -g + +.o: + $(CXX) $(LDFLAGS) $(LIBS) -o $@ $^ + +# Tests +tests: testFP testJPEGFile + +testFP: testFP.o FloatPlane.o + $(CXX) $(LDFLAGS) -lnetpbm -o $@ $^ +testJPEGFile: testJPEGFile.o FloatPlane.o Image.o JPEGFile.o + $(CXX) $(LDFLAGS) -lnetpbm -ljpeg -o $@ $^ +testFP.o: testFP.cpp FloatPlane.h +testJPEGFile.o: testFP.cpp FloatPlane.h +testJPEGFile.o: testJPEGFile.cpp Image.h JPEGFile.h + +# API +FloatPlane.o: FloatPlane.cpp FloatPlane.h +Image.o: Image.cpp FloatPlane.h Image.h +JPEGFile.o: JPEGFile.cpp JPEGFile.h FloatPlane.h Image.h + +clean: + rm -f *.o testFP diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/data.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/data.txt Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,7 @@ +output from jpeg_read_scanlines() +-------------------------------- +JSAMPLE scanlines[0..nscanlines][column * nplanes + plane] + +output from decompress() or jpeg_read_raw_data() +-------------------------------- +JSAMPLE scanlines[0..planes][scanline][column] diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/testFP.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/testFP.cpp Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,19 @@ +#include "FloatPlane.h" + +int main() +{ + FloatPlane a; + + a.allocate(100,100); + + float *p = a.getPtr(); + unsigned int w = a.getWidth(); + + for(int j=0; j < 100; j++) + for(int i=0; i < 100; i++) + p[j*w + i] = (float) ((i+j) % 255); + + a.writePGM("prova.pgm"); + + a.free(); +} diff -r 327eef3fe747 -r 9cbf4c7e7986 qjpeg/testJPEGFile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qjpeg/testJPEGFile.cpp Mon Jan 22 00:45:57 2007 +0100 @@ -0,0 +1,31 @@ +#include "JPEGFile.h" +#include "Image.h" +#include "FloatPlane.h" + +int main() +{ + JPEGFile a("a.jpg"); + + Image *i; + + i = a.getUnpackedImage(); + + /* Write the planes */ + i->plane[0].writePGM("hola1.pgm"); + i->plane[1].writePGM("hola2.pgm"); + i->plane[2].writePGM("hola3.pgm"); + + i->writePPM("hola.ppm"); + /* Remove the image and its planes */ + i->free(); + + i = a.getiDCTImage(); + + /* Write the planes */ + i->plane[0].writePGM("ihola1.pgm"); + i->plane[1].writePGM("ihola2.pgm"); + i->plane[2].writePGM("ihola3.pgm"); + + i->free(); + delete i; +}