Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

238 righe
5.4 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include "core.h"
  14. #include "image-private.h"
  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. REGISTER_IMAGE_CODEC(DummyImageCodec)
  33. #if defined USE_GDIPLUS
  34. REGISTER_IMAGE_CODEC(GdiPlusImageCodec)
  35. #endif
  36. #if defined __APPLE__ && defined __MACH__ && defined __arm__
  37. REGISTER_IMAGE_CODEC(IosImageCodec)
  38. #endif
  39. #if defined __CELLOS_LV2__
  40. REGISTER_IMAGE_CODEC(Ps3ImageCodec)
  41. #endif
  42. #if defined USE_SDL_IMAGE
  43. REGISTER_IMAGE_CODEC(SdlImageCodec)
  44. #endif
  45. REGISTER_IMAGE_CODEC(ZedImageCodec)
  46. REGISTER_IMAGE_CODEC(ZedPaletteImageCodec)
  47. #if defined USE_IMLIB2
  48. REGISTER_IMAGE_CODEC(Imlib2ImageCodec)
  49. #endif
  50. return true;
  51. }
  52. /*
  53. * Our static image loader
  54. */
  55. static class ImageLoader
  56. {
  57. friend class Image;
  58. public:
  59. inline ImageLoader()
  60. {
  61. RegisterAllCodecs(m_codecs);
  62. }
  63. private:
  64. Array<ImageCodec *> m_codecs;
  65. Map<String, Image *> m_images;
  66. }
  67. g_image_loader;
  68. /*
  69. * Public Image class
  70. */
  71. Image::Image()
  72. : m_data(new ImageData())
  73. {
  74. }
  75. Image::Image(char const *path)
  76. : m_data(new ImageData())
  77. {
  78. Load(path);
  79. }
  80. Image::Image(ivec2 size)
  81. : m_data(new ImageData())
  82. {
  83. SetSize(size);
  84. }
  85. Image::Image (Image const &other)
  86. : m_data(new ImageData())
  87. {
  88. ivec2 size = other.GetSize();
  89. PixelFormat fmt = other.GetFormat();
  90. SetSize(size);
  91. if (fmt != PixelFormat::Unknown)
  92. {
  93. SetFormat(fmt);
  94. void *psrc = other.m_data->m_pixels[(int)fmt];
  95. void *pdst = m_data->m_pixels[(int)fmt];
  96. memcpy(pdst, psrc, size.x * size.y * BytesPerPixel(fmt));
  97. }
  98. }
  99. Image & Image::operator =(Image other)
  100. {
  101. /* Since the argument is passed by value, we’re assured it’s a new
  102. * object and we can safely swap our m_data pointers. */
  103. std::swap(m_data, other.m_data);
  104. return *this;
  105. }
  106. Image::~Image()
  107. {
  108. for (int k : m_data->m_pixels.Keys())
  109. {
  110. delete[] (uint8_t *)m_data->m_pixels[k];
  111. m_data->m_pixels[k] = nullptr;
  112. }
  113. delete m_data;
  114. }
  115. bool Image::Load(char const *path)
  116. {
  117. for (auto codec : g_image_loader.m_codecs)
  118. if (codec->Load(this, path))
  119. return true;
  120. return false;
  121. }
  122. bool Image::Save(char const *path)
  123. {
  124. for (auto codec : g_image_loader.m_codecs)
  125. if (codec->Save(this, path))
  126. return true;
  127. return false;
  128. }
  129. ivec2 Image::GetSize() const
  130. {
  131. return m_data->m_size;
  132. }
  133. void Image::SetSize(ivec2 size)
  134. {
  135. if (m_data->m_size != size)
  136. {
  137. /* FIXME: delete data or resize it */
  138. if (m_data->m_format != PixelFormat::Unknown)
  139. {
  140. m_data->m_pixels.Remove((int)m_data->m_format);
  141. }
  142. }
  143. m_data->m_size = size;
  144. /* FIXME: don’t do this! It’s useless. */
  145. if (m_data->m_format != PixelFormat::Unknown)
  146. {
  147. Unlock(Lock<PixelFormat::RGBA_8>());
  148. }
  149. }
  150. /* Wrap-around mode for some operations */
  151. WrapMode Image::GetWrapX() const
  152. {
  153. return m_data->m_wrap_x;
  154. }
  155. WrapMode Image::GetWrapY() const
  156. {
  157. return m_data->m_wrap_y;
  158. }
  159. void Image::SetWrap(WrapMode wrap_x, WrapMode wrap_y)
  160. {
  161. m_data->m_wrap_x = wrap_x;
  162. m_data->m_wrap_y = wrap_y;
  163. }
  164. /* The Lock() method */
  165. template<PixelFormat T> typename PixelType<T>::type *Image::Lock()
  166. {
  167. SetFormat(T);
  168. return (typename PixelType<T>::type *)m_data->m_pixels[(int)T];
  169. }
  170. /* Explicit specialisations for the above template */
  171. #define _T(T) template PixelType<T>::type *Image::Lock<T>()
  172. _T(PixelFormat::Y_8);
  173. _T(PixelFormat::RGB_8);
  174. _T(PixelFormat::RGBA_8);
  175. _T(PixelFormat::Y_F32);
  176. _T(PixelFormat::RGB_F32);
  177. _T(PixelFormat::RGBA_F32);
  178. #undef _T
  179. /* Special case for the "any" format: return the last active buffer */
  180. template<> void *Image::Lock<PixelFormat::Unknown>()
  181. {
  182. ASSERT(m_data->m_format != PixelFormat::Unknown);
  183. return m_data->m_pixels[(int)m_data->m_format];
  184. }
  185. void Image::Unlock(void const *pixels)
  186. {
  187. ASSERT(m_data->m_pixels.HasKey((int)m_data->m_format));
  188. /* Ensure that the unlocked data is inside the buffer */
  189. uintptr_t start = (uintptr_t)m_data->m_pixels[(int)m_data->m_format];
  190. uintptr_t end = start + m_data->m_size.x * m_data->m_size.y
  191. * BytesPerPixel(m_data->m_format);
  192. ASSERT(start <= (uintptr_t)pixels);
  193. ASSERT((uintptr_t)pixels <= end);
  194. }
  195. bool Image::RetrieveTiles(Array<ivec2, ivec2>& tiles) const
  196. {
  197. /* TODO: re-implement this */
  198. //return m_data->m_codecdata->RetrieveTiles(tiles);
  199. return false;
  200. }
  201. } /* namespace lol */