ImageLoader.cpp
Go to the documentation of this file.
1 #include "ImageLoader.hpp"
2 #include "StreamTexture.hpp"
3 #include <FreeImage.h>
4 
5 namespace iv
6 {
7 
8 static unsigned l_ReadProc( void *buffer, unsigned size, unsigned count, fi_handle handle )
9 {
10  std::istream * in = (std::istream *)handle;
11  in->read( (char*)buffer, size * count );
12  return in->gcount();
13 }
14 
15 static unsigned l_WriteProc( void *buffer, unsigned size, unsigned count, fi_handle handle )
16 {
17  runtime_warning( SRC_INFO, "Writing to input stream is not supported." );
18  return 0;
19 }
20 
21 static int l_SeekProc( fi_handle handle, long offset, int origin )
22 {
23  std::ios_base::seekdir way;
24  if( origin == SEEK_SET )
25  way = std::ios_base::beg;
26  else if( origin == SEEK_CUR )
27  way = std::ios_base::cur;
28  else
29  way = std::ios_base::end;
30 
31  std::istream * in = (std::istream *)handle;
32  in->seekg( offset, way );
33  return 0;
34 }
35 
36 static long l_TellProc( fi_handle handle )
37 {
38  std::istream * in = (std::istream *)handle;
39  return in->tellg();
40 }
41 
42 static FreeImageIO l_IStreamIO =
43 {
44  .read_proc = l_ReadProc,
45  .write_proc = l_WriteProc,
46  .seek_proc = l_SeekProc,
47  .tell_proc = l_TellProc
48 };
49 
50 bool ImageLoader_Load( StreamResource * resource, PixelFormat, std::function< void( ImageLoader_Metadata const &, uint8_t * bytes, size_t bytes_count ) > const & f )
51 {
52  // determine type
53  FREE_IMAGE_FORMAT image_format = FIF_UNKNOWN;
54  resource->with_resource_stream( [&]( std::istream & in )
55  {
56  image_format = FreeImage_GetFileTypeFromHandle( &l_IStreamIO, &in, 0 );
57  if( image_format == FIF_UNKNOWN )
58  image_format = FreeImage_GetFIFFromFilename( resource->resource_path().string().c_str() );
59  } );
60 
61  if( image_format == FIF_UNKNOWN )
62  {
63  resource->cm.log( SRC_INFO, iv::Defs::Log::Warning, "Can not determine image format." );
64  return false;
65  }
66 
67  FIBITMAP * bitmap = nullptr;
68  resource->with_resource_stream( [&]( std::istream & in )
69  {
70  bitmap = FreeImage_LoadFromHandle( image_format, &l_IStreamIO, &in, 0 );
71  } );
72 
73  if( bitmap != nullptr )
74  {
75  // decide on format
76  PixelFormat format;
77  #if defined( FREEIMAGE_BIGENDIAN ) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
78  format = PixelFormat::RGBA;
79  #else
80  format = PixelFormat::BGRA;
81  #endif
82 
83  // convert to suitable format
84  if( format == PixelFormat::RGBA || format == PixelFormat::BGRA )
85  {
86  if( FreeImage_GetImageType( bitmap ) != FIT_BITMAP || FreeImage_GetBPP( bitmap ) != 32 )
87  {
88  resource->cm.log( SRC_INFO, iv::Defs::Log::Performance, "Converting image to PixelFormat::RGBA or PixelFormat::BGRA." );
89  FIBITMAP * old_bitmap = bitmap;
90  bitmap = FreeImage_ConvertTo32Bits( bitmap );
91  FreeImage_Unload( old_bitmap );
92  }
93  }
94  else
95  {
96  resource->cm.log( SRC_INFO, iv::Defs::Log::Warning, "PixelFormat ", format," is not supported in ImageLoader implementation." );
97  }
98 
99  // extract metadata
100  ImageLoader_Metadata metadata;
101  metadata.size.x = FreeImage_GetWidth( bitmap );
102  metadata.size.y = FreeImage_GetHeight( bitmap );
103  metadata.pixel_format = format;
104  int bpp = FreeImage_GetBPP( bitmap ) / 8;
105 
106  // report
107  f( metadata, FreeImage_GetBits( bitmap ), metadata.size.x * metadata.size.y * bpp );
108 
109  // clean up
110  FreeImage_Unload( bitmap );
111  }
112 
113  return false;
114 }
115 
116 }