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名前空間の始まり
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 

Generated on Wed Nov 12 2014 19:44:21 for MIST by doxygen 1.8.1.2