• 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 
35 typedef struct {
36  jas_image_t* image;
37 
38  int cmptlut[MAXCMPTS];
39 
40  jas_image_t* altimage;
41 } gs_t;
42 
43 
44 jas_image_t*
45 read_image( const TQImageIO* io )
46 {
47  jas_stream_t* in = 0;
48  // for QIODevice'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 
90 static bool
91 convert_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 
103 static bool
104 render_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 
152 KDE_EXPORT void
153 kimgio_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 
173 static jas_image_t*
174 create_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 
203 static bool
204 write_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 
236 KDE_EXPORT void
237 kimgio_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  int i = jp2_encode( ji, stream, rate.utf8().data() );
283 
284  jas_image_destroy( ji );
285  jas_stream_close( stream );
286 
287  if( i != 0 ) { delete ktempf; return; }
288 
289  if( ktempf ) {
290  // We've written to a tempfile. Copy the data to the final destination.
291  TQFile* in = ktempf->file();
292 
293  TQByteArray b( 4096 );
294  TQ_LONG size;
295 
296  // seek to the beginning of the file.
297  if( !in->at( 0 ) ) { delete ktempf; return; }
298 
299  // 0 or -1 is EOF / error
300  while( ( size = in->readBlock( b.data(), 4096 ) ) > 0 ) {
301  if( ( io->ioDevice()->writeBlock( b.data(), size ) ) == -1 ) {
302  delete ktempf;
303  return;
304  } // if
305  } // while
306  io->ioDevice()->flush();
307  delete ktempf;
308 
309  // see if we've left the while loop due to an error.
310  if( size == -1 ) return;
311  } // if
312 
313 
314  // everything went fine
315  io->setStatus( IO_Ok );
316 } // kimgio_jp2_write
317 
318 #endif // HAVE_JASPER
319 

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kimgio by doxygen 1.8.8
This website is maintained by Timothy Pearson.