Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

293 Zeilen
6.7 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include "image-private.h"
  14. #include <algorithm> /* for std::swap */
  15. namespace lol
  16. {
  17. /* HACK: We cannot make this an ImageLoader member function, because the
  18. * REGISTER_IMAGE_CODEC macro forward-declares free functions from
  19. * the "lol" namespace. An apparent bug in Visual Studio's compiler
  20. * makes it think these functions are actually in the top-level
  21. * namespace when the forward declaration is in a class member function.
  22. * To avoid the problem, we make the forward declaration in a free
  23. * function.
  24. * The bug was reported to Microsoft and fixed by them, but the fix
  25. * is not yet available.
  26. * https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */
  27. static bool RegisterAllCodecs(array<ImageCodec *> &codeclist)
  28. {
  29. #if defined __ANDROID__
  30. REGISTER_IMAGE_CODEC(AndroidImageCodec)
  31. #endif
  32. #if defined USE_GDIPLUS
  33. REGISTER_IMAGE_CODEC(GdiPlusImageCodec)
  34. #endif
  35. #if defined __APPLE__ && defined __MACH__ && defined __arm__
  36. REGISTER_IMAGE_CODEC(IosImageCodec)
  37. #endif
  38. #if defined USE_SDL_IMAGE
  39. REGISTER_IMAGE_CODEC(SdlImageCodec)
  40. #endif
  41. #if defined USE_IMLIB2
  42. REGISTER_IMAGE_CODEC(Imlib2ImageCodec)
  43. #endif
  44. REGISTER_IMAGE_CODEC(DummyImageCodec)
  45. REGISTER_IMAGE_CODEC(ZedImageCodec)
  46. REGISTER_IMAGE_CODEC(ZedPaletteImageCodec)
  47. REGISTER_IMAGE_CODEC(OricImageCodec)
  48. return true;
  49. }
  50. /*
  51. * Our static image loader
  52. */
  53. static class ImageLoader
  54. {
  55. friend class Image;
  56. public:
  57. inline ImageLoader()
  58. {
  59. RegisterAllCodecs(m_codecs);
  60. }
  61. private:
  62. array<ImageCodec *> m_codecs;
  63. map<String, Image *> m_images;
  64. }
  65. g_image_loader;
  66. /*
  67. * Public Image class
  68. */
  69. Image::Image()
  70. : m_data(new ImageData())
  71. {
  72. }
  73. Image::Image(char const *path)
  74. : m_data(new ImageData())
  75. {
  76. Load(path);
  77. }
  78. Image::Image(ivec2 size)
  79. : m_data(new ImageData())
  80. {
  81. SetSize(size);
  82. }
  83. Image::Image (Image const &other)
  84. : m_data(new ImageData())
  85. {
  86. Copy(other);
  87. }
  88. Image & Image::operator =(Image other)
  89. {
  90. /* Since the argument is passed by value, we’re assured it’s a new
  91. * object and we can safely swap our m_data pointers. */
  92. std::swap(m_data, other.m_data);
  93. return *this;
  94. }
  95. Image::~Image()
  96. {
  97. for (int k : m_data->m_pixels.keys())
  98. delete m_data->m_pixels[k];
  99. delete m_data;
  100. }
  101. void Image::DummyFill()
  102. {
  103. //TODO: This is not very beautiful
  104. for (auto codec : g_image_loader.m_codecs)
  105. {
  106. if (String(codec->GetName()).contains("Dummy"))
  107. {
  108. codec->Load(this, nullptr);
  109. return;
  110. }
  111. }
  112. }
  113. void Image::Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt)
  114. {
  115. ASSERT(fmt != PixelFormat::Unknown);
  116. SetSize(size);
  117. SetFormat(fmt);
  118. memcpy(m_data->m_pixels[(int)fmt]->data(), pixels,
  119. size.x * size.y * BytesPerPixel(fmt));
  120. }
  121. void Image::Copy(Image const &other)
  122. {
  123. ivec2 size = other.GetSize();
  124. PixelFormat fmt = other.GetFormat();
  125. SetSize(size);
  126. if (fmt != PixelFormat::Unknown)
  127. {
  128. SetFormat(fmt);
  129. memcpy(m_data->m_pixels[(int)fmt]->data(),
  130. other.m_data->m_pixels[(int)fmt]->data(),
  131. size.x * size.y * BytesPerPixel(fmt));
  132. }
  133. }
  134. bool Image::Load(char const *path)
  135. {
  136. ImageCodec* last_codec = nullptr;
  137. for (auto codec : g_image_loader.m_codecs)
  138. {
  139. last_codec = codec;
  140. if (codec->Load(this, path))
  141. {
  142. msg::info("Image::Load: Codec %s succesfully loaded %s.\n", codec->GetName(), path);
  143. return true;
  144. }
  145. }
  146. //Log error, because we shouldn't be here
  147. msg::error("Image::Load: Last codec %s, Error loading image %s.\n", last_codec->GetName(), path);
  148. return false;
  149. }
  150. bool Image::Save(char const *path)
  151. {
  152. ImageCodec* last_codec = nullptr;
  153. for (auto codec : g_image_loader.m_codecs)
  154. {
  155. last_codec = codec;
  156. if (codec->Save(this, path))
  157. {
  158. msg::info("Image::Save: Codec %s succesfully saved %s.\n", codec->GetName(), path);
  159. return true;
  160. }
  161. }
  162. //Log error, because we shouldn't be here
  163. msg::error("Image::Save: Last codec %s, Error saving image %s.\n", last_codec->GetName(), path);
  164. return false;
  165. }
  166. ivec2 Image::GetSize() const
  167. {
  168. return m_data->m_size;
  169. }
  170. void Image::SetSize(ivec2 size)
  171. {
  172. ASSERT(size.x > 0);
  173. ASSERT(size.y > 0);
  174. if (m_data->m_size != size)
  175. {
  176. for (int k : m_data->m_pixels.keys())
  177. {
  178. delete m_data->m_pixels[k];
  179. m_data->m_pixels[k] = nullptr;
  180. }
  181. m_data->m_format = PixelFormat::Unknown;
  182. }
  183. m_data->m_size = size;
  184. }
  185. /* Wrap-around mode for some operations */
  186. WrapMode Image::GetWrapX() const
  187. {
  188. return m_data->m_wrap_x;
  189. }
  190. WrapMode Image::GetWrapY() const
  191. {
  192. return m_data->m_wrap_y;
  193. }
  194. void Image::SetWrap(WrapMode wrap_x, WrapMode wrap_y)
  195. {
  196. m_data->m_wrap_x = wrap_x;
  197. m_data->m_wrap_y = wrap_y;
  198. }
  199. /* The Lock() method */
  200. template<PixelFormat T> typename PixelType<T>::type *Image::Lock()
  201. {
  202. SetFormat(T);
  203. return (typename PixelType<T>::type *)m_data->m_pixels[(int)T]->data();
  204. }
  205. /* The Lock2D() method */
  206. void *Image::Lock2DHelper(PixelFormat T)
  207. {
  208. SetFormat(T);
  209. return m_data->m_pixels[(int)T]->data2d();
  210. }
  211. template<typename T>
  212. void Image::Unlock2D(array2d<T> const &array)
  213. {
  214. ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
  215. ASSERT(array.data() == m_data->m_pixels[(int)m_data->m_format]->data());
  216. }
  217. /* Explicit specialisations for the above templates */
  218. #define _T(T) \
  219. template PixelType<T>::type *Image::Lock<T>(); \
  220. template array2d<PixelType<T>::type> &Image::Lock2D<T>(); \
  221. template void Image::Unlock2D(array2d<PixelType<T>::type> const &array);
  222. _T(PixelFormat::Y_8)
  223. _T(PixelFormat::RGB_8)
  224. _T(PixelFormat::RGBA_8)
  225. _T(PixelFormat::Y_F32)
  226. _T(PixelFormat::RGB_F32)
  227. _T(PixelFormat::RGBA_F32)
  228. #undef _T
  229. /* Special case for the "any" format: return the last active buffer */
  230. void *Image::Lock()
  231. {
  232. ASSERT(m_data->m_format != PixelFormat::Unknown);
  233. return m_data->m_pixels[(int)m_data->m_format]->data();
  234. }
  235. void Image::Unlock(void const *pixels)
  236. {
  237. ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
  238. ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->data());
  239. }
  240. bool Image::RetrieveTiles(array<ivec2, ivec2>& tiles) const
  241. {
  242. /* TODO: re-implement this */
  243. //return m_data->m_codecdata->RetrieveTiles(tiles);
  244. return false;
  245. }
  246. } /* namespace lol */