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.

213 righe
4.4 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2017 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. /*
  18. * Public image class
  19. */
  20. image::image()
  21. : m_data(new image_data())
  22. {
  23. }
  24. image::image(char const *path)
  25. : m_data(new image_data())
  26. {
  27. load(path);
  28. }
  29. image::image(ivec2 size)
  30. : m_data(new image_data())
  31. {
  32. resize(size);
  33. }
  34. image::image (image const &other)
  35. : m_data(new image_data())
  36. {
  37. Copy(other);
  38. }
  39. image & image::operator =(image other)
  40. {
  41. /* Since the argument is passed by value, we’re assured it’s a new
  42. * object and we can safely swap our m_data pointers. */
  43. std::swap(m_data, other.m_data);
  44. return *this;
  45. }
  46. image::~image()
  47. {
  48. for (int k : m_data->m_pixels.keys())
  49. delete m_data->m_pixels[k];
  50. delete m_data;
  51. }
  52. void image::Copy(uint8_t* src_pixels, ivec2 const& size, PixelFormat fmt)
  53. {
  54. ASSERT(fmt != PixelFormat::Unknown);
  55. resize(size);
  56. set_format(fmt);
  57. memcpy(m_data->m_pixels[(int)fmt]->data(), src_pixels,
  58. size.x * size.y * BytesPerPixel(fmt));
  59. }
  60. void image::Copy(image const &src)
  61. {
  62. ivec2 size = src.size();
  63. PixelFormat fmt = src.format();
  64. resize(size);
  65. if (fmt != PixelFormat::Unknown)
  66. {
  67. set_format(fmt);
  68. memcpy(m_data->m_pixels[(int)fmt]->data(),
  69. src.m_data->m_pixels[(int)fmt]->data(),
  70. size.x * size.y * BytesPerPixel(fmt));
  71. }
  72. }
  73. void image::DummyFill()
  74. {
  75. load("DUMMY");
  76. }
  77. bool image::load(char const *path)
  78. {
  79. auto resource = ResourceLoader::Load(path);
  80. if (resource == nullptr)
  81. return false;
  82. auto image_resource = dynamic_cast<ResourceImageData*>(resource);
  83. if (image_resource == nullptr)
  84. {
  85. delete image_resource;
  86. return false;
  87. }
  88. Copy(*image_resource->m_image);
  89. delete image_resource;
  90. return true;
  91. }
  92. bool image::save(char const *path)
  93. {
  94. auto data = new ResourceImageData(new image(*this));
  95. auto result = ResourceLoader::Save(path, data);
  96. delete data;
  97. return result;
  98. }
  99. ivec2 image::size() const
  100. {
  101. return m_data->m_size;
  102. }
  103. void image::resize(ivec2 size)
  104. {
  105. ASSERT(size.x > 0);
  106. ASSERT(size.y > 0);
  107. if (m_data->m_size != size)
  108. {
  109. for (int k : m_data->m_pixels.keys())
  110. {
  111. delete m_data->m_pixels[k];
  112. m_data->m_pixels[k] = nullptr;
  113. }
  114. m_data->m_format = PixelFormat::Unknown;
  115. }
  116. m_data->m_size = size;
  117. }
  118. /* Wrap-around mode for some operations */
  119. WrapMode image::GetWrapX() const
  120. {
  121. return m_data->m_wrap_x;
  122. }
  123. WrapMode image::GetWrapY() const
  124. {
  125. return m_data->m_wrap_y;
  126. }
  127. void image::SetWrap(WrapMode wrap_x, WrapMode wrap_y)
  128. {
  129. m_data->m_wrap_x = wrap_x;
  130. m_data->m_wrap_y = wrap_y;
  131. }
  132. /* The lock() method */
  133. template<PixelFormat T> typename PixelType<T>::type *image::lock()
  134. {
  135. set_format(T);
  136. return (typename PixelType<T>::type *)m_data->m_pixels[(int)T]->data();
  137. }
  138. /* The lock2d() method */
  139. void *image::lock2d_helper(PixelFormat T)
  140. {
  141. set_format(T);
  142. return m_data->m_pixels[(int)T]->data2d();
  143. }
  144. template<typename T>
  145. void image::unlock2d(array2d<T> const &array)
  146. {
  147. ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
  148. ASSERT(array.data() == m_data->m_pixels[(int)m_data->m_format]->data());
  149. }
  150. /* Explicit specialisations for the above templates */
  151. #define _T(T) \
  152. template PixelType<T>::type *image::lock<T>(); \
  153. template array2d<PixelType<T>::type> &image::lock2d<T>(); \
  154. template void image::unlock2d(array2d<PixelType<T>::type> const &array);
  155. _T(PixelFormat::Y_8)
  156. _T(PixelFormat::RGB_8)
  157. _T(PixelFormat::RGBA_8)
  158. _T(PixelFormat::Y_F32)
  159. _T(PixelFormat::RGB_F32)
  160. _T(PixelFormat::RGBA_F32)
  161. #undef _T
  162. /* Special case for the "any" format: return the last active buffer */
  163. void *image::lock()
  164. {
  165. ASSERT(m_data->m_format != PixelFormat::Unknown);
  166. return m_data->m_pixels[(int)m_data->m_format]->data();
  167. }
  168. void image::unlock(void const *pixels)
  169. {
  170. ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
  171. ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->data());
  172. }
  173. } /* namespace lol */