static void ReadJP2KImage( GenericImage<P>& img, jas_stream_t* jp2Stream, jas_image_t* jp2Image ) { int width = jas_image_cmptwidth( jp2Image, 0 ); int height = jas_image_cmptheight( jp2Image, 0 ); int numberOfChannels = jas_image_numcmpts( jp2Image ); jas_matrix_t* pixels = nullptr; try { pixels = jas_matrix_create( 1, width ); if ( pixels == nullptr ) throw Error( "Memory allocation error reading JPEG2000 image" ); // Allocate pixel data img.AllocateData( width, height, numberOfChannels, (jas_clrspc_fam( jas_image_clrspc( jp2Image ) ) == JAS_CLRSPC_FAM_GRAY) ? ColorSpace::Gray : ColorSpace::RGB ); for ( int c = 0; c < numberOfChannels; ++c ) { int n = jas_image_cmptprec( jp2Image, c ); bool s = jas_image_cmptsgnd( jp2Image, c ) != 0; for ( int y = 0; y < height; ++y ) { jas_image_readcmpt( jp2Image, c, 0, y, width, 1, pixels ); typename P::sample* f = img.ScanLine( y, c ); if ( n == 8 ) { if ( s ) for ( int x = 0; x < width; ++x ) *f++ = P::ToSample( int8( jas_matrix_get( pixels, 0, x ) ) ); else for ( int x = 0; x < width; ++x ) *f++ = P::ToSample( uint8( jas_matrix_get( pixels, 0, x ) ) ); } else { if ( s ) for ( int x = 0; x < width; ++x ) *f++ = P::ToSample( int16( jas_matrix_get( pixels, 0, x ) ) ); else for ( int x = 0; x < width; ++x ) *f++ = P::ToSample( uint16( jas_matrix_get( pixels, 0, x ) ) ); } } } jas_matrix_destroy( pixels ), pixels = nullptr; } catch ( ... ) { if ( pixels != nullptr ) jas_matrix_destroy( pixels ); throw; } }
static void LoadAndTransformImage( GenericImage<P>& transform, const GenericImage<P1>& image, bool parallel, int maxProcessors ) { Rect r = image.SelectedRectangle(); if ( !r.IsRect() ) return; int w = FFTC::OptimizedLength( r.Width() ); int h = FFTC::OptimizedLength( r.Height() ); int dw2 = (w - r.Width()) >> 1; int dh2 = (h - r.Height()) >> 1; transform.AllocateData( w, h, image.NumberOfSelectedChannels(), (image.NumberOfSelectedChannels() < 3 || image.FirstSelectedChannel() != 0) ? ColorSpace::Gray : image.ColorSpace() ); transform.Zero().Move( image, Point( dw2, dh2 ) ); ApplyInPlaceFourierTransform( transform, FFTDirection::Forward, parallel, maxProcessors ); }
static void ApplyInverseRealFourierTransform_2( GenericImage<P>& image, const GenericImage<P1>& dft, bool parallel, int maxProcessors ) { if ( dft.IsEmpty() ) { image.FreeData(); return; } int w = dft.Width(); int h = dft.Height(); image.AllocateData( 2*(w - 1), h, dft.NumberOfChannels(), dft.ColorSpace() ); bool statusInitialized = false; if ( image.Status().IsInitializationEnabled() ) { image.Status().Initialize( "Inverse FFT", image.NumberOfChannels()*size_type( w + h ) ); image.Status().DisableInitialization(); statusInitialized = true; } try { FFTR F( h, w, image.Status() ); F.EnableParallelProcessing( parallel, maxProcessors ); for ( int c = 0; c < image.NumberOfChannels(); ++c ) F( image[c], dft[c] ); if ( statusInitialized ) image.Status().EnableInitialization(); } catch ( ... ) { if ( statusInitialized ) image.Status().EnableInitialization(); throw; } }
static void ReadJPEGImage( GenericImage<P>& img, JPEGReader& reader, JPEGFileData* fileData ) { if ( !reader.IsOpen() ) throw JPEG::InvalidReadOperation( String() ); JSAMPLE* buffer = nullptr; // one-row sample array for scanline reading typename P::sample** v = nullptr; // pointers to destination scan lines try { // Set parameters for decompression. // Most parameters have already been established by Open(). // We just ensure that we'll get either a grayscale or a RGB color image. if ( jpeg_decompressor->out_color_space != JCS_GRAYSCALE ) jpeg_decompressor->out_color_space = JCS_RGB; // Start decompressor. ::jpeg_start_decompress( jpeg_decompressor ); // Allocate pixel data. img.AllocateData( jpeg_decompressor->output_width, jpeg_decompressor->output_height, jpeg_decompressor->output_components, (jpeg_decompressor->out_color_space == JCS_GRAYSCALE) ? ColorSpace::Gray : ColorSpace::RGB ); // Initialize status callback. if ( img.Status().IsInitializationEnabled() ) img.Status().Initialize( String().Format( "Decompressing JPEG: %d channel(s), %dx%d pixels", img.NumberOfChannels(), img.Width(), img.Height() ), img.NumberOfSamples() ); // // Read pixels row by row. // // JSAMPLEs per row in output buffer. int row_stride = img.Width() * img.NumberOfChannels(); // Make a one-row-high sample array. buffer = new JSAMPLE[ row_stride ]; // JPEG organization is chunky; PCL images are planar. v = new typename P::sample*[ img.NumberOfChannels() ]; while ( jpeg_decompressor->output_scanline < jpeg_decompressor->output_height ) { ::jpeg_read_scanlines( jpeg_decompressor, &buffer, 1 ); const JSAMPLE* b = buffer; for ( int c = 0; c < img.NumberOfChannels(); ++c ) v[c] = img.ScanLine( jpeg_decompressor->output_scanline-1, c ); for ( int i = 0; i < img.Width(); ++i ) for ( int c = 0; c < img.NumberOfChannels(); ++c, ++b ) *v[c]++ = P::IsFloatSample() ? typename P::sample( *b ) : P::ToSample( *b ); img.Status() += img.Width()*img.NumberOfChannels(); } // Clean up temporary structures. delete [] v, v = nullptr; delete [] buffer, buffer = nullptr; // Finish decompression. ::jpeg_finish_decompress( jpeg_decompressor ); // ### TODO --> At this point we might check whether any corrupt-data // warnings occurred (test whether jerr.pub.num_warnings is nonzero). } catch ( ... ) { reader.Close(); if ( buffer != nullptr ) delete [] buffer; if ( v != nullptr ) delete [] v; img.FreeData(); throw; } }