- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

jpeg2000.h
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28
36 #ifndef __INCLUDE_MIST_JPEG2000__
37 #define __INCLUDE_MIST_JPEG2000__
38
39
40 #ifndef __INCLUDE_MIST_H__
41 #include "../mist.h"
42 #endif
43
44 // カラー画像の設定を読み込む
45 #ifndef __INCLUDE_MIST_COLOR_H__
46 #include "../config/color.h"
47 #endif
48
49 #ifndef __INCLUDE_MIST_LIMITS__
50 #include "../limits.h"
51 #endif
52
53
54 #include <iostream>
55 #include <string>
56
57 extern "C"
58 {
59 #ifndef OPJ_STATIC
60 #define OPJ_STATIC
61 #endif
62
63 #include <openjpeg.h>
64 }
65
66
67 // mist名前空間の始まり
68 _MIST_BEGIN
69
70
71 namespace __jpeg2000_controller__
72 {
73 template < bool b >
74 struct _create_opj_image_
75 {
76 // グレースケールの画像を作成する
77 template < class T, class Allocator >
78 static opj_image_t *create( const array2< T, Allocator > &image, const opj_cparameters_t &param )
79 {
80 opj_image_cmptparm_t cmptparm[ 1 ];
81
82 memset( cmptparm, 0, 1 * sizeof( opj_image_cmptparm_t ) );
83
84 // 各色プレーンの設定を行う
85 for( size_t i = 0 ; i < 1 ; i++ )
86 {
87 cmptparm[ i ].prec = 8;
88 cmptparm[ i ].bpp = 8;
89 cmptparm[ i ].sgnd = 0;
90 cmptparm[ i ].dx = param.subsampling_dx;
91 cmptparm[ i ].dy = param.subsampling_dy;
92 cmptparm[ i ].w = static_cast< int >( image.width( ) );
93 cmptparm[ i ].h = static_cast< int >( image.height( ) );
94 }
95
96 // カラー画像として作成する
97 opj_image_t *img = opj_image_create( 1, cmptparm, CLRSPC_GRAY );
98
99 // 画像のオフセットとレンダリンググリッドを設定する
100 img->x0 = param.image_offset_x0;
101 img->y0 = param.image_offset_y0;
102 img->x1 = img->x0 + ( static_cast< int >( image.width( ) ) - 1 ) * param.subsampling_dx + 1;
103 img->y1 = img->y0 + ( static_cast< int >( image.height( ) ) - 1 ) * param.subsampling_dy + 1;
104
105 // 画像データをコピーする
106 for( size_t i = 0 ; i < image.size( ) ; i++ )
107 {
108 img->comps[ 0 ].data[ i ] = static_cast< int >( image[ i ] );
109 }
110
111 return( img );
112 }
113 };
114
115 template < >
116 struct _create_opj_image_< true >
117 {
118 // カラー画像を作成する
119 template < class T, class Allocator >
120 static opj_image_t *create( const array2< T, Allocator > &image, const opj_cparameters_t &param )
121 {
122 opj_image_cmptparm_t cmptparm[ 3 ];
123
124 memset( cmptparm, 0, 3 * sizeof( opj_image_cmptparm_t ) );
125
126 // 各色プレーンの設定を行う
127 for( size_t i = 0 ; i < 3 ; i++ )
128 {
129 cmptparm[ i ].prec = 8;
130 cmptparm[ i ].bpp = 8;
131 cmptparm[ i ].sgnd = 0;
132 cmptparm[ i ].dx = param.subsampling_dx;
133 cmptparm[ i ].dy = param.subsampling_dy;
134 cmptparm[ i ].w = static_cast< int >( image.width( ) );
135 cmptparm[ i ].h = static_cast< int >( image.height( ) );
136 }
137
138 // カラー画像として作成する
139 opj_image_t *img = opj_image_create( 3, cmptparm, CLRSPC_SRGB );
140
141 // 画像のオフセットとレンダリンググリッドを設定する
142 img->x0 = param.image_offset_x0;
143 img->y0 = param.image_offset_y0;
144 img->x1 = img->x0 + ( static_cast< int >( image.width( ) ) - 1 ) * param.subsampling_dx + 1;
145 img->y1 = img->y0 + ( static_cast< int >( image.height( ) ) - 1 ) * param.subsampling_dy + 1;
146
147 // 画像データをコピーする
148 for( size_t i = 0 ; i < image.size( ) ; i++ )
149 {
150 img->comps[ 0 ].data[ i ] = static_cast< int >( image[ i ].r );
151 img->comps[ 1 ].data[ i ] = static_cast< int >( image[ i ].g );
152 img->comps[ 2 ].data[ i ] = static_cast< int >( image[ i ].b );
153 }
154
155 return( img );
156 }
157 };
158
159 inline std::string to_lower_case( const std::string &str )
160 {
161 std::string s = "";
162 for( std::string::size_type i = 0 ; i < str.size( ) ; i++ )
163 {
164 s += static_cast< char >( tolower( str[ i ] ) );
165 }
166 return( s );
167 }
168
169 inline std::string get_ext( const std::string &str )
170 {
171 std::string::size_type index = str.rfind( '.' );
172 if( index == str.npos )
173 {
174 return( "" );
175 }
176 return( str.substr( index ) );
177 }
178
179 template < class T, class Allocator >
180 struct jpeg2000_controller
181 {
182 typedef _pixel_converter_< T > pixel_converter;
183 typedef typename pixel_converter::color_type color_type;
184
185 static bool read( array2< T, Allocator > &image, const std::string &filename )
186 {
187 typedef typename array2< T, Allocator >::size_type size_type;
188 typedef typename array2< T, Allocator >::difference_type difference_type;
189
190 // ファイルからデータをすべて読み込む
191 FILE *fp = fopen( filename.c_str( ), "rb" );
192 if( fp == NULL )
193 {
194 std::cerr << "Can't open file " << filename << std::endl;
195 return( false );
196 }
197
198 // ファイルサイズを取得
199 fseek( fp, 0, SEEK_END );
200 size_type filesize = ftell( fp );
201 fseek( fp, 0, SEEK_SET );
202
203 // データを少しずつ読み込む
204 unsigned char *buff = new unsigned char[ filesize + 1 ];
205 unsigned char *pointer = buff;
206 size_type read_size = 0;
207 while( feof( fp ) == 0 )
208 {
209 read_size = fread( pointer, sizeof( unsigned char ), 1024, fp );
210 if( read_size < 1024 )
211 {
212 break;
213 }
214 pointer += read_size;
215 }
216
217 // ファイルを閉じる
218 fclose( fp );
219
220 // デコーダを決定する
221 std::string ext = to_lower_case( get_ext( filename ) );
222 OPJ_CODEC_FORMAT codec;
223 if( ext == ".jp2" )
224 {
225 codec = CODEC_JP2;
226 }
227 else if( ext == ".j2k" || ext == ".j2c" )
228 {
229 codec = CODEC_J2K;
230 }
231 else if( ext == ".jpt" )
232 {
233 codec = CODEC_JPT;
234 }
235
236 // OpenJPEGライブラリの圧縮パラメータ
237 opj_dparameters_t param;
238
239 // デコードパラメータをデフォルトに設定する
240 opj_set_default_decoder_parameters( &param );
241
242 // デコーダエンジンを初期化する
243 //opj_dinfo_t *dinfo = opj_create_decompress( CODEC_UNKNOWN );
244 opj_dinfo_t *dinfo = opj_create_decompress( codec );
245
246 // エラーハンドリングの関数を設定する
247 opj_event_mgr_t event_mgr;
248 memset( &event_mgr, 0, sizeof( opj_event_mgr_t ) );
249 //event_mgr.error_handler = error;
250 //event_mgr.warning_handler = warning;
251 //event_mgr.info_handler = info;
252 opj_set_event_mgr( (opj_common_ptr)dinfo, &event_mgr, stderr );
253
254 // デコーダにパラメータを設定する
255 opj_setup_decoder( dinfo, &param );
256
257 // デコード用のメモリストリームを準備する
258 opj_cio_t *cio = opj_cio_open( ( opj_common_ptr )dinfo, buff, static_cast< int >( filesize ) );
259
260 // 画像をデコードする
261 opj_image_t *img = opj_decode( dinfo, cio );
262 if( img == NULL )
263 {
264 std::cerr << "Failed to read JPEG2000 image from " << filename << std::endl;
265
266 opj_destroy_decompress( dinfo );
267 opj_cio_close( cio );
268
269 delete [] buff;
270
271 return( false );
272 }
273 else
274 {
275 delete [] buff;
276 }
277
278 if( img->numcomps != 1 && img->numcomps != 3 )
279 {
280 // おかしな画像が読み込まれた？
281 opj_destroy_decompress( dinfo );
282 opj_cio_close( cio );
283
284 std::cerr << "Invalid image is loaded." << std::endl;
285
286 return( false );
287 }
288
289 // OpenJPEG ライブラリの画像形式からMISTの形式に変換する
290 image.resize( img->comps[ 0 ].w, img->comps[ 0 ].h );
291
292 if( img->numcomps == 1 )
293 {
294 for( size_type i = 0 ; i < image.size( ) ; i++ )
295 {
296 int pix = img->comps[ 0 ].data[ i ];
297 image[ i ] = pixel_converter::convert_to( pix, pix, pix );
298 }
299 }
300 else // img->numcomps == 3
301 {
302 for( size_type i = 0 ; i < image.size( ) ; i++ )
303 {
304 image[ i ] = pixel_converter::convert_to( img->comps[ 0 ].data[ i ], img->comps[ 1 ].data[ i ], img->comps[ 2 ].data[ i ] );
305 }
306 }
307
308
309 // OpenJPEG ライブラリで使用したリソース等を開放する
310 opj_cio_close( cio );
311 opj_destroy_decompress( dinfo );
312 opj_image_destroy( img );
313
314 return( true );
315 }
316
317 static bool write( const array2< T, Allocator > &image, const std::string &filename, double compression_level )
318 {
319 typedef typename array2< T, Allocator >::size_type size_type;
320 typedef typename array2< T, Allocator >::difference_type difference_type;
321
322 if( image.width( ) == 0 )
323 {
324 std::cerr << "Image width is zero!" << std::endl;
325 return( false );
326 }
327 else if( image.height( ) == 0 )
328 {
329 std::cerr << "Image height is zero!" << std::endl;
330 return( false );
331 }
332
333 // OpenJPEGライブラリの圧縮パラメータ
334 opj_cparameters_t param;
335
336 // エンコードパラメータをデフォルトに設定する
337 opj_set_default_encoder_parameters( &param );
338
339 // 圧縮率を設定する
340 // 0はLossless圧縮
341 param.tcp_rates[ 0 ] = static_cast< float >( compression_level );
342 param.tcp_numlayers = 1;
343 param.cp_disto_alloc = 1;
344
345 // コメントを埋め込む
346 static char comment[] = "Created by MIST with OpenJPEG Library";
347 param.cp_comment = comment;
348
349 // OpenJPEGライブラリ内部で使用する画像形式に変換する
350 opj_image_t *img = _create_opj_image_< is_color< T >::value >::create( image, param );
351
352 // 色のコンポーネントの数を調べる
353 param.tcp_mct = img->numcomps == 3 ? 1 : 0;
354
355 // エラーハンドリングの関数を設定する
356 opj_event_mgr_t event_mgr;
357 memset( &event_mgr, 0, sizeof( opj_event_mgr_t ) );
358 //event_mgr.error_handler = error;
359 //event_mgr.warning_handler = warning;
360 //event_mgr.info_handler = info;
361
362 // JPEG2000の圧縮エンジンを初期化する
363 opj_cinfo_t * cinfo = opj_create_compress( CODEC_JP2 );
364
365 // エラー処理用の関数を設定する
366 opj_set_event_mgr( ( opj_common_ptr )cinfo, &event_mgr, stderr );
367
368 // JPEG2000 の圧縮エンジンにパラメータと画像を設定する
369 opj_setup_encoder( cinfo, &param, img );
370
371 // 画像をメモリ上に展開するためのオブジェクトを初期化する
372 opj_cio_t *cio = opj_cio_open( ( opj_common_ptr )cinfo, NULL, 0 );
373
374 // JPEG2000で画像を圧縮する
375 if( !opj_encode( cinfo, cio, img, NULL ) )
376 {
377 opj_cio_close( cio );
378 opj_destroy_compress( cinfo );
379 opj_image_destroy( img );
380
381 // 圧縮に失敗
382 return( false );
383 }
384
385 // 圧縮後のデータ長を取得する
386 difference_type codestream_length = cio_tell( cio );
387
388 // 画像出力用のファイルポインタを作成する
389 FILE *fp = fopen( filename.c_str( ), "wb" );
390
391 if( fp == NULL )
392 {
393 // 画像を作成することができなかった・・・
394 opj_cio_close( cio );
395 opj_destroy_compress( cinfo );
396 opj_image_destroy( img );
397 std::cerr << "Failed to write image to " << filename << std::endl;
398 return( false );
399 }
400
401 // 画像データをファイルに少しずつ書き出す
402 unsigned char *pointer = cio->buffer;
403 while( codestream_length > 0 )
404 {
405 size_type write_size = fwrite( pointer, sizeof( unsigned char ), codestream_length > 1024 ? 1024 : codestream_length, fp );
406 pointer += write_size;
407 codestream_length -= write_size;
408 }
409
410 // ファイルを閉じる
411 fclose( fp );
412
413 // OpenJPEG ライブラリで使用したリソース等を開放する
414 opj_cio_close( cio );
415 opj_destroy_compress( cinfo );
416 opj_image_destroy( img );
417
418 return( true );
419 }
420 };
421 }
422
423
426
438
439
450 template < class T, class Allocator >
451 bool read_jpeg2000( array2< T, Allocator > &image, const std::string &filename )
452 {
453 return( __jpeg2000_controller__::jpeg2000_controller< T, Allocator >::read( image, filename ) );
454 }
455
456
467 template < class T, class Allocator >
468 bool read_jpeg2000( array2< T, Allocator > &image, const std::wstring &filename )
469 {
470 return( read_jpeg2000( image, wstr2str( filename ) ) );
471 }
472
473
485 template < class T, class Allocator >
486 bool write_jpeg2000( const array2< T, Allocator > &image, const std::string &filename, double compression_level = 0 )
487 {
488 return( __jpeg2000_controller__::jpeg2000_controller< T, Allocator >::write( image, filename, compression_level ) );
489 }
490
491
503 template < class T, class Allocator >
504 bool write_jpeg2000( const array2< T, Allocator > &image, const std::wstring &filename, double compression_level = 0 )
505 {
506 return( write_jpeg2000( image, wstr2str( filename ), compression_level ) );
507 }
508
509
511 // JPEG2000 画像入出力グループの終わり
512
514 // 画像入出力グループの終わり
515
516
517 // mist名前空間の終わり
518 _MIST_END
519
520
521 #endif // __INCLUDE_MIST_JPEG2000__
522