• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kimgio
 

kimgio

jp2.cpp

00001 // This library is distributed under the conditions of the GNU LGPL.
00002 #include "config.h"
00003 
00004 #ifdef HAVE_JASPER
00005 
00006 #include "jp2.h"
00007 
00008 #if !defined(__STDC_LIMIT_MACROS)
00009 #define __STDC_LIMIT_MACROS
00010 #endif
00011 
00012 #ifdef HAVE_SYS_TYPES_H
00013 #include <sys/types.h>
00014 #endif
00015 #ifdef HAVE_STDINT_H
00016 #include <stdint.h>
00017 #endif
00018 #include <tdetempfile.h>
00019 #include <tqcolor.h>
00020 #include <tqcstring.h>
00021 #include <tqfile.h>
00022 #include <tqimage.h>
00023 
00024 // dirty, but avoids a warning because jasper.h includes jas_config.h.
00025 #undef PACKAGE
00026 #undef VERSION
00027 #include <jasper/jasper.h>
00028 
00029 // code taken in parts from JasPer's jiv.c
00030 
00031 #define DEFAULT_RATE 0.10
00032 #define MAXCMPTS 256
00033 
00034 
00035 typedef struct {
00036     jas_image_t* image;
00037 
00038     int cmptlut[MAXCMPTS];
00039 
00040     jas_image_t* altimage;
00041 } gs_t;
00042 
00043 
00044 jas_image_t*
00045 read_image( const TQImageIO* io )
00046 {
00047     jas_stream_t* in = 0;
00048     // for QIODevice's other than TQFile, a temp. file is used.
00049     KTempFile* tempf = 0;
00050 
00051     TQFile* qf = 0;
00052     if( ( qf = dynamic_cast<TQFile*>( io->ioDevice() ) ) ) {
00053         // great, it's a TQFile. Let's just take the filename.
00054         in = jas_stream_fopen( TQFile::encodeName( qf->name() ), "rb" );
00055     } else {
00056         // not a TQFile. Copy the whole data to a temp. file.
00057         tempf = new KTempFile();
00058         if( tempf->status() != 0 ) {
00059             delete tempf;
00060             return 0;
00061         } // if
00062         tempf->setAutoDelete( true );
00063         TQFile* out = tempf->file();
00064         // 4096 (=4k) is a common page size.
00065         TQByteArray b( 4096 );
00066         TQ_LONG size;
00067         // 0 or -1 is EOF / error
00068         while( ( size = io->ioDevice()->readBlock( b.data(), 4096 ) ) > 0 ) {
00069             // in case of a write error, still give the decoder a try
00070             if( ( out->writeBlock( b.data(), size ) ) == -1 ) break;
00071         } // while
00072         // flush everything out to disk
00073         out->flush();
00074 
00075         in = jas_stream_fopen( TQFile::encodeName( tempf->name() ), "rb" );
00076     } // else
00077     if( !in ) {
00078         delete tempf;
00079         return 0;
00080     } // if
00081 
00082     jas_image_t* image = jas_image_decode( in, -1, 0 );
00083     jas_stream_close( in );
00084     delete tempf;
00085 
00086     // image may be 0, but that's Ok
00087     return image;
00088 } // read_image
00089 
00090 static bool
00091 convert_colorspace( gs_t& gs )
00092 {
00093     jas_cmprof_t *outprof = jas_cmprof_createfromclrspc( JAS_CLRSPC_SRGB );
00094     if( !outprof ) return false;
00095 
00096     gs.altimage = jas_image_chclrspc( gs.image, outprof,
00097                                       JAS_CMXFORM_INTENT_PER );
00098     if( !gs.altimage ) return false;
00099 
00100     return true;
00101 } // convert_colorspace
00102 
00103 static bool
00104 render_view( gs_t& gs, TQImage& qti )
00105 {
00106     if((gs.cmptlut[0] = jas_image_getcmptbytype(gs.altimage,
00107                                                 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R))) < 0 ||
00108        (gs.cmptlut[1] = jas_image_getcmptbytype(gs.altimage,
00109                                                 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G))) < 0 ||
00110        (gs.cmptlut[2] = jas_image_getcmptbytype(gs.altimage,
00111                                                 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B))) < 0) {
00112         return false;
00113     } // if
00114 
00115     const int* cmptlut = gs.cmptlut;
00116     int v[3];
00117 
00118     // check that all components have the same size.
00119     const int width = jas_image_cmptwidth( gs.altimage, cmptlut[0] );
00120     const int height = jas_image_cmptheight( gs.altimage, cmptlut[0] );
00121     for( int i = 1; i < 3; ++i ) {
00122         if (jas_image_cmptwidth( gs.altimage, cmptlut[i] ) != width ||
00123             jas_image_cmptheight( gs.altimage, cmptlut[i] ) != height)
00124             return false;
00125     } // for
00126 
00127     if( !qti.create( jas_image_width( gs.altimage ),
00128                      jas_image_height( gs.altimage ), 32 ) )
00129         return false;
00130 
00131     uint32_t* data = (uint32_t*)qti.bits();
00132 
00133     for( int y = 0; y < height; ++y ) {
00134         for( int x = 0; x < width; ++x ) {
00135             for( int k = 0; k < 3; ++k ) {
00136                 v[k] = jas_image_readcmptsample( gs.altimage, cmptlut[k], x, y );
00137                 // if the precision of the component is too small, increase
00138                 // it to use the complete value range.
00139                 v[k] <<= 8 - jas_image_cmptprec( gs.altimage, cmptlut[k] );
00140 
00141                 if( v[k] < 0 ) v[k] = 0;
00142                 else if( v[k] > 255 ) v[k] = 255;
00143             } // for k
00144 
00145             *data++ = tqRgb( v[0], v[1], v[2] );
00146         } // for x
00147     } // for y
00148     return true;
00149 } // render_view
00150 
00151 
00152 KDE_EXPORT void
00153 kimgio_jp2_read( TQImageIO* io )
00154 {
00155     if( jas_init() ) return;
00156 
00157     gs_t gs;
00158     if( !(gs.image = read_image( io )) ) return;
00159 
00160     if( !convert_colorspace( gs ) ) return;
00161 
00162     TQImage image;
00163     render_view( gs, image );
00164 
00165     if( gs.image ) jas_image_destroy( gs.image );
00166     if( gs.altimage ) jas_image_destroy( gs.altimage );
00167 
00168     io->setImage( image );
00169     io->setStatus( 0 );
00170 } // kimgio_jp2_read
00171 
00172 
00173 static jas_image_t*
00174 create_image( const TQImage& qi )
00175 {
00176     // prepare the component parameters
00177     jas_image_cmptparm_t* cmptparms = new jas_image_cmptparm_t[ 3 ];
00178 
00179     for ( int i = 0; i < 3; ++i ) {
00180         // x and y offset
00181         cmptparms[i].tlx = 0;
00182         cmptparms[i].tly = 0;
00183 
00184         // the resulting image will be hstep*width x vstep*height !
00185         cmptparms[i].hstep = 1;
00186         cmptparms[i].vstep = 1;
00187         cmptparms[i].width = qi.width();
00188         cmptparms[i].height = qi.height();
00189 
00190         // we write everything as 24bit truecolor ATM
00191         cmptparms[i].prec = 8;
00192         cmptparms[i].sgnd = false;
00193     }
00194 
00195     jas_image_t* ji = jas_image_create( 3 /* number components */, cmptparms, JAS_CLRSPC_UNKNOWN );
00196     delete[] cmptparms;
00197 
00198     // returning 0 is ok
00199     return ji;
00200 } // create_image
00201 
00202 
00203 static bool
00204 write_components( jas_image_t* ji, const TQImage& qi )
00205 {
00206     const unsigned height = qi.height();
00207     const unsigned width = qi.width();
00208 
00209     jas_matrix_t* m = jas_matrix_create( height, width );
00210     if( !m ) return false;
00211 
00212     jas_image_setclrspc( ji, JAS_CLRSPC_SRGB );
00213 
00214     jas_image_setcmpttype( ji, 0, JAS_IMAGE_CT_RGB_R );
00215     for( uint y = 0; y < height; ++y )
00216         for( uint x = 0; x < width; ++x )
00217             jas_matrix_set( m, y, x, tqRed( qi.pixel( x, y ) ) );
00218     jas_image_writecmpt( ji, 0, 0, 0, width, height, m );
00219 
00220     jas_image_setcmpttype( ji, 1, JAS_IMAGE_CT_RGB_G );
00221     for( uint y = 0; y < height; ++y )
00222         for( uint x = 0; x < width; ++x )
00223             jas_matrix_set( m, y, x, tqGreen( qi.pixel( x, y ) ) );
00224     jas_image_writecmpt( ji, 1, 0, 0, width, height, m );
00225 
00226     jas_image_setcmpttype( ji, 2, JAS_IMAGE_CT_RGB_B );
00227     for( uint y = 0; y < height; ++y )
00228         for( uint x = 0; x < width; ++x )
00229             jas_matrix_set( m, y, x, tqBlue( qi.pixel( x, y ) ) );
00230     jas_image_writecmpt( ji, 2, 0, 0, width, height, m );
00231     jas_matrix_destroy( m );
00232 
00233     return true;
00234 } // write_components
00235 
00236 KDE_EXPORT void
00237 kimgio_jp2_write( TQImageIO* io )
00238 {
00239     if( jas_init() ) return;
00240 
00241     // open the stream. we write directly to the file if possible, to a
00242     // temporary file otherwise.
00243     jas_stream_t* stream = 0;
00244 
00245     TQFile* qf = 0;
00246     KTempFile* ktempf = 0;
00247     if( ( qf = dynamic_cast<TQFile*>( io->ioDevice() ) ) ) {
00248         // jas_stream_fdopen works here, but not when reading...
00249         stream = jas_stream_fdopen( dup( qf->handle() ), "w" );
00250     } else {
00251         ktempf = new KTempFile;
00252         ktempf->setAutoDelete( true );
00253         stream = jas_stream_fdopen( dup( ktempf->handle()), "w" );
00254     } // else
00255 
00256 
00257     // by here, a jas_stream_t is open
00258     if( !stream ) return;
00259 
00260     jas_image_t* ji = create_image( io->image() );
00261     if( !ji ) {
00262         delete ktempf;
00263         jas_stream_close( stream );
00264         return;
00265     } // if
00266 
00267     if( !write_components( ji, io->image() ) ) {
00268         delete ktempf;
00269         jas_stream_close( stream );
00270         jas_image_destroy( ji );
00271         return;
00272     } // if
00273 
00274     // optstr:
00275     // - rate=#B => the resulting file size is about # bytes
00276     // - rate=0.0 .. 1.0 => the resulting file size is about the factor times
00277     //                      the uncompressed size
00278     TQString rate;
00279     TQTextStream ts( &rate, IO_WriteOnly );
00280     ts << "rate="
00281         << ( (io->quality() < 0) ? DEFAULT_RATE : io->quality() / 100.0F );
00282     int i = jp2_encode( ji, stream, rate.utf8().data() );
00283 
00284     jas_image_destroy( ji );
00285     jas_stream_close( stream );
00286 
00287     if( i != 0 ) { delete ktempf; return; }
00288 
00289     if( ktempf ) {
00290         // We've written to a tempfile. Copy the data to the final destination.
00291         TQFile* in = ktempf->file();
00292 
00293         TQByteArray b( 4096 );
00294         TQ_LONG size;
00295 
00296         // seek to the beginning of the file.
00297         if( !in->at( 0 ) ) { delete ktempf; return; }
00298 
00299         // 0 or -1 is EOF / error
00300         while( ( size = in->readBlock( b.data(), 4096 ) ) > 0 ) {
00301             if( ( io->ioDevice()->writeBlock( b.data(), size ) ) == -1 ) {
00302                 delete ktempf;
00303                 return;
00304             } // if
00305         } // while
00306         io->ioDevice()->flush();
00307         delete ktempf;
00308 
00309         // see if we've left the while loop due to an error.
00310         if( size == -1 ) return;
00311     } // if
00312 
00313 
00314     // everything went fine
00315     io->setStatus( IO_Ok );
00316 } // kimgio_jp2_write
00317 
00318 #endif // HAVE_JASPER
00319 

kimgio

Skip menu "kimgio"
  • Main Page
  • File List
  • Related Pages

kimgio

Skip menu "kimgio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kimgio by doxygen 1.7.1
This website is maintained by Timothy Pearson.