Mondschein Engine  0.3.0
buffer.cpp
1 /* Mondschein Engine is a fast, powerful, and easy-to-use 3D realtime rendering engine.
2  *
3  * Copyright (C) 2009-2013 by Andreas Amereller
4  * E-Mail: andreas.amereller.dev@googlemail.com
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 3 of the License, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "freeimage/buffer.h"
22 #include "core/texture.h"
23 
24 using namespace mondschein;
25 using namespace io;
26 
27 void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message)
28 {
29  std::cerr<<"FreeImage ERROR: "<<message<<std::endl;
30  return;
31 }
32 
33 FI_Buffer::FI_Buffer() : Buffer(), format(FIF_UNKNOWN)
34 {
35  return;
36 }
37 
38 FI_Buffer::FI_Buffer(FI_Buffer_c _b) : Buffer(_b), format(_b->format)
39 {
40  FreeImage_SetOutputMessage(FreeImageErrorHandler);
41  return;
42 }
43 
44 FI_Buffer::FI_Buffer(FREE_IMAGE_FORMAT _format) : Buffer(), format(_format)
45 {
46  FreeImage_SetOutputMessage(FreeImageErrorHandler);
47  return;
48 }
49 
50 FI_Buffer::~FI_Buffer()
51 {
52  return;
53 }
54 
55 FI_Buffer &FI_Buffer::operator=(FI_Buffer_c _b)
56 {
57  Buffer::operator=(_b);
58  format=_b->format;
59  return *this;
60 }
61 
62 void FI_Buffer::parse_istream(std::istream &_in)
63 {
64  std::string content;
65  while (_in.good())
66  {
67  content+=_in.get();
68  }
69  if (content.empty()) return;
70  try
71  {
72  parse_string(content);
73  }
74  catch (exception &e)
75  {
76  std::string err(*boost::get_error_info<exception_error>(e));
77  err+=", called in function\n\tvoid mondschein::io::FI_Buffer::parse_istream(const std::istream& _in)";
78  throw boost::enable_current_exception(e) << exception_error(err);
79  }
80  return;
81 }
82 
83 void FI_Buffer::parse_string(const std::string &_in)
84 {
85  // Load the image
86  #ifdef DEBUG_0_3
87  std::cout<<"Mondschein Engine DEBUG: Loading image \"FI_Texture\"...\nParameter info:\nLength: "<<_in.size()<<std::endl;
88  #ifdef DEBUG_LONG
89  std::cout<<"Data: "<<_in<<std::endl;
90  #else
91  std::cout<<"Data: <shorted out>"<<std::endl;
92  #endif // DEBUG_LONG
93  #endif // DEBUG_0_3
94  BYTE *str=new BYTE[_in.size()];
95  for (uint i=0;i<_in.size();++i) str[i]=_in.at(i);
96  FIMEMORY *buffer=FreeImage_OpenMemory(str,_in.size());
97  if (buffer==nullptr)
98  {
99  std::string err("Mondschein Engine ERROR: Error while opening memory buffer. Exception raised in function\n\t");
100  err+="void mondschein::io::FI_Buffer::parse_string(const std::string& _in)";
101  throw boost::enable_current_exception(exception()) << exception_error(err);
102  }
103  FIBITMAP *image=nullptr;
104  if (format == FIF_UNKNOWN) format=FreeImage_GetFileTypeFromMemory(buffer,_in.size());
105  if (format == FIF_UNKNOWN)
106  {
107  std::string err("Mondschein Engine ERROR: Could not detect any valid file format. ");
108  err+="Exception raised in function\n\t";
109  err+="void mondschein::io::FI_Buffer::parse_string(const std::string& _in)";
110  throw boost::enable_current_exception(exception()) << exception_error(err);
111  }
112  if (FreeImage_FIFSupportsReading(format))
113  {
114  image=FreeImage_LoadFromMemory(format,buffer);
115  if (image==nullptr)
116  {
117  std::string err("Mondschein Engine ERROR: Error while loading image. Exception raised in function\n\t");
118  err+="void mondschein::io::FI_Buffer::parse_string(const std::string& _in)";
119  throw boost::enable_current_exception(exception()) << exception_error(err);
120  }
121  }
122  else
123  {
124  std::string err("Mondschein Engine ERROR: File format plugin <");
125  err+=FreeImage_GetFormatFromFIF(format);
126  err+="> does not support reading. ";
127  err+="Exception raised in function\n\t";
128  err+="void mondschein::io::FI_Buffer::parse_string(const std::string& _in)";
129  throw boost::enable_current_exception(exception()) << exception_error(err);
130  }
131  FreeImage_CloseMemory(buffer);
132  delete[] str;
133 
134  // Convert FreeImage bitmap to texture object
135  if (FreeImage_GetImageType(image)!=FIT_BITMAP) image=FreeImage_ConvertToStandardType(image,true);
136  uint8 *tmp=static_cast<uint8 *>(FreeImage_GetBits(image));
137  uint32 s=FreeImage_GetWidth(image)*FreeImage_GetHeight(image)*FreeImage_GetBPP(image)/8;
138  std::vector<uint8> data(s);
139  for (uint32 i=0; i<s; ++i)
140  {
141  data.at(i)=tmp[i];
142  }
143  scene::texture_attribs_t texture(FreeImage_GetWidth(image),FreeImage_GetHeight(image),FreeImage_GetBPP(image),
144  !FreeImage_IsLittleEndian(),ONN,0,0,data);
145 
146  #ifdef DEBUG_0_3
147  std::cout<<"Mondschein Engine DEBUG: Loaded texture \"FI_Texture\":\nWidth: "<<texture.width;
148  std::cout<<"\nHeight: "<<texture.height<<"\nBPP: "<<(int)texture.bpp<<"\nRGB: "<<texture.rgb<<"\nTexture filter: ";
149  std::cout<<texture.texture_filter<<"\nAnisotrpic filter: "<<(int)texture.anisotropic_filter<<std::endl;
150  #ifdef DEBUG_LONG
151  std::cout<<"Data: ";
152  for (uint i=0;i<texture.data.size();++i) std::cout<<texture.data.at(i);
153  std::cout<<std::endl;
154  #else
155  std::cout<<"<shorted out>"<<std::endl;
156  #endif // DEBUG_LONG
157  #endif // DEBUG_0_3
158 
159  FreeImage_Unload(image);
160  io_objects_t result=get_io_objects();
161  result.nodes.insert(std::make_pair("ID_FI_TEXTURE",scene::Texture_p(new scene::Texture("ID_FI_TEXTURE",texture))));
162  set_io_objects(result);
163  return;
164 }
165 
166 void FI_Buffer::serialize_ostream(std::ostream &_out) const
167 {
168  std::string content;
169  try
170  {
171  serialize_string(content);
172  }
173  catch (exception &e)
174  {
175  std::string err(*boost::get_error_info<exception_error>(e));
176  err+=", called in function\n\tvoid mondschein::io::FI_Buffer::parse_istream(const std::istream& _in)";
177  throw boost::enable_current_exception(e) << exception_error(err);
178  }
179  _out<<content;
180  return;
181 }
182 
183 void FI_Buffer::serialize_string(std::string &_out) const
184 {
185  // Convert texture object into FreeImage bitmap
186  scene::Texture_p tmp=boost::dynamic_pointer_cast<scene::Texture>(get_io_objects().nodes.at("FI_Texture"));
187  if (tmp.get()==NULL)
188  {
189  std::string err("Mondschein Engine ERROR: No Element \"FI_Texture\" or \"FI_Texture\" is not a texture node. ");
190  err+="Exception raised in function\n\t";
191  err+="void mondschein::io::FI_Buffer::serialize_string(std::string &_out) const";
192  throw boost::enable_current_exception(exception()) << exception_error(err);
193  }
194  scene::texture_attribs_t texture=tmp->get_texture_attribs();
195  FIBITMAP *image=FreeImage_Allocate(texture.width,texture.height,texture.bpp);
196  uint8 *data=static_cast<uint8 *>(FreeImage_GetBits(image));
197  uint32 s=texture.width*texture.height*texture.bpp;
198  for (uint32 i=0; i<s; ++i)
199  {
200  data[i]=texture.data.at(i);
201  }
202 
203  // Write image data to memory buffer
204  char str[FreeImage_GetDIBSize(image)];
205  FIMEMORY *buffer=FreeImage_OpenMemory(reinterpret_cast<BYTE *>(data),FreeImage_GetDIBSize(image));
206  if (format == FIF_UNKNOWN)
207  {
208  if (FreeImage_FIFSupportsWriting(FIF_JPEG)) FreeImage_SaveToMemory(FIF_JPEG,image,buffer);
209  }
210  else
211  {
212  if (FreeImage_FIFSupportsWriting(format)) FreeImage_SaveToMemory(format,image,buffer);
213  }
214  FreeImage_CloseMemory(buffer);
215  _out=str;
216  return;
217 }
218 
219 void FI_Buffer::set_format(FREE_IMAGE_FORMAT _format)
220 {
221  format=_format;
222  return;
223 }
224 
225 FREE_IMAGE_FORMAT FI_Buffer::get_format() const
226 {
227  return format;
228 }