Commit c415d524 authored by Tomáš Oberhuber's avatar Tomáš Oberhuber
Browse files

Implementing JPEG image.

parent 84514204
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -28,6 +28,14 @@
#include <core/io/tnlImage.h>
#include <core/io/tnlRegionOfInterest.h>

#ifdef HAVE_JPEG_H      
struct my_error_mgr
{
   jpeg_error_mgr pub;
   jmp_buf setjmp_buffer;
};
#endif

template< typename Index = int >
class tnlJPEGImage : public tnlImage< Index >
{
@@ -74,13 +82,10 @@ class tnlJPEGImage : public tnlImage< Index >
      bool fileOpen;

#ifdef HAVE_JPEG_H      
      struct my_error_mgr
      {
         jpeg_error_mgr pub;
         jmp_buf setjmp_buffer;
      };
      
      my_error_mgr jerr;
      jpeg_decompress_struct cinfo;
      int components;
      J_COLOR_SPACE color_space;
#endif         
};

+69 −153
Original line number Diff line number Diff line
@@ -18,7 +18,21 @@
#ifndef TNLJPEGIMAGE_IMPL_H
#define	TNLJPEGIMAGE_IMPL_H

#include <core/io/tnlJPEGImage.h"
#include <core/io/tnlJPEGImage.h>
#include <setjmp.h>

inline void my_error_exit( j_common_ptr cinfo )
{
  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  my_error_mgr* myerr = ( my_error_mgr* ) cinfo->err;

  /* Always display the message. */
  /* We could postpone this until after returning, if we chose. */
  ( *cinfo->err->output_message )( cinfo );

  /* Return control to the setjmp point */
  longjmp( myerr->setjmp_buffer, 1 );
}

template< typename Index >
tnlJPEGImage< Index >::
@@ -32,74 +46,34 @@ bool
tnlJPEGImage< Index >::
readHeader()
{
#ifdef HAVE_PNG_H
#ifdef HAVE_JPEG_H
   this->cinfo.err = jpeg_std_error(&jerr.pub);
   this->jerr.pub.error_exit = my_error_exit; 
   
   /***
    * Check if it is a PNG image.
    * Prepare the long jump back from libjpeg.
    */
   const int headerSize( 8 );
   png_byte header[ headerSize ];
   if( fread( header, sizeof( char ), headerSize, this->file ) != headerSize )
   if( setjmp( jerr.setjmp_buffer ) )
   {
      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
        * If we get here, the JPEG code has signaled an error.
        * We need to clean up the JPEG object, close the input file, and return.
        */
   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 );
      jpeg_destroy_decompress( &this->cinfo );
      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 );
   jpeg_create_decompress( &this->cinfo );
   jpeg_stdio_src( &this->cinfo, this->file );
   if( jpeg_read_header( &this->cinfo, true ) != JPEG_HEADER_OK )
      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;   
   this->height = this->cinfo.image_height;
   this->width = this->cinfo.image_width;
   this->components = this->cinfo.num_components; 
   //this->color_space = this->cinfo.jpeg_color_space;
   //cout << this->height << " x " << this->width << " : " << this->components << " " << this->color_space << endl;
#else
   cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
   cerr << "TNL was not compiled with support of JPEG. You may still use PGM format." << endl;
   return false;
#endif   
}
@@ -137,21 +111,29 @@ read( const tnlRegionOfInterest< Index > roi,
   typedef typename GridType::CoordinatesType CoordinatesType;
   
   /***
    * Prepare the long jump back from libpng.
    * Prepare the long jump back from libjpeg.
    */
   if( setjmp(png_jmpbuf( this->png_ptr ) ) )
   if( setjmp( jerr.setjmp_buffer ) )
   {
      png_destroy_read_struct( &this->png_ptr,
                               &this->info_ptr,
                               &this->end_info );
       /****
        * If we get here, the JPEG code has signaled an error.
        * We need to clean up the JPEG object, close the input file, and return.
        */
      jpeg_destroy_decompress( &this->cinfo );
      return false;
   }
      
   png_bytepp row_pointers = png_get_rows( this->png_ptr, this->info_ptr );
   jpeg_start_decompress( &this->cinfo );
   int row_stride = this->cinfo.output_width * this->cinfo.output_components;
   JSAMPARRAY row = ( *( this->cinfo.mem->alloc_sarray ) )( ( j_common_ptr ) &this->cinfo,
                                                            JPOOL_IMAGE,
                                                            row_stride,
                                                            1 );	
   
   Index i, j;
   for( i = 0; i < this->height; i ++ )
   while( this->cinfo.output_scanline < this->cinfo.output_height)
   {
      jpeg_read_scanlines( &this->cinfo, row, 1 );
      for( j = 0; j < this->width; j ++ )
      {
         if( !roi.isIn( i, j ) )
@@ -161,55 +143,33 @@ read( const tnlRegionOfInterest< Index > roi,
                                              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 )
         Real value, r, g, b;
         switch( this->components )
         {
                  char_color[ 0 ] = row_pointers[ i ][ j ];
                  Real value = char_color[ 0 ] / ( Real ) 255.0;
            case 1:
               char_color[ 0 ] = row[ 0 ][ j ];
               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;
            case 3:
               char_color[ 0 ] = row[ 0 ][ 3 * j ];
               char_color[ 1 ] = row[ 0 ][ 3 * j + 1 ];
               char_color[ 2 ] = row[ 0 ][ 3 * j + 2 ];
               r = char_color[ 0 ] / ( Real ) 255.0;
               g = char_color[ 1 ] / ( Real ) 255.0;
               b = char_color[ 2 ] / ( Real ) 255.0;
               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;
               cerr << "Unknown JPEG color type." << endl;
               return false;
         }
      }
   }
   return true;
#else
   cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
   //cerr << "TNL was not compiled with support of JPEG. You may still use PGM format." << endl;
   return false;
#endif      
}
@@ -221,51 +181,7 @@ 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 );
   
