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

kimgio

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

kimgio

Skip menu "kimgio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kimgio by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |