您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

246 行
5.5 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010-2015 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // This program 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. ivec2 size = other.GetSize();
  87. PixelFormat fmt = other.GetFormat();
  88. SetSize(size);
  89. if (fmt != PixelFormat::Unknown)
  90. {
  91. SetFormat(fmt);
  92. memcpy(m_data->m_pixels[(int)fmt]->Data(),
  93. other.m_data->m_pixels[(int)fmt]->Data(),
  94. size.x * size.y * BytesPerPixel(fmt));
  95. }
  96. }
  97. Image & Image::operator =(Image other)
  98. {
  99. /* Since the argument is passed by value, we’re assured it’s a new
  100. * object and we can safely swap our m_data pointers. */
  101. std::swap(m_data, other.m_data);
  102. return *this;
  103. }
  104. Image::~Image()
  105. {
  106. for (int k : m_data->m_pixels.keys())
  107. delete m_data->m_pixels[k];
  108. delete m_data;
  109. }
  110. bool Image::Load(char const *path)
  111. {
  112. for (auto codec : g_image_loader.m_codecs)
  113. if (codec->Load(this, path))
  114. return true;
  115. return false;
  116. }
  117. bool Image::Save(char const *path)
  118. {
  119. for (auto codec : g_image_loader.m_codecs)
  120. if (codec->Save(this, path))
  121. return true;
  122. return false;
  123. }
  124. ivec2 Image::GetSize() const
  125. {
  126. return m_data->m_size;
  127. }
  128. void Image::SetSize(ivec2 size)
  129. {
  130. ASSERT(size.x > 0);
  131. ASSERT(size.y > 0);
  132. if (m_data->m_size != size)
  133. {
  134. for (int k : m_data->m_pixels.keys())
  135. {
  136. delete m_data->m_pixels[k];
  137. m_data->m_pixels[k] = nullptr;
  138. }
  139. m_data->m_format = PixelFormat::Unknown;
  140. }
  141. m_data->m_size = size;
  142. }
  143. /* Wrap-around mode for some operations */
  144. WrapMode Image::GetWrapX() const
  145. {
  146. return m_data->m_wrap_x;
  147. }
  148. WrapMode Image::GetWrapY() const
  149. {
  150. return m_data->m_wrap_y;
  151. }
  152. void Image::SetWrap(WrapMode wrap_x, WrapMode wrap_y)
  153. {
  154. m_data->m_wrap_x = wrap_x;
  155. m_data->m_wrap_y = wrap_y;
  156. }
  157. /* The Lock() method */
  158. template<PixelFormat T> typename PixelType<T>::type *Image::Lock()
  159. {
  160. SetFormat(T);
  161. return (typename PixelType<T>::type *)m_data->m_pixels[(int)T]->Data();
  162. }
  163. /* The Lock2D() method */
  164. void *Image::Lock2DHelper(PixelFormat T)
  165. {
  166. SetFormat(T);
  167. return m_data->m_pixels[(int)T]->Data2D();
  168. }
  169. template<typename T>
  170. void Image::Unlock2D(array2d<T> const &array)
  171. {
  172. ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
  173. ASSERT(array.Data() == m_data->m_pixels[(int)m_data->m_format]->Data());
  174. }
  175. /* Explicit specialisations for the above templates */
  176. #define _T(T) \
  177. template PixelType<T>::type *Image::Lock<T>(); \
  178. template array2d<PixelType<T>::type> &Image::Lock2D<T>(); \
  179. template void Image::Unlock2D(array2d<PixelType<T>::type> const &array);
  180. _T(PixelFormat::Y_8)
  181. _T(PixelFormat::RGB_8)
  182. _T(PixelFormat::RGBA_8)
  183. _T(PixelFormat::Y_F32)
  184. _T(PixelFormat::RGB_F32)
  185. _T(PixelFormat::RGBA_F32)
  186. #undef _T
  187. /* Special case for the "any" format: return the last active buffer */
  188. void *Image::Lock()
  189. {
  190. ASSERT(m_data->m_format != PixelFormat::Unknown);
  191. return m_data->m_pixels[(int)m_data->m_format]->Data();
  192. }
  193. void Image::Unlock(void const *pixels)
  194. {
  195. ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
  196. ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->Data());
  197. }
  198. bool Image::RetrieveTiles(array<ivec2, ivec2>& tiles) const
  199. {
  200. /* TODO: re-implement this */
  201. //return m_data->m_codecdata->RetrieveTiles(tiles);
  202. return false;
  203. }
  204. } /* namespace lol */