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

kimgio

  • kimgio
jp2.cpp
1// This library is distributed under the conditions of the GNU LGPL.
2#include "config.h"
3
4#ifdef HAVE_JASPER
5#include <unistd.h>
6#include "jp2.h"
7
8#if !defined(__STDC_LIMIT_MACROS)
9#define __STDC_LIMIT_MACROS
10#endif
11
12#ifdef HAVE_SYS_TYPES_H
13#include <sys/types.h>
14#endif
15#ifdef HAVE_STDINT_H
16#include <stdint.h>
17#endif
18#include <tdetempfile.h>
19#include <tqcolor.h>
20#include <tqcstring.h>
21#include <tqfile.h>
22#include <tqimage.h>
23
24// dirty, but avoids a warning because jasper.h includes jas_config.h.
25#undef PACKAGE
26#undef VERSION
27#include <jasper/jasper.h>
28
29// code taken in parts from JasPer's jiv.c
30
31#define DEFAULT_RATE 0.10
32#define MAXCMPTS 256
33
34
35typedef struct {
36 jas_image_t* image;
37
38 int cmptlut[MAXCMPTS];
39
40 jas_image_t* altimage;
41} gs_t;
42
43
44jas_image_t*
45read_image( const TQImageIO* io )
46{
47 jas_stream_t* in = 0;
48 // for TQIODevice's other than TQFile, a temp. file is used.
49 KTempFile* tempf = 0;
50
51 TQFile* qf = 0;
52 if( ( qf = dynamic_cast<TQFile*>( io->ioDevice() ) ) ) {
53 // great, it's a TQFile. Let's just take the filename.
54 in = jas_stream_fopen( TQFile::encodeName( qf->name() ), "rb" );
55 } else {
56 // not a TQFile. Copy the whole data to a temp. file.
57 tempf = new KTempFile();
58 if( tempf->status() != 0 ) {
59 delete tempf;
60 return 0;
61 } // if
62 tempf->setAutoDelete( true );
63 TQFile* out = tempf->file();
64 // 4096 (=4k) is a common page size.
65 TQByteArray b( 4096 );
66 TQ_LONG size;
67 // 0 or -1 is EOF / error
68 while( ( size = io->ioDevice()->readBlock( b.data(), 4096 ) ) > 0 ) {
69 // in case of a write error, still give the decoder a try
70 if( ( out->writeBlock( b.data(), size ) ) == -1 ) break;
71 } // while
72 // flush everything out to disk
73 out->flush();
74
75 in = jas_stream_fopen( TQFile::encodeName( tempf->name() ), "rb" );
76 } // else
77 if( !in ) {
78 delete tempf;
79 return 0;
80 } // if
81
82 jas_image_t* image = jas_image_decode( in, -1, 0 );
83 jas_stream_close( in );
84 delete tempf;
85
86 // image may be 0, but that's Ok
87 return image;
88} // read_image
89
90static bool
91convert_colorspace( gs_t& gs )
92{
93 jas_cmprof_t *outprof = jas_cmprof_createfromclrspc( JAS_CLRSPC_SRGB );
94 if( !outprof ) return false;
95
96 gs.altimage = jas_image_chclrspc( gs.image, outprof,
97 JAS_CMXFORM_INTENT_PER );
98 if( !gs.altimage ) return false;
99
100 return true;
101} // convert_colorspace
102
103static bool
104render_view( gs_t& gs, TQImage& qti )
105{
106 if((gs.cmptlut[0] = jas_image_getcmptbytype(gs.altimage,
107 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R))) < 0 ||
108 (gs.cmptlut[1] = jas_image_getcmptbytype(gs.altimage,
109 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G))) < 0 ||
110 (gs.cmptlut[2] = jas_image_getcmptbytype(gs.altimage,
111 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B))) < 0) {
112 return false;
113 } // if
114
115 const int* cmptlut = gs.cmptlut;
116 int v[3];
117
118 // check that all components have the same size.
119 const int width = jas_image_cmptwidth( gs.altimage, cmptlut[0] );
120 const int height = jas_image_cmptheight( gs.altimage, cmptlut[0] );
121 for( int i = 1; i < 3; ++i ) {
122 if (jas_image_cmptwidth( gs.altimage, cmptlut[i] ) != width ||
123 jas_image_cmptheight( gs.altimage, cmptlut[i] ) != height)
124 return false;
125 } // for
126
127 if( !qti.create( jas_image_width( gs.altimage ),
128 jas_image_height( gs.altimage ), 32 ) )
129 return false;
130
131 uint32_t* data = (uint32_t*)qti.bits();
132
133 for( int y = 0; y < height; ++y ) {
134 for( int x = 0; x < width; ++x ) {
135 for( int k = 0; k < 3; ++k ) {
136 v[k] = jas_image_readcmptsample( gs.altimage, cmptlut[k], x, y );
137 // if the precision of the component is too small, increase
138 // it to use the complete value range.
139 v[k] <<= 8 - jas_image_cmptprec( gs.altimage, cmptlut[k] );
140
141 if( v[k] < 0 ) v[k] = 0;
142 else if( v[k] > 255 ) v[k] = 255;
143 } // for k
144
145 *data++ = tqRgb( v[0], v[1], v[2] );
146 } // for x
147 } // for y
148 return true;
149} // render_view
150
151
152TDE_EXPORT void
153kimgio_jp2_read( TQImageIO* io )
154{
155 if( jas_init() ) return;
156
157 gs_t gs;
158 if( !(gs.image = read_image( io )) ) return;
159
160 if( !convert_colorspace( gs ) ) return;
161
162 TQImage image;
163 render_view( gs, image );
164
165 if( gs.image ) jas_image_destroy( gs.image );
166 if( gs.altimage ) jas_image_destroy( gs.altimage );
167
168 io->setImage( image );
169 io->setStatus( 0 );
170} // kimgio_jp2_read
171
172
173static jas_image_t*
174create_image( const TQImage& qi )
175{
176 // prepare the component parameters
177 jas_image_cmptparm_t* cmptparms = new jas_image_cmptparm_t[ 3 ];
178
179 for ( int i = 0; i < 3; ++i ) {
180 // x and y offset
181 cmptparms[i].tlx = 0;
182 cmptparms[i].tly = 0;
183
184 // the resulting image will be hstep*width x vstep*height !
185 cmptparms[i].hstep = 1;
186 cmptparms[i].vstep = 1;
187 cmptparms[i].width = qi.width();
188 cmptparms[i].height = qi.height();
189
190 // we write everything as 24bit truecolor ATM
191 cmptparms[i].prec = 8;
192 cmptparms[i].sgnd = false;
193 }
194
195 jas_image_t* ji = jas_image_create( 3 /* number components */, cmptparms, JAS_CLRSPC_UNKNOWN );
196 delete[] cmptparms;
197
198 // returning 0 is ok
199 return ji;
200} // create_image
201
202
203static bool
204write_components( jas_image_t* ji, const TQImage& qi )
205{
206 const unsigned height = qi.height();
207 const unsigned width = qi.width();
208
209 jas_matrix_t* m = jas_matrix_create( height, width );
210 if( !m ) return false;
211
212 jas_image_setclrspc( ji, JAS_CLRSPC_SRGB );
213
214 jas_image_setcmpttype( ji, 0, JAS_IMAGE_CT_RGB_R );
215 for( uint y = 0; y < height; ++y )
216 for( uint x = 0; x < width; ++x )
217 jas_matrix_set( m, y, x, tqRed( qi.pixel( x, y ) ) );
218 jas_image_writecmpt( ji, 0, 0, 0, width, height, m );
219
220 jas_image_setcmpttype( ji, 1, JAS_IMAGE_CT_RGB_G );
221 for( uint y = 0; y < height; ++y )
222 for( uint x = 0; x < width; ++x )
223 jas_matrix_set( m, y, x, tqGreen( qi.pixel( x, y ) ) );
224 jas_image_writecmpt( ji, 1, 0, 0, width, height, m );
225
226 jas_image_setcmpttype( ji, 2, JAS_IMAGE_CT_RGB_B );
227 for( uint y = 0; y < height; ++y )
228 for( uint x = 0; x < width; ++x )
229 jas_matrix_set( m, y, x, tqBlue( qi.pixel( x, y ) ) );
230 jas_image_writecmpt( ji, 2, 0, 0, width, height, m );
231 jas_matrix_destroy( m );
232
233 return true;
234} // write_components
235
236TDE_EXPORT void
237kimgio_jp2_write( TQImageIO* io )
238{
239 if( jas_init() ) return;
240
241 // open the stream. we write directly to the file if possible, to a
242 // temporary file otherwise.
243 jas_stream_t* stream = 0;
244
245 TQFile* qf = 0;
246 KTempFile* ktempf = 0;
247 if( ( qf = dynamic_cast<TQFile*>( io->ioDevice() ) ) ) {
248 // jas_stream_fdopen works here, but not when reading...
249 stream = jas_stream_fdopen( dup( qf->handle() ), "w" );
250 } else {
251 ktempf = new KTempFile;
252 ktempf->setAutoDelete( true );
253 stream = jas_stream_fdopen( dup( ktempf->handle()), "w" );
254 } // else
255
256
257 // by here, a jas_stream_t is open
258 if( !stream ) return;
259
260 jas_image_t* ji = create_image( io->image() );
261 if( !ji ) {
262 delete ktempf;
263 jas_stream_close( stream );
264 return;
265 } // if
266
267 if( !write_components( ji, io->image() ) ) {
268 delete ktempf;
269 jas_stream_close( stream );
270 jas_image_destroy( ji );
271 return;
272 } // if
273
274 // optstr:
275 // - rate=#B => the resulting file size is about # bytes
276 // - rate=0.0 .. 1.0 => the resulting file size is about the factor times
277 // the uncompressed size
278 TQString rate;
279 TQTextStream ts( &rate, IO_WriteOnly );
280 ts << "rate="
281 << ( (io->quality() < 0) ? DEFAULT_RATE : io->quality() / 100.0F );
282# if defined(JAS_VERSION_MAJOR) && (JAS_VERSION_MAJOR >= 3)
283 const jas_image_fmtinfo_t *jp2_fmtinfo = jas_image_lookupfmtbyname("jp2");
284 int i = -1;
285 if (jp2_fmtinfo)
286 {
287 i = jas_image_encode(ji, stream, jp2_fmtinfo->id, rate.utf8().data());
288 }
289# else
290 int i = jp2_encode( ji, stream, rate.utf8().data() );
291# endif
292
293 jas_image_destroy( ji );
294 jas_stream_close( stream );
295
296 if( i != 0 ) { delete ktempf; return; }
297
298 if( ktempf ) {
299 // We've written to a tempfile. Copy the data to the final destination.
300 TQFile* in = ktempf->file();
301
302 TQByteArray b( 4096 );
303 TQ_LONG size;
304
305 // seek to the beginning of the file.
306 if( !in->at( 0 ) ) { delete ktempf; return; }
307
308 // 0 or -1 is EOF / error
309 while( ( size = in->readBlock( b.data(), 4096 ) ) > 0 ) {
310 if( ( io->ioDevice()->writeBlock( b.data(), size ) ) == -1 ) {
311 delete ktempf;
312 return;
313 } // if
314 } // while
315 io->ioDevice()->flush();
316 delete ktempf;
317
318 // see if we've left the while loop due to an error.
319 if( size == -1 ) return;
320 } // if
321
322
323 // everything went fine
324 io->setStatus( IO_Ok );
325} // kimgio_jp2_write
326
327#endif // HAVE_JASPER
328

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.9.4
This website is maintained by Timothy Pearson.