You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 13 година
пре 13 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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 */