From 84514204d740a23a50a5e267e63214576028dc2c Mon Sep 17 00:00:00 2001
From: Tomas Oberhuber <tomas.oberhuber@fjfi.cvut.cz>
Date: Sat, 25 Jul 2015 18:29:51 +0200
Subject: [PATCH] Adding JPEG format support.

---
 src/config/tnlParameterContainer.cpp |   2 +-
 src/core/io/tnlJPEGImage.h           |  91 +++++++
 src/core/io/tnlJPEGImage_impl.h      | 359 +++++++++++++++++++++++++++
 src/core/io/tnlPNGImage.h            |   6 +-
 src/core/io/tnlPNGImage_impl.h       |  87 ++++++-
 tools/src/tnl-image-converter.cpp    | 148 +++++++----
 6 files changed, 623 insertions(+), 70 deletions(-)
 create mode 100644 src/core/io/tnlJPEGImage.h
 create mode 100644 src/core/io/tnlJPEGImage_impl.h

diff --git a/src/config/tnlParameterContainer.cpp b/src/config/tnlParameterContainer.cpp
index 7e9eea94b1..6483d3dbe2 100644
--- a/src/config/tnlParameterContainer.cpp
+++ b/src/config/tnlParameterContainer.cpp
@@ -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;
diff --git a/src/core/io/tnlJPEGImage.h b/src/core/io/tnlJPEGImage.h
new file mode 100644
index 0000000000..8e607b8692
--- /dev/null
+++ b/src/core/io/tnlJPEGImage.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+                          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 */
+
diff --git a/src/core/io/tnlJPEGImage_impl.h b/src/core/io/tnlJPEGImage_impl.h
new file mode 100644
index 0000000000..9a1c5036a9
--- /dev/null
+++ b/src/core/io/tnlJPEGImage_impl.h
@@ -0,0 +1,359 @@
+/***************************************************************************
+                          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 */
+
diff --git a/src/core/io/tnlPNGImage.h b/src/core/io/tnlPNGImage.h
index f28fc095fd..b907655f2b 100644
--- a/src/core/io/tnlPNGImage.h
+++ b/src/core/io/tnlPNGImage.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;
 
diff --git a/src/core/io/tnlPNGImage_impl.h b/src/core/io/tnlPNGImage_impl.h
index 13b12bbb78..04ca727dde 100644
--- a/src/core/io/tnlPNGImage_impl.h
+++ b/src/core/io/tnlPNGImage_impl.h
@@ -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
diff --git a/tools/src/tnl-image-converter.cpp b/tools/src/tnl-image-converter.cpp
index c4d3ba3277..b0dabea545 100644
--- a/tools/src/tnl-image-converter.cpp
+++ b/tools/src/tnl-image-converter.cpp
@@ -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();
       }
    }     
 }
-- 
GitLab