00001
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
00025 #undef PACKAGE
00026 #undef VERSION
00027 #include <jasper/jasper.h>
00028
00029
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
00049 KTempFile* tempf = 0;
00050
00051 TQFile* qf = 0;
00052 if( ( qf = dynamic_cast<TQFile*>( io->ioDevice() ) ) ) {
00053
00054 in = jas_stream_fopen( TQFile::encodeName( qf->name() ), "rb" );
00055 } else {
00056
00057 tempf = new KTempFile();
00058 if( tempf->status() != 0 ) {
00059 delete tempf;
00060 return 0;
00061 }
00062 tempf->setAutoDelete( true );
00063 TQFile* out = tempf->file();
00064
00065 TQByteArray b( 4096 );
00066 TQ_LONG size;
00067
00068 while( ( size = io->ioDevice()->readBlock( b.data(), 4096 ) ) > 0 ) {
00069
00070 if( ( out->writeBlock( b.data(), size ) ) == -1 ) break;
00071 }
00072
00073 out->flush();
00074
00075 in = jas_stream_fopen( TQFile::encodeName( tempf->name() ), "rb" );
00076 }
00077 if( !in ) {
00078 delete tempf;
00079 return 0;
00080 }
00081
00082 jas_image_t* image = jas_image_decode( in, -1, 0 );
00083 jas_stream_close( in );
00084 delete tempf;
00085
00086
00087 return image;
00088 }
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 }
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 }
00114
00115 const int* cmptlut = gs.cmptlut;
00116 int v[3];
00117
00118
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 }
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
00138
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 }
00144
00145 *data++ = tqRgb( v[0], v[1], v[2] );
00146 }
00147 }
00148 return true;
00149 }
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 }
00171
00172
00173 static jas_image_t*
00174 create_image( const TQImage& qi )
00175 {
00176
00177 jas_image_cmptparm_t* cmptparms = new jas_image_cmptparm_t[ 3 ];
00178
00179 for ( int i = 0; i < 3; ++i ) {
00180
00181 cmptparms[i].tlx = 0;
00182 cmptparms[i].tly = 0;
00183
00184
00185 cmptparms[i].hstep = 1;
00186 cmptparms[i].vstep = 1;
00187 cmptparms[i].width = qi.width();
00188 cmptparms[i].height = qi.height();
00189
00190
00191 cmptparms[i].prec = 8;
00192 cmptparms[i].sgnd = false;
00193 }
00194
00195 jas_image_t* ji = jas_image_create( 3 , cmptparms, JAS_CLRSPC_UNKNOWN );
00196 delete[] cmptparms;
00197
00198
00199 return ji;
00200 }
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 }
00235
00236 KDE_EXPORT void
00237 kimgio_jp2_write( TQImageIO* io )
00238 {
00239 if( jas_init() ) return;
00240
00241
00242
00243 jas_stream_t* stream = 0;
00244
00245 TQFile* qf = 0;
00246 KTempFile* ktempf = 0;
00247 if( ( qf = dynamic_cast<TQFile*>( io->ioDevice() ) ) ) {
00248
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 }
00255
00256
00257
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 }
00266
00267 if( !write_components( ji, io->image() ) ) {
00268 delete ktempf;
00269 jas_stream_close( stream );
00270 jas_image_destroy( ji );
00271 return;
00272 }
00273
00274
00275
00276
00277
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
00291 TQFile* in = ktempf->file();
00292
00293 TQByteArray b( 4096 );
00294 TQ_LONG size;
00295
00296
00297 if( !in->at( 0 ) ) { delete ktempf; return; }
00298
00299
00300 while( ( size = in->readBlock( b.data(), 4096 ) ) > 0 ) {
00301 if( ( io->ioDevice()->writeBlock( b.data(), size ) ) == -1 ) {
00302 delete ktempf;
00303 return;
00304 }
00305 }
00306 io->ioDevice()->flush();
00307 delete ktempf;
00308
00309
00310 if( size == -1 ) return;
00311 }
00312
00313
00314
00315 io->setStatus( IO_Ok );
00316 }
00317
00318 #endif // HAVE_JASPER
00319