// // Lol Engine // // Copyright © 2010—2017 Sam Hocevar // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #include #include "image-private.h" #include /* for std::swap */ namespace lol { /* * Public image class */ image::image() : m_data(new image_data()) { } image::image(char const *path) : m_data(new image_data()) { load(path); } image::image(ivec2 size) : m_data(new image_data()) { resize(size); } image::image (image const &other) : m_data(new image_data()) { Copy(other); } image & image::operator =(image other) { /* Since the argument is passed by value, we’re assured it’s a new * object and we can safely swap our m_data pointers. */ std::swap(m_data, other.m_data); return *this; } image::~image() { for (int k : m_data->m_pixels.keys()) delete m_data->m_pixels[k]; delete m_data; } void image::Copy(uint8_t* src_pixels, ivec2 const& size, PixelFormat fmt) { ASSERT(fmt != PixelFormat::Unknown); resize(size); set_format(fmt); memcpy(m_data->m_pixels[(int)fmt]->data(), src_pixels, size.x * size.y * BytesPerPixel(fmt)); } void image::Copy(image const &src) { ivec2 size = src.size(); PixelFormat fmt = src.format(); resize(size); if (fmt != PixelFormat::Unknown) { set_format(fmt); memcpy(m_data->m_pixels[(int)fmt]->data(), src.m_data->m_pixels[(int)fmt]->data(), size.x * size.y * BytesPerPixel(fmt)); } } void image::DummyFill() { load("DUMMY"); } bool image::load(char const *path) { auto resource = ResourceLoader::Load(path); if (resource == nullptr) return false; auto image_resource = dynamic_cast(resource); if (image_resource == nullptr) { delete image_resource; return false; } Copy(*image_resource->m_image); delete image_resource; return true; } bool image::save(char const *path) { auto data = new ResourceImageData(new image(*this)); auto result = ResourceLoader::Save(path, data); delete data; return result; } ivec2 image::size() const { return m_data->m_size; } void image::resize(ivec2 size) { ASSERT(size.x > 0); ASSERT(size.y > 0); if (m_data->m_size != size) { for (int k : m_data->m_pixels.keys()) { delete m_data->m_pixels[k]; m_data->m_pixels[k] = nullptr; } m_data->m_format = PixelFormat::Unknown; } m_data->m_size = size; } /* Wrap-around mode for some operations */ WrapMode image::GetWrapX() const { return m_data->m_wrap_x; } WrapMode image::GetWrapY() const { return m_data->m_wrap_y; } void image::SetWrap(WrapMode wrap_x, WrapMode wrap_y) { m_data->m_wrap_x = wrap_x; m_data->m_wrap_y = wrap_y; } /* The lock() method */ template typename PixelType::type *image::lock() { set_format(T); return (typename PixelType::type *)m_data->m_pixels[(int)T]->data(); } /* The lock2d() method */ void *image::lock2d_helper(PixelFormat T) { set_format(T); return m_data->m_pixels[(int)T]->data2d(); } template void image::unlock2d(array2d const &array) { ASSERT(m_data->m_pixels.has_key((int)m_data->m_format)); ASSERT(array.data() == m_data->m_pixels[(int)m_data->m_format]->data()); } /* Explicit specialisations for the above templates */ #define _T(T) \ template PixelType::type *image::lock(); \ template array2d::type> &image::lock2d(); \ template void image::unlock2d(array2d::type> const &array); _T(PixelFormat::Y_8) _T(PixelFormat::RGB_8) _T(PixelFormat::RGBA_8) _T(PixelFormat::Y_F32) _T(PixelFormat::RGB_F32) _T(PixelFormat::RGBA_F32) #undef _T /* Special case for the "any" format: return the last active buffer */ void *image::lock() { ASSERT(m_data->m_format != PixelFormat::Unknown); return m_data->m_pixels[(int)m_data->m_format]->data(); } void image::unlock(void const *pixels) { ASSERT(m_data->m_pixels.has_key((int)m_data->m_format)); ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->data()); } } /* namespace lol */