#ifdef HAVE_JPEG_H
#else
   cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
   return false;
+16 −12
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
#ifndef TNLPNGIMAGE_IMPL_H
#define	TNLPNGIMAGE_IMPL_H

#include "tnlPNGImage.h"
#include <core/io/tnlPNGImage.h>

template< typename Index >
tnlPNGImage< Index >::
@@ -99,7 +99,7 @@ readHeader()
   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;
   //cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
   return false;
#endif   
}
@@ -160,7 +160,7 @@ read( const tnlRegionOfInterest< Index > roi,
         Index cellIndex = grid.getCellIndex( CoordinatesType( j - roi.getLeft(),
                                              roi.getBottom() - 1 - i ) );
         unsigned char char_color[ 4 ];
         unsigned int int_color[ 4 ];
         unsigned short int int_color[ 4 ];
         switch( this->color_type )
         {
            case PNG_COLOR_TYPE_GRAY:
@@ -180,9 +180,10 @@ read( const tnlRegionOfInterest< Index > roi,
            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 ];
                  unsigned char* row = ( unsigned char* ) row_pointers[ i ];
                  char_color[ 0 ] = row[ 3 * j ];
                  char_color[ 1 ] = row[ 3 * j + 1 ];
                  char_color[ 2 ] = row[ 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;
@@ -191,9 +192,10 @@ read( const tnlRegionOfInterest< Index > roi,
               }
               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 ];
                  unsigned short int* row = ( unsigned short int* ) row_pointers[ i ];
                  int_color[ 0 ] = row[ 3 * j ];
                  int_color[ 1 ] = row[ 3 * j + 1 ];
                  int_color[ 2 ] = row[ 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;
@@ -209,7 +211,7 @@ read( const tnlRegionOfInterest< Index > roi,
   }
   return true;
#else
   cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
   //cerr << "TNL was not compiled with support of PNG. You may still use PGM format." << endl;
   return false;
#endif      
}
@@ -302,6 +304,7 @@ tnlPNGImage< Index >::
write( 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;
   
@@ -329,10 +332,11 @@ write( const tnlGrid< 2, Real, Device, Index >& grid,
      }
      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;
#else
   return false;
#endif   
}


+1 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ ADD_EXECUTABLE(tnl-dicom-reader${debugExt} ${tnl_dicom_reader_SOURCES})
target_link_libraries (tnl-dicom-reader${debugExt} tnl${debugExt}-${tnlVersion} )

ADD_EXECUTABLE(tnl-image-converter${debugExt} ${tnl_image_converter_SOURCES})
target_link_libraries (tnl-image-converter${debugExt} tnl${debugExt}-${tnlVersion} ${PNG_LIBRARIES})
target_link_libraries (tnl-image-converter${debugExt} tnl${debugExt}-${tnlVersion} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} )


ADD_EXECUTABLE( tnl-functions-benchmark${debugExt} ${tnlfunctionsbenchmarksources} )
+3 −3
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ bool processImages( const tnlParameterContainer& parameters )
         cout << "JPEG format detected ...";
         if( i == 0 )
         {
            if( ! roi.setup( parameters, &pngImage ) )
            if( ! roi.setup( parameters, &jpegImage ) )
               return false;
            setGrid( roi, grid, verbose );
            vector.setSize( grid.getNumberOfCells() );
@@ -139,9 +139,9 @@ bool processImages( const tnlParameterContainer& parameters )
            grid.save( meshFile );
         }
         else 
            if( ! roi.check( &pgmImage ) )
            if( ! roi.check( &jpegImage ) )
               return false;
         if( ! pngImage.read( roi, grid, vector ) )
         if( ! jpegImage.read( roi, grid, vector ) )
            return false;
         tnlString outputFileName( fileName );
         RemoveFileExtension( outputFileName );