bmp.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 
34 #ifndef __INCLUDE_MIST_BMP__
35 #define __INCLUDE_MIST_BMP__
36 
37 
38 #ifndef __INCLUDE_MIST_H__
39 #include "../mist.h"
40 #endif
41 
42 // カラー画像の設定を読み込む
43 #ifndef __INCLUDE_MIST_COLOR_H__
44 #include "../config/color.h"
45 #endif
46 
47 #ifndef __INCLUDE_MIST_ENDIAN__
48 #include "../config/endian.h"
49 #endif
50 
51 #ifndef __INCLUDE_MIST_LIMITS__
52 #include "../limits.h"
53 #endif
54 
55 #include <cstdio>
56 #include <iostream>
57 #include <string>
58 
59 #include <deque>
60 #include <map>
61 #include <algorithm>
62 
63 
64 // mist名前空間の始まり
66 
67 
68 namespace __bmp_controller__
69 {
70  // 構造体内のアライメントを1バイトに設定し,パディングを禁止する
71 #if defined(__MIST_MSVC__) || defined(__INTEL_COMPILER)
72  #pragma pack( push, bmp_align, 1 )
73 #endif
74  struct _rgbquad_
75  {
76  enum{ bytes = 4 };
77  unsigned char rgbBlue;
78  unsigned char rgbGreen;
79  unsigned char rgbRed;
80  unsigned char rgbReserved;
81  } _MIST_PACKED;
82 
83  struct _bitmapinfoheader_
84  {
85  enum{ bytes = 40 };
86  unsigned int biSize;
87  signed int biWidth;
88  signed int biHeight;
89  unsigned short biPlanes;
90  unsigned short biBitCount;
91  unsigned int biCompression;
92  unsigned int biSizeImage;
93  signed int biXPelsPerMeter;
94  signed int biYPelsPerMeter;
95  unsigned int biClrUsed;
96  unsigned int biClrImportant;
97  } _MIST_PACKED;
98 
99  struct _bitmapfileheader_
100  {
101  enum{ bytes = 14 };
102  unsigned short bfType;
103  unsigned int bfSize;
104  unsigned short bfReserved1;
105  unsigned short bfReserved2;
106  unsigned int bfOffBits;
107  } _MIST_PACKED;
108 
109 #if defined(__MIST_MSVC__) || defined(__INTEL_COMPILER)
110  #pragma pack( pop, bmp_align )
111 #endif
112  // 構造体内のアライメントを1バイトに設定し,パディングを禁止する 〜 ここまで 〜
113 
114  template < class T, class Allocator >
115  struct bmp_controller
116  {
117  typedef typename array2< T, Allocator >::size_type size_type;
118  typedef _pixel_converter_< T > pixel_converter;
119  typedef typename pixel_converter::color_type color_type;
120 
121  static bool is_supported( size_type bmp_bits )
122  {
123  bool ret = false;
124  switch( bmp_bits )
125  {
126  case 1:
127  case 4:
128  case 8:
129 // case 16:
130  case 24:
131  case 32:
132  ret = true;
133  break;
134 
135  default:
136  break;
137  }
138  return( ret );
139  }
140 
141  static size_type get_bmp_line_bytes( size_type width, size_type bmp_bits )
142  {
143  switch( bmp_bits )
144  {
145  case 1:
146  {
147  size_type tmp = width / 8;
148  width = width == tmp * 8 ? tmp : tmp + 1;
149  }
150  break;
151 
152  case 4:
153  {
154  size_type tmp = width / 2;
155  width = width == tmp * 2 ? tmp : tmp + 1;
156  }
157  break;
158 
159  case 8:
160  break;
161 
162  case 16:
163  width *= 2;
164  break;
165 
166  case 24:
167  width *= 3;
168  break;
169 
170  case 32:
171  width *= 4;
172  break;
173 
174  default:
175  width = 0;
176  break;
177  }
178  return( width );
179  }
180 
181  static size_type get_bmp_palette_num( size_type bmp_bits )
182  {
183  size_type color_num;
184  switch( bmp_bits )
185  {
186  case 1:
187  color_num = 2;
188  break;
189 
190  case 4:
191  color_num = 16;
192  break;
193 
194  case 8:
195  color_num = 256;
196  break;
197 
198  default:
199  color_num = 0;
200  break;
201  }
202  return( color_num );
203  }
204 
205  static size_type get_bmp_line_strip( size_type width, size_type bmp_bits )
206  {
207  size_type line_bytes = get_bmp_line_bytes( width, bmp_bits );
208  size_type rest = line_bytes % 4;
209  if( rest == 0 )
210  {
211  return( line_bytes );
212  }
213  else
214  {
215  return( line_bytes + 4 - rest );
216  }
217  }
218 
219  static size_type get_bmp_bytes( const array2< T, Allocator > &image, size_type bmp_bits )
220  {
221  return( _bitmapfileheader_::bytes + _bitmapinfoheader_::bytes + _rgbquad_::bytes * get_bmp_palette_num( bmp_bits ) + image.height( ) * get_bmp_line_strip( image.width( ), bmp_bits ) );
222  }
223 
224 
225  class __PALETTE__
226  {
227  public:
228  unsigned char red;
229  unsigned char green;
230  unsigned char blue;
231  unsigned long value;
232 
233  const __PALETTE__ &operator =( const __PALETTE__ &c )
234  {
235  if( this == &c ) return( *this );
236  red = c.red;
237  green = c.green;
238  blue = c.blue;
239  value = c.value;
240  return( *this );
241  }
242  bool operator ==( const __PALETTE__ &c ) const { return( red == c.red && green == c.green && blue == c.blue ); }
243  bool operator <( const __PALETTE__ &c ) const
244  {
245  if( red < c.red ) return( true );
246  if( red != c.red && green < c.green ) return( true );
247  if( red != c.red && green != c.green && blue < c.blue ) return( true );
248  return( false );
249  }
250  static bool compare_value( const __PALETTE__ &c1, const __PALETTE__ &c2 ){ return( c1.value > c2.value ); }
251 
252  __PALETTE__( unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned long v = 0 ) : red( r ), green( g ), blue( b ), value( v ){ }
253  };
254 
255  static double distance( const __PALETTE__ &c1, const __PALETTE__ &c2 )
256  {
257  return( ( c1.red - c2.red ) * ( c1.red - c2.red ) + ( c1.green - c2.green ) * ( c1.green - c2.green ) + ( c1.blue - c2.blue ) * ( c1.blue - c2.blue ) );
258  }
259 
260  // 最も基本となる256色のパレットを作成する
261  static void create_default_palette( std::deque< __PALETTE__ > &palette )
262  {
263  int i, j, k;
264 
265  palette.clear( );
266 
267  for( i = 0 ; i < 6 ; i++ ) /* カラーテーブル作成 */
268  {
269  for( j = 0 ; j < 6 ; j++ )
270  {
271  for( k = 0 ; k < 6 ; k++ )
272  {
273  palette.push_back( __PALETTE__( k * 51, j * 51, i * 51 ) );
274  }
275  }
276  }
277  for( i = 1 ; i < 32 ; i++ )
278  {
279  palette.push_back( __PALETTE__( i * 8, i * 8, i * 8 ) );
280  }
281  palette.push_back( __PALETTE__( 255, 255, 255 ) );
282  }
283 
284  static void eliminate_palette( std::deque< __PALETTE__ > &palette, size_type palette_num )
285  {
286  if( palette.size( ) == palette_num ) return;
287  if( palette.size( ) < palette_num )
288  {
289  size_type num = palette_num - palette.size( );
290  for( size_type i = 0 ; i < num ; i++ ) palette.push_back( __PALETTE__( ) );
291  return;
292  }
293 
294  // 使用回数の多い順に並べる
295  std::sort( palette.begin( ), palette.end( ), __PALETTE__::compare_value );
296 
297  // 先頭から palette_num までのパレットを残す
298  palette.erase( palette.begin( ) + palette_num, palette.end( ) );
299  }
300 
301  // カラーパレットを作成
302  static void create_adaptive_palette( const array2< T, Allocator > &image, _rgbquad_ *palette, size_type palette_num )
303  {
304  size_type width = image.width( );
305  size_type height = image.height( );
306 
307  std::deque< __PALETTE__ > adaptive_palette;
308  std::map< __PALETTE__, __PALETTE__ > palette_table;
309 
310  unsigned char r, g, b;
311  size_type i;
312 
313  // 使用されている色を全て列挙する
314  for( i = 0 ; i < width * height ; i++ )
315  {
316  color_type c = pixel_converter::convert_from( image[i] );
317  r = static_cast< unsigned char >( c.r );
318  g = static_cast< unsigned char >( c.g );
319  b = static_cast< unsigned char >( c.b );
320 
321  if( palette_table.find( __PALETTE__( r, g, b ) ) != palette_table.end( ) )
322  {
323  palette_table[ __PALETTE__( r, g, b ) ].value += 1;
324  }
325  else
326  {
327  palette_table[ __PALETTE__( r, g, b ) ] = __PALETTE__( r, g, b, 0 );
328  }
329  }
330 
331  typename std::map< __PALETTE__, __PALETTE__ >::iterator ite = palette_table.begin( );
332  for( ; ite != palette_table.end( ) ; ++ite )
333  {
334  adaptive_palette.push_back( ite->second );
335  }
336 
337  eliminate_palette( adaptive_palette, palette_num );
338 
339  // パレットを書き出す
340  for( i = 0 ; i < palette_num ; i++ )
341  {
342  palette[i].rgbRed = adaptive_palette[i].red;
343  palette[i].rgbGreen = adaptive_palette[i].green;
344  palette[i].rgbBlue = adaptive_palette[i].blue;
345  palette[i].rgbReserved = 0;
346  }
347 
348  adaptive_palette.clear( );
349  palette_table.clear( );
350  }
351 
352  static size_type find_palette_index( const T &pixel, _rgbquad_ *palette, size_type palette_num )
353  {
354  unsigned char r, g, b, pr, pg, pb;
355  color_type c = pixel_converter::convert_from( pixel );
356  r = static_cast< unsigned char >( c.r );
357  g = static_cast< unsigned char >( c.g );
358  b = static_cast< unsigned char >( c.b );
359 
360  double minimum, distance;
361  size_type k, index = 0;
362  /* 最も近い色を検索 */
363  pr = palette[0].rgbRed;
364  pg = palette[0].rgbGreen;
365  pb = palette[0].rgbBlue;
366 
367  /* ピクセルとカラーテーブル要素の距離計算 */
368  minimum = ( r - pr ) * ( r - pr ) + ( g - pg ) * ( g - pg ) + ( b - pb ) * ( b - pb );
369 
370  for( k = 1 ; k < palette_num ; k++ )
371  {
372  /* 最も近い色を検索 */
373  pr = palette[k].rgbRed;
374  pg = palette[k].rgbGreen;
375  pb = palette[k].rgbBlue;
376 
377  /* ピクセルとカラーテーブル要素の距離計算 */
378  distance = ( r - pr ) * ( r - pr ) + ( g - pg ) * ( g - pg ) + ( b - pb ) * ( b - pb );
379 
380  /* 色空間内の距離が最小の色を保存 */
381  if( minimum > distance )
382  {
383  /* これまでで距離最小の色 */
384  minimum = distance; /* 最小値保存 */
385  index = k; /* カラーテーブル番号保存 */
386  }
387  }
388  return( index );
389  }
390 
391  static bool convert_from_bmp_data( unsigned char *bmp, size_type num_bytes, array2< T, Allocator > &image )
392  {
393  // ビットマップ用のヘッダの位置を指定する
394  _bitmapfileheader_ *pfilehead = reinterpret_cast < _bitmapfileheader_ * > ( bmp );
395  _bitmapinfoheader_ *pinfohead = reinterpret_cast < _bitmapinfoheader_ * > ( bmp + _bitmapfileheader_::bytes );
396  _rgbquad_ *palette = reinterpret_cast < _rgbquad_ * > ( bmp + _bitmapfileheader_::bytes + _bitmapinfoheader_::bytes );
397 
398  _bitmapfileheader_ &filehead = *pfilehead;
399  _bitmapinfoheader_ &infohead = *pinfohead;
400 
401  if( filehead.bfType != 'M' * 256 + 'B' && filehead.bfType != 'm' * 256 + 'b' )
402  {
403  // ビットマップではありません
404  std::cerr << "This is not a bitmap format!" << std::endl;
405  return( false );
406  }
407 
408  size_type bmp_bits = infohead.biBitCount;
409  size_type width = infohead.biWidth;
410  size_type height = infohead.biHeight;
411 
412  if( infohead.biCompression != 0 )
413  {
414  // 圧縮のかかったビットマップは未サポート
415  std::cerr << "Compressed bitmap format is not supported." << std::endl;
416  return( false );
417  }
418 
419  if( !is_supported( bmp_bits ) )
420  {
421  // 未サポートのビットマップ
422  std::cerr << "This format is not supported currently!" << std::endl;
423  return( false );
424  }
425 
426  image.resize( width, height );
427 
428  size_type i, j, jj, line_bytes = get_bmp_line_strip( width, bmp_bits );
429  unsigned char *pixel = bmp + static_cast< size_type >( filehead.bfOffBits );
430 
431  if( line_bytes * height > num_bytes - static_cast< size_type >( filehead.bfOffBits ) )
432  {
433  // 不正なビットマップヘッダ
434  // 規定のデータバイト分だけ存在していない
435  std::cerr << "This bitmap has incorrect BMP header." << std::endl;
436  return( false );
437  }
438 
439  for( jj = 0 ; jj < height ; jj++ )
440  {
441  j = height - jj - 1;
442  switch( bmp_bits )
443  {
444  case 1:
445  {
446  size_type rest = width % 8;
447  size_type w = ( width - rest ) / 8;
448  size_type index, k;
449  unsigned int pix;
450  for( i = 0 ; i < w ; i++ )
451  {
452  pix = pixel[ i ];
453  for( k = 0 ; k < 8 ; k++ )
454  {
455  index = ( pix & 0x80 ) == 0 ? 0 : 1;
456  image( i * 8 + k, j ) = pixel_converter::convert_to( palette[ index ].rgbRed, palette[ index ].rgbGreen, palette[ index ].rgbBlue );
457  pix <<= 1;
458  }
459  }
460  if( rest > 0 )
461  {
462  pix = pixel[ w ];
463  for( i = 0 ; i < rest ; i++ )
464  {
465  index = ( pix & 0x80 ) == 0 ? 0 : 1;
466  image( w * 8 + i, j ) = pixel_converter::convert_to( palette[ index ].rgbRed, palette[ index ].rgbGreen, palette[ index ].rgbBlue );
467  pix <<= 1;
468  }
469  }
470  }
471  break;
472 
473  case 4:
474  {
475  size_type rest = width % 2;
476  size_type w = ( width - rest ) / 2;
477  size_type index;
478  for( i = 0 ; i < w ; i++ )
479  {
480  index = ( pixel[ i ] >> 4 ) & 0x0f;
481  image( i * 2 + 0, j ) = pixel_converter::convert_to( palette[ index ].rgbRed, palette[ index ].rgbGreen, palette[ index ].rgbBlue );
482  index = ( pixel[ i ] ) & 0x0f;
483  image( i * 2 + 1, j ) = pixel_converter::convert_to( palette[ index ].rgbRed, palette[ index ].rgbGreen, palette[ index ].rgbBlue );
484  }
485  if( rest == 1 )
486  {
487  index = ( pixel[ w ] >> 4 ) & 0x0f;
488  image( i * 2 + 0, j ) = pixel_converter::convert_to( palette[ index ].rgbRed, palette[ index ].rgbGreen, palette[ index ].rgbBlue );
489  }
490  }
491  break;
492 
493  case 8:
494  for( i = 0 ; i < width ; i++ )
495  {
496  image( i, j ) = pixel_converter::convert_to( palette[ pixel[ i ] ].rgbRed, palette[ pixel[ i ] ].rgbGreen, palette[ pixel[ i ] ].rgbBlue );
497  }
498  break;
499 
500  case 16:
501  break;
502 
503  case 24:
504  for( i = 0 ; i < width ; i++ )
505  {
506  image( i, j ) = pixel_converter::convert_to( pixel[ i * 3 + 2 ], pixel[ i * 3 + 1 ], pixel[ i * 3 + 0 ] );
507  }
508  break;
509 
510  case 32:
511  for( i = 0 ; i < width ; i++ )
512  {
513  image( i, j ) = pixel_converter::convert_to( pixel[ i * 4 + 2 ], pixel[ i * 4 + 1 ], pixel[ i * 4 + 0 ] );
514  }
515  break;
516 
517  default:
518  break;
519  }
520  pixel += line_bytes;
521  }
522 
523  return( true );
524  }
525 
526  static bool convert_to_bmp_data( const array2< T, Allocator > &image, unsigned char *bmp, size_type bmp_bits )
527  {
528  size_type num_bytes = get_bmp_bytes( image, bmp_bits );
529  size_type color_num = get_bmp_palette_num( bmp_bits );
530  size_type width = image.width( );
531  size_type height = image.height( );
532 
533  // 全てのバッファをクリアする
534  memset( bmp, 0, sizeof( unsigned char ) * num_bytes );
535 
536  // ビットマップ用のヘッダの位置を指定する
537  _bitmapfileheader_ *pfilehead = reinterpret_cast < _bitmapfileheader_ * > ( bmp );
538  _bitmapinfoheader_ *pinfohead = reinterpret_cast < _bitmapinfoheader_ * > ( bmp + _bitmapfileheader_::bytes );
539  _rgbquad_ *palette = reinterpret_cast < _rgbquad_ * > ( bmp + _bitmapfileheader_::bytes + _bitmapinfoheader_::bytes );
540 
541  _bitmapfileheader_ &filehead = *pfilehead;
542  _bitmapinfoheader_ &infohead = *pinfohead;
543 
544  // BITMAPFILEHEADERの情報を設定
545  filehead.bfType = 0x4d42; //'M'*256+'B';
546  filehead.bfSize = static_cast< unsigned int >( num_bytes );
547  filehead.bfOffBits = static_cast< unsigned int >( _bitmapfileheader_::bytes + _bitmapinfoheader_::bytes + _rgbquad_::bytes * color_num );
548 
549  // BITMAPINFOHEADER情報をセット
550  infohead.biSize = _bitmapinfoheader_::bytes;
551  infohead.biWidth = static_cast< int >( width );
552  infohead.biHeight = static_cast< int >( height );
553  infohead.biPlanes = 1;
554  infohead.biBitCount = static_cast< unsigned short >( bmp_bits );
555  infohead.biCompression = 0;
556 
557  switch( bmp_bits )
558  {
559  case 1:
560  case 4:
561  case 8:
562  create_adaptive_palette( image, palette, color_num );
563  break;
564  default:
565  break;
566  }
567 
568  size_type i, j, jj, line_bytes = get_bmp_line_strip( width, bmp_bits );
569  unsigned char *pixel = bmp + _bitmapfileheader_::bytes + _bitmapinfoheader_::bytes + _rgbquad_::bytes * color_num;
570  for( jj = 0 ; jj < height ; jj++ )
571  {
572  j = height - jj - 1;
573  switch( bmp_bits )
574  {
575  case 1:
576  {
577  size_type rest = width % 8;
578  size_type w = ( width - rest ) / 8;
579  for( i = 0 ; i < w ; i++ )
580  {
581  pixel[ i ] = ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 0, j ), palette, color_num ) ) & 0x01 ) << 7;
582  pixel[ i ] |= ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 1, j ), palette, color_num ) ) & 0x01 ) << 6;
583  pixel[ i ] |= ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 2, j ), palette, color_num ) ) & 0x01 ) << 5;
584  pixel[ i ] |= ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 3, j ), palette, color_num ) ) & 0x01 ) << 4;
585  pixel[ i ] |= ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 4, j ), palette, color_num ) ) & 0x01 ) << 3;
586  pixel[ i ] |= ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 5, j ), palette, color_num ) ) & 0x01 ) << 2;
587  pixel[ i ] |= ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 6, j ), palette, color_num ) ) & 0x01 ) << 1;
588  pixel[ i ] |= ( static_cast< unsigned char >( find_palette_index( image( i * 8 + 7, j ), palette, color_num ) ) & 0x01 );
589  }
590  unsigned char pix = 0;
591  for( i = 0 ; i < rest ; i++ )
592  {
593  pix |= ( static_cast< unsigned char >( find_palette_index( image( w * 8 + i, j ), palette, color_num ) ) & 0x01 ) << ( 7 - i );
594  }
595  pixel[ w ] = pix;
596  }
597  break;
598 
599  case 4:
600  {
601  size_type rest = width % 2;
602  size_type w = ( width - rest ) / 2;
603  for( i = 0 ; i < w ; i++ )
604  {
605  pixel[ i ] = static_cast< unsigned char >( find_palette_index( image( i * 2 + 0, j ), palette, color_num ) ) << 4;
606  pixel[ i ] |= static_cast< unsigned char >( find_palette_index( image( i * 2 + 1, j ), palette, color_num ) );
607  }
608  if( rest == 1 )
609  {
610  pixel[ w ] = static_cast< unsigned char >( find_palette_index( image( w * 2 + i, j ), palette, color_num ) ) << 4;
611  }
612  }
613  break;
614 
615  case 8:
616  for( i = 0 ; i < width ; i++ )
617  {
618  pixel[ i ] = static_cast< unsigned char >( find_palette_index( image( i, j ), palette, color_num ) );
619  }
620  break;
621 
622  case 16:
623  break;
624 
625  case 24:
626  for( i = 0 ; i < width ; i++ )
627  {
628  color_type c = limits_0_255( pixel_converter::convert_from( image( i, j ) ) );
629  pixel[ i * 3 + 0 ] = static_cast< unsigned char >( c.b );
630  pixel[ i * 3 + 1 ] = static_cast< unsigned char >( c.g );
631  pixel[ i * 3 + 2 ] = static_cast< unsigned char >( c.r );
632  }
633  break;
634 
635  case 32:
636  for( i = 0 ; i < width ; i++ )
637  {
638  color_type c = limits_0_255( pixel_converter::convert_from( image( i, j ) ) );
639  pixel[ i * 4 + 0 ] = static_cast< unsigned char >( c.b );
640  pixel[ i * 4 + 1 ] = static_cast< unsigned char >( c.g );
641  pixel[ i * 4 + 2 ] = static_cast< unsigned char >( c.r );
642  }
643  break;
644 
645  default:
646  break;
647  }
648  pixel += line_bytes;
649  }
650 
651  return( true );
652  }
653 
654  static bool read( array2< T, Allocator > &image, const std::string &filename )
655  {
656  typedef typename array2< T, Allocator >::size_type size_type;
657 
658  size_type filesize;
659  FILE *fp;
660  if( ( fp = fopen( filename.c_str( ), "rb" ) ) == NULL ) return( false );
661  // ファイルサイズを取得
662  fseek( fp, 0, SEEK_END );
663  filesize = ftell( fp );
664  fseek( fp, 0, SEEK_SET );
665 
666  unsigned char *buff = new unsigned char[ filesize + 1 ];
667  unsigned char *pointer = buff;
668  size_type read_size = 0;
669  while( feof( fp ) == 0 )
670  {
671  read_size = fread( pointer, sizeof( unsigned char ), 1024, fp );
672  if( read_size < 1024 )
673  {
674  break;
675  }
676  pointer += read_size;
677  }
678  fclose( fp );
679 
680  bool ret = convert_from_bmp_data( buff, filesize, image );
681  delete [] buff;
682  return( ret );
683  }
684 
685  static bool write( const array2< T, Allocator > &image, const std::string &filename, size_type bmp_bits )
686  {
687  typedef typename array2< T, Allocator >::size_type size_type;
688 
689  if( image.width( ) == 0 )
690  {
691  std::cerr << "Image width is zero!" << std::endl;
692  return( false );
693  }
694  else if( image.height( ) == 0 )
695  {
696  std::cerr << "Image height is zero!" << std::endl;
697  return( false );
698  }
699  else if( !is_supported( bmp_bits ) )
700  {
701  std::cerr << "This format is not supported currently!" << std::endl;
702  return( false );
703  }
704 
705  size_type size = get_bmp_bytes( image, bmp_bits );
706  unsigned char *buff = new unsigned char[ size + 1 ];
707  bool ret = convert_to_bmp_data( image, buff, bmp_bits );
708 
709  if( !ret )
710  {
711  delete [] buff;
712  return( false );
713  }
714 
715  FILE *fp;
716  if( ( fp = fopen( filename.c_str( ), "wb" ) ) == NULL )
717  {
718  delete [] buff;
719  return( false );
720  }
721 
722 
723  // ファイルへ書き出し
724  unsigned char *pointer = buff;
725  size_type write_size = 0, writed_size = 0;
726  while( size > 0 )
727  {
728  write_size = size < 1024 ? size : 1024;
729 
730  writed_size = fwrite( pointer, sizeof( unsigned char ), write_size, fp );
731  pointer += writed_size;
732  size -= writed_size;
733  if( write_size != writed_size )
734  {
735  fclose( fp );
736  delete [] buff;
737  return( false );
738  }
739  }
740  fclose( fp );
741 
742  delete [] buff;
743  return( true );
744  }
745  };
746 }
747 
750 
763 
764 
775 template < class T, class Allocator >
776 bool read_bmp( array2< T, Allocator > &image, const std::string &filename )
777 {
778  return( __bmp_controller__::bmp_controller< T, Allocator >::read( image, filename ) );
779 }
780 
781 
792 template < class T, class Allocator >
793 bool read_bmp( array2< T, Allocator > &image, const std::wstring &filename )
794 {
795  return( read_bmp( image, wstr2str( filename ) ) );
796 }
797 
798 
814 template < class T, class Allocator >
815 bool write_bmp( const array2< T, Allocator > &image, const std::string &filename, typename array2< T, Allocator >::size_type bmp_bits = 24 )
816 {
817  return( __bmp_controller__::bmp_controller< T, Allocator >::write( image, filename, bmp_bits ) );
818 }
819 
820 
836 template < class T, class Allocator >
837 bool write_bmp( const array2< T, Allocator > &image, const std::wstring &filename, typename array2< T, Allocator >::size_type bmp_bits = 24 )
838 {
839  return( write_bmp( image, wstr2str( filename ), bmp_bits ) );
840 }
841 
843 // BMP 画像入出力グループの終わり
844 
846 // 画像入出力グループの終わり
847 
848 
849 // mist名前空間の終わり
850 _MIST_END
851 
852 
853 #endif // __INCLUDE_MIST_BMP__
854 

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