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

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

pnm.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
33 #ifndef __INCLUDE_MIST_PNM__
34 #define __INCLUDE_MIST_PNM__
35
36
37 #ifndef __INCLUDE_MIST_H__
38 #include "../mist.h"
39 #endif
40
41 // カラー画像の設定を読み込む
42 #ifndef __INCLUDE_MIST_COLOR_H__
43 #include "../config/color.h"
44 #endif
45
46
47 #include <iostream>
48 #include <string>
49 #include <vector>
50
51
52 // mist名前空間の始まり
53 _MIST_BEGIN
54
55
56 namespace __pnm_controller__
57 {
58 enum PNM_TYPE
59 {
60 UNKNOWN = 0,
61 P1,
62 P2,
63 P3,
64 P4,
65 P5,
66 P6
67 };
68
69 template < bool b >
70 struct _gray_converter_
71 {
72 template < class T >
73 static T get_value( const T &v ){ return( v ); }
74 };
75
76 template < >
77 struct _gray_converter_< true >
78 {
79 template < class T >
80 static typename T::value_type get_value( const T &v ){ return( v.get_value( ) ); }
81 };
82
83 template < class T, class Allocator >
84 struct pnm_controller
85 {
86 typedef typename array2< T, Allocator >::size_type size_type;
87 typedef _pixel_converter_< T > pixel_converter;
88 typedef _gray_converter_< is_color< T >::value > gray_converter;
89 typedef typename pixel_converter::color_type color_type;
90 typedef typename pixel_converter::value_type value_type;
91
92 static PNM_TYPE pnm_format( const std::string &str )
93 {
94 if( str == "P1" )
95 {
96 return( P1 );
97 }
98 else if( str == "P2" )
99 {
100 return( P2 );
101 }
102 else if( str == "P3" )
103 {
104 return( P3 );
105 }
106 else if( str == "P4" )
107 {
108 return( P4 );
109 }
110 else if( str == "P5" )
111 {
112 return( P5 );
113 }
114 else if( str == "P6" )
115 {
116 return( P6 );
117 }
118 else
119 {
120 return( UNKNOWN );
121 }
122 }
123
124 static const unsigned char *get_line( const unsigned char *s, const unsigned char *e, std::string &line )
125 {
126 line = "";
127 while( s < e )
128 {
129 if( s[ 0 ] == '\r' )
130 {
131 if( s + 1 != e && s[ 1 ] == '\n' )
132 {
133 s = s + 2;
134 }
135 else
136 {
137 s++;
138 }
139 break;
140 }
141 else if( s[ 0 ] == '\n' )
142 {
143 s = s + 1;
144 break;
145 }
146 line += *s;
147 s++;
148 }
149 return( s > e ? e : s );
150 }
151
152 static const unsigned char *get_value( const unsigned char *s, const unsigned char *e, std::string &line, bool &flag )
153 {
154 line = "";
155 // 先頭の空白（改行やタブを含む）を飛ばす
156 while( s < e )
157 {
158 if( flag && s[ 0 ] == '#' )
159 {
160 // コメント行なのですっ飛ばす
161 while( s < e )
162 {
163 if( s[ 0 ] == '\r' )
164 {
165 if( s + 1 != e && s[ 1 ] == '\n' )
166 {
167 s = s + 2;
168 }
169 else
170 {
171 s++;
172 }
173 break;
174 }
175 else if( s[ 0 ] == '\n' )
176 {
177 s++;
178 break;
179 }
180 s++;
181 }
182 }
183 else if( s[ 0 ] == '\r' )
184 {
185 if( s + 1 != e && s[ 1 ] == '\n' )
186 {
187 s = s + 2;
188 }
189 else
190 {
191 s = s + 1;
192 }
193 flag = true;
194 }
195 else if( s[ 0 ] == '\n' )
196 {
197 s++;
198 flag = true;
199 }
200 else if( s[ 0 ] == ' ' || s[ 0 ] == '\t' )
201 {
202 s++;
203 }
204 else
205 {
206 break;
207 }
208 }
209 // 次に空白が来る前まで進める
210 flag = false;
211 while( s < e )
212 {
213 if( s[ 0 ] == '\r' )
214 {
215 if( s + 1 != e && s[ 1 ] == '\n' )
216 {
217 s = s + 2;
218 }
219 else
220 {
221 s++;
222 }
223 flag = true;
224 break;
225 }
226 else if( s[ 0 ] == '\n' )
227 {
228 s++;
229 flag = true;
230 break;
231 }
232 else if( s[ 0 ] == ' ' || s[ 0 ] == '\t' )
233 {
234 s++;
235 break;
236 }
237 line += *s;
238 s++;
239 }
240 return( s > e ? e : s );
241 }
242
243 static size_type split_string( const std::string &line, const char ch, std::vector< std::string > &elements )
244 {
245 std::string str = "";
246 size_type i = 0;
247 elements.clear( );
248 while( i < line.size( ) )
249 {
250 for( ; i < line.size( ) && line[ i ] == ch ; i++ ){}
251
252 str = "";
253 for( ; i < line.size( ) && line[ i ] != ch ; i++ )
254 {
255 str += line[ i ];
256 }
257
258 if( str != "" )
259 {
260 elements.push_back( str );
261 }
262 }
263 return( elements.size( ) );
264 }
265
266 static bool is_number( const std::string &line )
267 {
268 for( size_t i = 0 ; i < line.size( ) ; i++ )
269 {
270 if( line[ i ] < '0' || '9' < line[ i ] )
271 {
272 return( false );
273 }
274 }
275 return( true );
276 }
277
278 static bool convert_from_pnm_data( array2< T, Allocator > &image, const unsigned char *buff, size_type len, typename array2< T, Allocator >::size_type level )
279 {
280 // PNM形式のヘッダ部分
281 const unsigned char *p = buff;
282 const unsigned char *e = buff + len;
283 std::string line = "";
284 std::vector< std::string > elements;
285
286 bool flag = true;
287 p = get_value( p, e, line, flag );
288 PNM_TYPE pnm_type = pnm_format( line );
289 if( pnm_type == UNKNOWN )
290 {
291 // 未サポートのビットマップ
292 std::cerr << "This format is not supported currently!" << std::endl;
293 return( false );
294 }
295
296 // 画像サイズを取得する
297 size_type w = 0, h = 0, gray_level = level;
298 p = get_value( p, e, line, flag );
299 if( is_number( line ) )
300 {
301 w = atoi( line.c_str( ) );
302 }
303 else
304 {
305 // 未サポートのビットマップ
306 std::cerr << "Image size is unknown!" << std::endl;
307 }
308
309 p = get_value( p, e, line, flag );
310 if( is_number( line ) )
311 {
312 h = atoi( line.c_str( ) );
313 }
314 else
315 {
316 // 未サポートのビットマップ
317 std::cerr << "Image size is unknown!" << std::endl;
318 }
319
320 image.resize( w, h );
321
322 // 濃淡のレベル数を取得する
323 switch( pnm_type )
324 {
325 case P2:
326 case P3:
327 case P5:
328 case P6:
329 p = get_value( p, e, line, flag );
330 if( !is_number( line ) )
331 {
332 // 未サポートのビットマップ
333 std::cerr << "Image size is unknown!" << std::endl;
334 return( false );
335 }
336 gray_level = atoi( line.c_str( ) );
337 break;
338
339 default:
340 break;
341 }
342
343 // 画素データを取得する
344 size_type i = 0;
345 double scale = static_cast< double >( level ) / static_cast< double >( gray_level );
346 switch( pnm_type )
347 {
348 case P1:
349 case P2:
350 while( i < image.size( ) && p < e )
351 {
352 p = get_line( p, e, line );
353 split_string( line, ' ', elements );
354 for( size_type j = 0 ; i < image.size( ) && j < elements.size( ) ; j++ )
355 {
356 image[ i++ ] = static_cast< value_type >( atoi( elements[ j ].c_str( ) ) * scale );
357 }
358 }
359 break;
360
361 case P3:
362 while( i < image.size( ) && p < e )
363 {
364 p = get_line( p, e, line );
365 split_string( line, ' ', elements );
366 for( size_type j = 0 ; i < image.size( ) && j < elements.size( ) ; j += 3 )
367 {
368 value_type r = static_cast< value_type >( atoi( elements[ j + 0 ].c_str( ) ) * scale );
369 value_type g = static_cast< value_type >( atoi( elements[ j + 1 ].c_str( ) ) * scale );
370 value_type b = static_cast< value_type >( atoi( elements[ j + 2 ].c_str( ) ) * scale );
371 image[ i++ ] = pixel_converter::convert_to( r, g, b );
372 }
373 }
374 break;
375
376 case P4:
377 case P5:
378 while( i < image.size( ) && p < e )
379 {
380 image[ i++ ] = static_cast< value_type >( *p++ * scale );
381 }
382 break;
383
384 case P6:
385 while( i < image.size( ) && p < e )
386 {
387 value_type r = static_cast< value_type >( p[ 0 ] * scale );
388 value_type g = static_cast< value_type >( p[ 1 ] * scale );
389 value_type b = static_cast< value_type >( p[ 2 ] * scale );
390 image[ i++ ] = pixel_converter::convert_to( r, g, b );
391 p += 3;
392 }
393 break;
394
395 default:
396 return( false );
397 }
398
399 return( p == e );
400 }
401
402 static bool read( array2< T, Allocator > &image, const std::string &filename, typename array2< T, Allocator >::size_type level )
403 {
404 typedef typename array2< T, Allocator >::size_type size_type;
405
406 size_type filesize;
407 FILE *fp;
408 if( ( fp = fopen( filename.c_str( ), "rb" ) ) == NULL ) return( false );
409 // ファイルサイズを取得
410 fseek( fp, 0, SEEK_END );
411 filesize = ftell( fp );
412 fseek( fp, 0, SEEK_SET );
413
414 unsigned char *buff = new unsigned char[ filesize + 1 ];
415 unsigned char *pointer = buff;
416 size_type read_size = 0;
417 while( feof( fp ) == 0 )
418 {
419 read_size = fread( pointer, sizeof( unsigned char ), 1024, fp );
420 if( read_size < 1024 )
421 {
422 break;
423 }
424 pointer += read_size;
425 }
426 fclose( fp );
427
428 bool ret = convert_from_pnm_data( image, buff, filesize, level );
429 delete [] buff;
430 return( ret );
431 }
432
433 static bool write( const array2< T, Allocator > &image, const std::string &filename, PNM_TYPE pnm_type, typename array2< T, Allocator >::size_type level )
434 {
435 typedef typename array2< T, Allocator >::size_type size_type;
436
437 if( image.width( ) == 0 )
438 {
439 std::cerr << "Image width is zero!" << std::endl;
440 return( false );
441 }
442 else if( image.height( ) == 0 )
443 {
444 std::cerr << "Image height is zero!" << std::endl;
445 return( false );
446 }
447 else if( pnm_type == UNKNOWN )
448 {
449 std::cerr << "This format is not supported currently!" << std::endl;
450 return( false );
451 }
452
453 FILE *fp;
454 if( ( fp = fopen( filename.c_str( ), "wb" ) ) == NULL )
455 {
456 return( false );
457 }
458
459 // ヘッダ情報を書き込む
460 fprintf( fp, "P%1d\n", pnm_type );
461 fprintf( fp, "# Created by MIST\n" );
462 fprintf( fp, "%d %d\n", static_cast< int >( image.width( ) ), static_cast< int >( image.height( ) ) );
463
464 size_type i, j;
465
466 switch( pnm_type )
467 {
468 case P2:
469 case P3:
470 case P5:
471 case P6:
472 {
473 typename array2< T, Allocator >::value_type max = image[ 0 ];
474 for( i = 1 ; i < image.size( ) ; i++ )
475 {
476 max = max > image[ i ] ? max : image[ i ];
477 }
478 int max_level = static_cast< int >( gray_converter::get_value( max ) );
479 max_level = max_level > static_cast< int >( level ) ? max_level : static_cast< int >( level );
480 fprintf( fp, "%d\n", max_level );
481 }
482 break;
483
484 default:
485 break;
486 }
487
488
489 // 画素データを書き出し
490 switch( pnm_type )
491 {
492 case P1:
493 case P2:
494 for( j = 0 ; j < image.height( ) ; j++ )
495 {
496 for( i = 0 ; i < image.width( ) ; i++ )
497 {
498 fprintf( fp, "%d ", static_cast< int >( gray_converter::get_value( image( i, j ) ) ) );
499 }
500 fputc( '\n', fp );
501 }
502 break;
503
504 case P3:
505 for( j = 0 ; j < image.height( ) ; j++ )
506 {
507 for( i = 0 ; i < image.width( ) ; i++ )
508 {
509 color_type c = pixel_converter::convert_from( image( i, j ) );
510 fprintf( fp, "%d ", static_cast< int >( c.r ) );
511 fprintf( fp, "%d ", static_cast< int >( c.g ) );
512 fprintf( fp, "%d ", static_cast< int >( c.b ) );
513 }
514 fputc( '\n', fp );
515 }
516 break;
517
518 case P4:
519 case P5:
520 for( j = 0 ; j < image.height( ) ; j++ )
521 {
522 for( i = 0 ; i < image.width( ) ; i++ )
523 {
524 fprintf( fp, "%c", static_cast< unsigned char >( gray_converter::get_value( image( i, j ) ) ) );
525 }
526 }
527 break;
528
529 case P6:
530 for( j = 0 ; j < image.height( ) ; j++ )
531 {
532 for( i = 0 ; i < image.width( ) ; i++ )
533 {
534 color_type c = pixel_converter::convert_from( image( i, j ) );
535 fprintf( fp, "%c", static_cast< unsigned char >( c.r ) );
536 fprintf( fp, "%c", static_cast< unsigned char >( c.g ) );
537 fprintf( fp, "%c", static_cast< unsigned char >( c.b ) );
538 }
539 }
540 break;
541
542 default:
543 fclose( fp );
544 return( false );
545 }
546
547 fclose( fp );
548
549 return( true );
550 }
551 };
552 }
553
554
557
570
571
583 template < class T, class Allocator >
584 bool read_pnm( array2< T, Allocator > &image, const std::string &filename, typename array2< T, Allocator >::size_type level = 255 )
585 {
586 return( __pnm_controller__::pnm_controller< T, Allocator >::read( image, filename, level ) );
587 }
588
589
601 template < class T, class Allocator >
602 bool read_pnm( array2< T, Allocator > &image, const std::wstring &filename, typename array2< T, Allocator >::size_type level = 255 )
603 {
604 return( read_pnm( image, wstr2str( filename ), level ) );
605 }
606
607
629 template < class T, class Allocator >
630 bool write_pnm( const array2< T, Allocator > &image, const std::string &filename, typename array2< T, Allocator >::size_type pnm_type = 6, typename array2< T, Allocator >::size_type level = 255 )
631 {
632 if( pnm_type > 6 )
633 {
634 std::cerr << "This format is not supported currently!" << std::endl;
635 return( false );
636 }
637 return( __pnm_controller__::pnm_controller< T, Allocator >::write( image, filename, static_cast< __pnm_controller__::PNM_TYPE >( pnm_type ), level ) );
638 }
639
640
662 template < class T, class Allocator >
663 bool write_pnm( const array2< T, Allocator > &image, const std::wstring &filename, typename array2< T, Allocator >::size_type pnm_type = 6, typename array2< T, Allocator >::size_type level = 255 )
664 {
665 return( write_pnm( image, wstr2str( filename ), static_cast< __pnm_controller__::PNM_TYPE >( pnm_type ), level ) );
666 }
667
668
670 // PNM画像入出力グループの終わり
671
673 // 画像入出力グループの終わり
674
675
676 // mist名前空間の終わり
677 _MIST_END
678
679
680 #endif // __INCLUDE_MIST_PNM__
681