Skip to content
Snippets Groups Projects
Commit 84514204 authored by Tomáš Oberhuber's avatar Tomáš Oberhuber
Browse files

Adding JPEG format support.

parent 5573adcb
No related branches found
No related tags found
No related merge requests found
......@@ -184,7 +184,7 @@ parseCommandLine( int argc, char* argv[],
if( strcmp( _option, "--help" ) == 0 )
{
config_description.printUsage( argv[ 0 ] );
continue;
return true;
}
const char* option = _option + 2;
const tnlConfigEntryBase* entry;
......
/***************************************************************************
tnlJPEGImage.h - description
-------------------
begin : Jul 25, 2015
copyright : (C) 2015 by Tomas Oberhuber
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef TNLJPEGIMAGE_H
#define TNLJPEGIMAGE_H
#include <tnlConfig.h>
#ifdef HAVE_JPEG_H
#include <jpeglib.h>
#endif
#include <core/tnlString.h>
#include <core/io/tnlImage.h>
#include <core/io/tnlRegionOfInterest.h>
template< typename Index = int >
class tnlJPEGImage : public tnlImage< Index >
{
public:
typedef Index IndexType;
tnlJPEGImage();
bool openForRead( const tnlString& fileName );
template< typename Real,
typename Device,
typename Vector >
bool read( const tnlRegionOfInterest< Index > roi,
const tnlGrid< 2, Real, Device, Index >& grid,
Vector& vector );
template< typename Real,
typename Device >
bool openForWrite( const tnlString& fileName,
tnlGrid< 2, Real, Device, Index >& grid );
template< typename Real,
typename Device,
typename Vector >
bool write( const tnlGrid< 2, Real, Device, Index >& grid,
Vector& vector );
void close();
~tnlJPEGImage();
protected:
bool readHeader();
template< typename Real,
typename Device >
bool writeHeader( const tnlGrid< 2, Real, Device, Index >& grid );
FILE* file;
bool fileOpen;
#ifdef HAVE_JPEG_H
struct my_error_mgr
{
jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
jpeg_decompress_struct cinfo;
#endif
};
#include <core/io/tnlJPEGImage_impl.h>
#endif /* TNLJPEGIMAGE_H */
/***************************************************************************
tnlJPEGImage_impl.h - description
-------------------
begin : Jul 25, 2015
copyright : (C) 2015 by Tomas Oberhuber
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef TNLJPEGIMAGE_IMPL_H
#define TNLJPEGIMAGE_IMPL_H
#include <core/io/tnlJPEGImage.h"
template< typename Index >
tnlJPEGImage< Index >::
tnlJPEGImage() :
fileOpen( false )
{
}
template< typename Index >
bool
tnlJPEGImage< Index >::
readHeader()
{
#ifdef HAVE_PNG_H
/***
* Check if it is a PNG image.
*/
const int headerSize( 8 );
png_byte header[ headerSize ];
if( fread( header, sizeof( char ), headerSize, this->file ) != headerSize )
{
cerr << "I am not able to read PNG image header." << endl;
return false;
}
bool isPNG = !png_sig_cmp( header, 0, headerSize );
if( ! isPNG )
return false;
/****
* Allocate necessary memory
*/
this->png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL );
if( !this->png_ptr )
return false;
this->info_ptr = png_create_info_struct( this->png_ptr );
if( !this->info_ptr )
{
png_destroy_read_struct( &this->png_ptr,
( png_infopp ) NULL,
( png_infopp ) NULL );
return false;
}
this->end_info = png_create_info_struct( this->png_ptr );
if( !this->end_info )
{
png_destroy_read_struct( &this->png_ptr,
&this->info_ptr,
( png_infopp ) NULL );
return false;
}
/***
* Prepare the long jump back from libpng.
*/
if( setjmp(png_jmpbuf( this->png_ptr ) ) )
{
png_destroy_read_struct( &this->png_ptr,
&this->info_ptr,
&end_info );
return false;
}
png_init_io( this->png_ptr, this->file );
png_set_sig_bytes( this->png_ptr, headerSize );
/****
* Read the header
*/
png_read_png( this->png_ptr, this->info_ptr, PNG_TRANSFORM_IDENTITY, NULL );
this->height = ( Index ) png_get_image_height( this->png_ptr, this->info_ptr );
this->width = ( Index ) png_get_image_width( this->png_ptr, this->info_ptr );
this->bit_depth = png_get_bit_depth( this->png_ptr, this->info_ptr );
this->color_type = png_get_color_type( this->png_ptr, this->info_ptr );
cout << this->height << " x " << this->width << endl;
return true;
#else
cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
return false;
#endif
}
template< typename Index >
bool
tnlJPEGImage< Index >::
openForRead( const tnlString& fileName )
{
this->close();
this->file = fopen( fileName.getString(), "r" );
if( ! this->file )
{
cerr << "Unable to open the file " << fileName << endl;
return false;
}
this->fileOpen = true;
if( ! readHeader() )
return false;
return true;
}
template< typename Index >
template< typename Real,
typename Device,
typename Vector >
bool
tnlJPEGImage< Index >::
read( const tnlRegionOfInterest< Index > roi,
const tnlGrid< 2, Real, Device, Index >& grid,
Vector& vector )
{
#ifdef HAVE_PNG_H
typedef tnlGrid< 2, Real, Device, Index > GridType;
typedef typename GridType::CoordinatesType CoordinatesType;
/***
* Prepare the long jump back from libpng.
*/
if( setjmp(png_jmpbuf( this->png_ptr ) ) )
{
png_destroy_read_struct( &this->png_ptr,
&this->info_ptr,
&this->end_info );
return false;
}
png_bytepp row_pointers = png_get_rows( this->png_ptr, this->info_ptr );
Index i, j;
for( i = 0; i < this->height; i ++ )
{
for( j = 0; j < this->width; j ++ )
{
if( !roi.isIn( i, j ) )
continue;
Index cellIndex = grid.getCellIndex( CoordinatesType( j - roi.getLeft(),
roi.getBottom() - 1 - i ) );
unsigned char char_color[ 4 ];
unsigned int int_color[ 4 ];
switch( this->color_type )
{
case PNG_COLOR_TYPE_GRAY:
if( this->bit_depth == 8 )
{
char_color[ 0 ] = row_pointers[ i ][ j ];
Real value = char_color[ 0 ] / ( Real ) 255.0;
vector.setElement( cellIndex, value );
}
if( this->bit_depth == 16 )
{
int_color[ 0 ] = row_pointers[ i ][ j ];
Real value = int_color[ 0 ] / ( Real ) 65535.0;
vector.setElement( cellIndex, value );
}
break;
case PNG_COLOR_TYPE_RGB:
if( this->bit_depth == 8 )
{
char_color[ 0 ] = row_pointers[ i ][ 3 * j ];
char_color[ 1 ] = row_pointers[ i ][ 3 * j + 1 ];
char_color[ 2 ] = row_pointers[ i ][ 3 * j + 2 ];
Real r = char_color[ 0 ] / ( Real ) 255.0;
Real g = char_color[ 1 ] / ( Real ) 255.0;
Real b = char_color[ 2 ] / ( Real ) 255.0;
Real value = 0.2989 * r + 0.5870 * g + 0.1140 * b;
vector.setElement( cellIndex, value );
}
if( this->bit_depth == 16 )
{
int_color[ 0 ] = row_pointers[ i ][ 3 * j ];
int_color[ 1 ] = row_pointers[ i ][ 3 * j + 1 ];
int_color[ 2 ] = row_pointers[ i ][ 3 * j + 2 ];
Real r = int_color[ 0 ] / ( Real ) 65535.0;
Real g = int_color[ 1 ] / ( Real ) 66355.0;
Real b = int_color[ 2 ] / ( Real ) 65535.0;
Real value = 0.2989 * r + 0.5870 * g + 0.1140 * b;
vector.setElement( cellIndex, value );
}
break;
default:
cerr << "Unknown PNG color type." << endl;
return false;
}
}
}
return true;
#else
cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
return false;
#endif
}
template< typename Index >
template< typename Real,
typename Device >
bool
tnlJPEGImage< Index >::
writeHeader( const tnlGrid< 2, Real, Device, Index >& grid )
{
#ifdef HAVE_PNG_H
this->png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL );
if( !png_ptr )
return false;
this->info_ptr = png_create_info_struct( this->png_ptr );
if( !this->info_ptr )
{
png_destroy_write_struct( &this->png_ptr,
NULL);
return false;
}
/***
* Prepare the long jump back from libpng.
*/
if( setjmp(png_jmpbuf( this->png_ptr ) ) )
{
png_destroy_read_struct( &this->png_ptr,
&this->info_ptr,
&this->end_info );
return false;
}
/****
* Set the zlib compression level
*/
//png_set_compression_level( this->png_ptr, Z_BEST_COMPRESSION );
const int bitDepth( 8 );
png_set_IHDR( this->png_ptr,
this->info_ptr,
grid.getDimensions().x(),
grid.getDimensions().y(),
8, //bitDepth,
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT );
png_init_io( this->png_ptr, this->file );
png_write_info( png_ptr, info_ptr );
#else
cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
return false;
#endif
}
template< typename Index >
template< typename Real,
typename Device >
bool
tnlJPEGImage< Index >::
openForWrite( const tnlString& fileName,
tnlGrid< 2, Real, Device, Index >& grid )
{
this->close();
this->file = fopen( fileName.getString(), "w" );
if( ! this->file )
{
cerr << "Unable to open the file " << fileName << endl;
return false;
}
this->fileOpen = true;
if( ! writeHeader( grid ) )
return false;
return true;
}
template< typename Index >
template< typename Real,
typename Device,
typename Vector >
bool
tnlJPEGImage< Index >::
write( const tnlGrid< 2, Real, Device, Index >& grid,
Vector& vector )
{
typedef tnlGrid< 2, Real, Device, Index > GridType;
typedef typename GridType::CoordinatesType CoordinatesType;
/***
* Prepare the long jump back from libpng.
*/
if( setjmp(png_jmpbuf( this->png_ptr ) ) )
{
png_destroy_read_struct( &this->png_ptr,
&this->info_ptr,
&this->end_info );
return false;
}
Index i, j;
png_bytep row = new png_byte[ 3 * grid.getDimensions().x() ];
for( i = 0; i < grid.getDimensions().y(); i ++ )
{
for( j = 0; j < grid.getDimensions().x(); j ++ )
{
Index cellIndex = grid.getCellIndex( CoordinatesType( j,
grid.getDimensions().y() - 1 - i ) );
row[ j ] = 255 * vector.getElement( cellIndex );
}
png_write_row( this->png_ptr, row );
}
//png_set_rows( this->png_ptr, this->info_ptr, row_pointers );
//png_write_png( this->png_ptr, this->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
delete[] row;
return true;
}
template< typename Index >
void
tnlJPEGImage< Index >::
close()
{
if( this->fileOpen )
fclose( file );
this->fileOpen = false;
}
template< typename Index >
tnlJPEGImage< Index >::
~tnlJPEGImage()
{
close();
}
#endif /* TNLJPEGIMAGE_IMPL_H */
......@@ -49,8 +49,7 @@ class tnlPNGImage : public tnlImage< Index >
template< typename Real,
typename Device >
bool openForWrite( const tnlString& fileName,
tnlGrid< 2, Real, Device, Index >& grid,
bool binary = true );
tnlGrid< 2, Real, Device, Index >& grid );
template< typename Real,
typename Device,
......@@ -68,8 +67,7 @@ class tnlPNGImage : public tnlImage< Index >
template< typename Real,
typename Device >
bool writeHeader( const tnlGrid< 2, Real, Device, Index >& grid,
bool binary );
bool writeHeader( const tnlGrid< 2, Real, Device, Index >& grid );
FILE* file;
......
......@@ -18,9 +18,7 @@
#ifndef TNLPNGIMAGE_IMPL_H
#define TNLPNGIMAGE_IMPL_H
#ifdef HAVE_PNG_H
#include <png.h>
#endif
#include "tnlPNGImage.h"
template< typename Index >
tnlPNGImage< Index >::
......@@ -94,8 +92,8 @@ readHeader()
* Read the header
*/
png_read_png( this->png_ptr, this->info_ptr, PNG_TRANSFORM_IDENTITY, NULL );
this->height = this->info_ptr->height; //( Index ) png_get_image_height( this->png_ptr, this->info_ptr );
this->width = this->info_ptr->width; //( Index ) png_get_image_width( this->png_ptr, this->info_ptr );
this->height = ( Index ) png_get_image_height( this->png_ptr, this->info_ptr );
this->width = ( Index ) png_get_image_width( this->png_ptr, this->info_ptr );
this->bit_depth = png_get_bit_depth( this->png_ptr, this->info_ptr );
this->color_type = png_get_color_type( this->png_ptr, this->info_ptr );
cout << this->height << " x " << this->width << endl;
......@@ -221,10 +219,9 @@ template< typename Index >
typename Device >
bool
tnlPNGImage< Index >::
writeHeader( const tnlGrid< 2, Real, Device, Index >& grid,
bool binary )
writeHeader( const tnlGrid< 2, Real, Device, Index >& grid )
{
#idef HAVE_PNG_H
#ifdef HAVE_PNG_H
this->png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING,
NULL,
NULL,
......@@ -240,11 +237,39 @@ writeHeader( const tnlGrid< 2, Real, Device, Index >& grid,
return false;
}
/***
* Prepare the long jump back from libpng.
*/
if( setjmp(png_jmpbuf( this->png_ptr ) ) )
{
png_destroy_read_struct( &this->png_ptr,
&this->info_ptr,
&this->end_info );
return false;
}
/****
* Set the zlib compression level
*/
//png_set_compression_level( this->png_ptr, Z_BEST_COMPRESSION );
const int bitDepth( 8 );
png_set_IHDR( this->png_ptr,
this->info_ptr,
grid.getDimensions().x(),
grid.getDimensions().y(),
8, //bitDepth,
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT );
png_init_io( this->png_ptr, this->file );
png_write_info( png_ptr, info_ptr );
#else
cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
return false;
#endif
#endif
}
template< typename Index >
......@@ -268,6 +293,48 @@ openForWrite( const tnlString& fileName,
return true;
}
template< typename Index >
template< typename Real,
typename Device,
typename Vector >
bool
tnlPNGImage< Index >::
write( const tnlGrid< 2, Real, Device, Index >& grid,
Vector& vector )
{
typedef tnlGrid< 2, Real, Device, Index > GridType;
typedef typename GridType::CoordinatesType CoordinatesType;
/***
* Prepare the long jump back from libpng.
*/
if( setjmp(png_jmpbuf( this->png_ptr ) ) )
{
png_destroy_read_struct( &this->png_ptr,
&this->info_ptr,
&this->end_info );
return false;
}
Index i, j;
png_bytep row = new png_byte[ 3 * grid.getDimensions().x() ];
for( i = 0; i < grid.getDimensions().y(); i ++ )
{
for( j = 0; j < grid.getDimensions().x(); j ++ )
{
Index cellIndex = grid.getCellIndex( CoordinatesType( j,
grid.getDimensions().y() - 1 - i ) );
row[ j ] = 255 * vector.getElement( cellIndex );
}
png_write_row( this->png_ptr, row );
}
//png_set_rows( this->png_ptr, this->info_ptr, row_pointers );
//png_write_png( this->png_ptr, this->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
delete[] row;
return true;
}
template< typename Index >
void
......
......@@ -21,6 +21,7 @@
#include <mesh/tnlGrid.h>
#include <core/io/tnlPGMImage.h>
#include <core/io/tnlPNGImage.h>
#include <core/io/tnlJPEGImage.h>
#include <core/io/tnlRegionOfInterest.h>
void configSetup( tnlConfigDescription& config )
......@@ -70,61 +71,87 @@ bool processImages( const tnlParameterContainer& parameters )
tnlRegionOfInterest< int > roi;
for( int i = 0; i < inputImages.getSize(); i++ )
{
const tnlString& fileName = inputImages[ i ];
cout << "Processing image file " << fileName << "... ";
tnlPGMImage< int > pgmImage;
if( pgmImage.openForRead( fileName ) )
{
cout << "PGM format detected ...";
if( i == 0 )
{
if( ! roi.setup( parameters, &pgmImage ) )
return false;
setGrid( roi, grid, verbose );
vector.setSize( grid.getNumberOfCells() );
cout << "Writing grid to file " << meshFile << endl;
grid.save( meshFile );
}
else
if( ! roi.check( &pgmImage ) )
return false;
if( ! pgmImage.read( roi, grid, vector ) )
return false;
tnlString outputFileName( fileName );
RemoveFileExtension( outputFileName );
outputFileName += ".tnl";
cout << "Writing image data to " << outputFileName << endl;
vector.save( outputFileName );
pgmImage.close();
continue;
}
tnlPNGImage< int > pngImage;
if( pngImage.openForRead( fileName ) )
{
cout << "PNG format detected ...";
if( i == 0 )
{
if( ! roi.setup( parameters, &pngImage ) )
return false;
setGrid( roi, grid, verbose );
vector.setSize( grid.getNumberOfCells() );
cout << "Writing grid to file " << meshFile << endl;
grid.save( meshFile );
}
else
if( ! roi.check( &pgmImage ) )
return false;
if( ! pngImage.read( roi, grid, vector ) )
return false;
tnlString outputFileName( fileName );
RemoveFileExtension( outputFileName );
outputFileName += ".tnl";
cout << "Writing image data to " << outputFileName << endl;
vector.save( outputFileName );
pgmImage.close();
continue;
}
}
const tnlString& fileName = inputImages[ i ];
cout << "Processing image file " << fileName << "... ";
tnlPGMImage< int > pgmImage;
if( pgmImage.openForRead( fileName ) )
{
cout << "PGM format detected ...";
if( i == 0 )
{
if( ! roi.setup( parameters, &pgmImage ) )
return false;
setGrid( roi, grid, verbose );
vector.setSize( grid.getNumberOfCells() );
cout << "Writing grid to file " << meshFile << endl;
grid.save( meshFile );
}
else
if( ! roi.check( &pgmImage ) )
return false;
if( ! pgmImage.read( roi, grid, vector ) )
return false;
tnlString outputFileName( fileName );
RemoveFileExtension( outputFileName );
outputFileName += ".tnl";
cout << "Writing image data to " << outputFileName << endl;
vector.save( outputFileName );
pgmImage.close();
continue;
}
tnlPNGImage< int > pngImage;
if( pngImage.openForRead( fileName ) )
{
cout << "PNG format detected ...";
if( i == 0 )
{
if( ! roi.setup( parameters, &pngImage ) )
return false;
setGrid( roi, grid, verbose );
vector.setSize( grid.getNumberOfCells() );
cout << "Writing grid to file " << meshFile << endl;
grid.save( meshFile );
}
else
if( ! roi.check( &pgmImage ) )
return false;
if( ! pngImage.read( roi, grid, vector ) )
return false;
tnlString outputFileName( fileName );
RemoveFileExtension( outputFileName );
outputFileName += ".tnl";
cout << "Writing image data to " << outputFileName << endl;
vector.save( outputFileName );
pgmImage.close();
continue;
}
tnlJPEGImage< int > jpegImage;
if( jpegImage.openForRead( fileName ) )
{
cout << "JPEG format detected ...";
if( i == 0 )
{
if( ! roi.setup( parameters, &pngImage ) )
return false;
setGrid( roi, grid, verbose );
vector.setSize( grid.getNumberOfCells() );
cout << "Writing grid to file " << meshFile << endl;
grid.save( meshFile );
}
else
if( ! roi.check( &pgmImage ) )
return false;
if( ! pngImage.read( roi, grid, vector ) )
return false;
tnlString outputFileName( fileName );
RemoveFileExtension( outputFileName );
outputFileName += ".tnl";
cout << "Writing image data to " << outputFileName << endl;
vector.save( outputFileName );
pgmImage.close();
continue;
}
}
}
bool processTNLFiles( const tnlParameterContainer& parameters )
......@@ -159,6 +186,17 @@ bool processTNLFiles( const tnlParameterContainer& parameters )
image.openForWrite( outputFileName, grid, true );
image.write( grid, vector );
image.close();
continue;
}
if( imageFormat == "png" )
{
tnlPNGImage< int > image;
tnlString outputFileName( fileName );
RemoveFileExtension( outputFileName );
outputFileName += ".png";
image.openForWrite( outputFileName, grid );
image.write( grid, vector );
image.close();
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment