Browse Source

image: refactor codecs so that they no longer store anything in the image

objects themselves.
undefined
Sam Hocevar 10 years ago
parent
commit
227411f337
13 changed files with 169 additions and 293 deletions
  1. +3
    -1
      src/image/codec/android-image.cpp
  2. +3
    -7
      src/image/codec/dummy-image.cpp
  3. +39
    -59
      src/image/codec/gdiplus-image.cpp
  4. +3
    -7
      src/image/codec/ios-image.cpp
  5. +3
    -2
      src/image/codec/ps3-image.cpp
  6. +27
    -22
      src/image/codec/sdl-image.cpp
  7. +3
    -13
      src/image/codec/zed-image.cpp
  8. +3
    -7
      src/image/codec/zed-palette-image.cpp
  9. +21
    -92
      src/image/image-private.h
  10. +48
    -62
      src/image/image.cpp
  11. +8
    -12
      src/lol/image/image.h
  12. +4
    -4
      src/tileset.cpp
  13. +4
    -5
      test/unit/image.cpp

+ 3
- 1
src/image/codec/android-image.cpp View File

@@ -35,7 +35,7 @@ extern ANativeActivity *g_activity;
* Image implementation class
*/

DECLARE_IMAGE_CODEC(AndroidImageCodec, 100)
class AndroidImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
@@ -50,6 +50,8 @@ private:
jint *pixels;
};

DECLARE_IMAGE_CODEC(AndroidImageCodec, 100)

bool AndroidImageCodec::Load(Image *image, char const *path)
{
JNIEnv *env;


+ 3
- 7
src/image/codec/dummy-image.cpp View File

@@ -24,14 +24,15 @@ namespace lol
* Image implementation class
*/

DECLARE_IMAGE_CODEC(DummyImageCodec, 0)
class DummyImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual bool Close();
};

DECLARE_IMAGE_CODEC(DummyImageCodec, 0)

/*
* Public Image class
*/
@@ -63,10 +64,5 @@ bool DummyImageCodec::Save(Image *image, char const *path)
return true;
}

bool DummyImageCodec::Close()
{
return true;
}

} /* namespace lol */


+ 39
- 59
src/image/codec/gdiplus-image.cpp View File

@@ -31,20 +31,15 @@ namespace lol
* Image implementation class
*/

DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100)
class GdiPlusImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual bool Close();

virtual uint8_t *GetData() const;

private:
Gdiplus::Bitmap *m_bitmap;
Gdiplus::BitmapData m_bdata;
};

DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100)

/*
* Public Image class
*/
@@ -64,7 +59,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
}

Array<String> pathlist = System::GetPathList(path);
m_bitmap = nullptr;
Gdiplus::Bitmap *bitmap = nullptr;
for (auto fullpath : pathlist)
{
size_t len;
@@ -80,11 +75,11 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
}

status = Gdiplus::Ok;
m_bitmap = Gdiplus::Bitmap::FromFile(wpath, 0);
bitmap = Gdiplus::Bitmap::FromFile(wpath, 0);

if (m_bitmap)
if (bitmap)
{
status = m_bitmap->GetLastStatus();
status = bitmap->GetLastStatus();
if (status != Gdiplus::Ok)
{
#if !LOL_BUILD_RELEASE
@@ -92,17 +87,17 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
Log::Error("error %d loading %s\n",
status, fullpath.C());
#endif
delete m_bitmap;
m_bitmap = nullptr;
delete bitmap;
bitmap = nullptr;
}
}

delete[] wpath;
if (m_bitmap)
if (bitmap)
break;
}

if (!m_bitmap)
if (!bitmap)
{
#if !LOL_BUILD_RELEASE
Log::Error("could not load %s\n", path);
@@ -110,33 +105,32 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
return false;
}

image->m_data->m_size = ivec2(m_bitmap->GetWidth(),
m_bitmap->GetHeight());
image->m_data->m_format = PixelFormat::RGBA_8;

Gdiplus::Rect rect(0, 0, image->m_data->m_size.x, image->m_data->m_size.y);
if (m_bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead,
PixelFormat32bppARGB, &m_bdata) != Gdiplus::Ok)
ivec2 size(bitmap->GetWidth(), bitmap->GetHeight());
Gdiplus::Rect rect(0, 0, size.x, size.y);
Gdiplus::BitmapData bdata;
if (bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead,
PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
{
#if !LOL_BUILD_RELEASE
Log::Error("could not lock bits in %s\n", path);
#endif
delete m_bitmap;
delete bitmap;
return false;
}

/* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't
* know about ARGB, only RGBA. So we swap bytes. We could also fix
* this in the shader. */
uint8_t *p = static_cast<uint8_t *>(m_bdata.Scan0);
for (int y = 0; y < image->m_data->m_size.y; y++)
for (int x = 0; x < image->m_data->m_size.x; x++)
{
uint8_t tmp = p[2];
p[2] = p[0];
p[0] = tmp;
p += 4;
}
image->SetSize(size);
u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>();
u8vec4 *source = static_cast<u8vec4 *>(bdata.Scan0);
for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++)
*pixels++ = (*source++).bgra;
image->Unlock();

bitmap->UnlockBits(&bdata);
delete bitmap;

return true;
}
@@ -159,16 +153,16 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)
else /* if (strstr(path, ".bmp")) */
fmt = L"image/bmp";

unsigned int num = 0, size = 0;
Gdiplus::GetImageEncodersSize(&num, &size);
unsigned int num = 0, encoder_size = 0;
Gdiplus::GetImageEncodersSize(&num, &encoder_size);
if (num == 0)
{
Log::Error("no GDI+ image encoders found\n");
return false;
}
Gdiplus::ImageCodecInfo *codecs
= (Gdiplus::ImageCodecInfo *)new uint8_t[size];
Gdiplus::GetImageEncoders(num, size, codecs);
= (Gdiplus::ImageCodecInfo *)new uint8_t[encoder_size];
Gdiplus::GetImageEncoders(num, encoder_size, codecs);
CLSID clsid;
for (unsigned int i = 0; i < num; i++)
{
@@ -190,15 +184,16 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)
return false;
}

ivec2 size = image->GetSize();

/* FIXME: we create a new image because there is no guarantee that
* the image comes from GDI. But the engine architecture doesn't
* allow us to save other images anyway. */
Gdiplus::Bitmap *b = new Gdiplus::Bitmap(image->m_data->m_size.x,
image->m_data->m_size.y,
Gdiplus::Bitmap *b = new Gdiplus::Bitmap(size.x, size.y,
PixelFormat32bppARGB);

Gdiplus::BitmapData bdata;
Gdiplus::Rect rect(0, 0, image->m_data->m_size.x, image->m_data->m_size.y);
Gdiplus::Rect rect(0, 0, size.x, size.y);

if (b->LockBits(&rect, (unsigned int)Gdiplus::ImageLockModeWrite,
PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
@@ -210,14 +205,12 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)
return false;
}

u8vec4 *psrc = static_cast<u8vec4 *>(m_bdata.Scan0);
u8vec4 *psrc = image->Lock<PixelFormat::RGBA_8>();
u8vec4 *pdst = static_cast<u8vec4 *>(bdata.Scan0);
for (int y = 0; y < image->m_data->m_size.y; y++)
for (int x = 0; x < image->m_data->m_size.x; x++)
{
for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++)
*pdst++ = (*psrc++).bgra;
}

image->Unlock();
b->UnlockBits(&bdata);

if (b->Save(wpath, &clsid, NULL) != Gdiplus::Ok)
@@ -235,19 +228,6 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)
return true;
}

bool GdiPlusImageCodec::Close()
{
m_bitmap->UnlockBits(&m_bdata);
delete m_bitmap;

return true;
}

uint8_t * GdiPlusImageCodec::GetData() const
{
return static_cast<uint8_t *>(m_bdata.Scan0);
}

} /* namespace lol */

#endif /* defined USE_GDIPLUS */


+ 3
- 7
src/image/codec/ios-image.cpp View File

@@ -28,19 +28,15 @@ namespace lol
* Image implementation class
*/

DECLARE_IMAGE_CODEC(IosImageCodec, 100)
class IosImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual bool Close();

virtual uint8_t *GetData() const;

private:
uint8_t *pixels;
};

DECLARE_IMAGE_CODEC(IosImageCodec, 100)

/*
* Public Image class
*/


+ 3
- 2
src/image/codec/ps3-image.cpp View File

@@ -30,7 +30,7 @@ namespace lol
* Image implementation class
*/

DECLARE_IMAGE_CODEC(Ps3ImageCodec, 100)
class Ps3ImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
@@ -42,9 +42,10 @@ public:
private:
static void* Malloc(uint32_t size, void* data) { return malloc(size); };
static int32_t Free(void* ptr, void* data) { free(ptr); return 0; };
uint8_t *pixels;
};

DECLARE_IMAGE_CODEC(Ps3ImageCodec, 100)

/*
* Public Image class
*/


+ 27
- 22
src/image/codec/sdl-image.cpp View File

@@ -37,34 +37,34 @@ namespace lol
* Image implementation class
*/

DECLARE_IMAGE_CODEC(SdlImageCodec, 50)
class SdlImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual bool Close();

static SDL_Surface *Create32BppSurface(ivec2 size);

private:
SDL_Surface *m_surface;
};

DECLARE_IMAGE_CODEC(SdlImageCodec, 50)

/*
* Public Image class
*/

bool SdlImageCodec::Load(Image *image, char const *path)
{
SDL_Surface *surface = nullptr;

Array<String> pathlist = System::GetPathList(path);
for (int i = 0; i < pathlist.Count(); i++)
{
m_surface = IMG_Load(pathlist[i].C());
if (m_surface)
surface = IMG_Load(pathlist[i].C());
if (surface)
break;
}

if (!m_surface)
if (!surface)
{
#if !LOL_BUILD_RELEASE
Log::Error("could not load image %s\n", path);
@@ -72,34 +72,39 @@ bool SdlImageCodec::Load(Image *image, char const *path)
return false;
}

if (m_surface->format->BytesPerPixel != 4)
ivec2 size(surface->w, surface->h);

if (surface->format->BytesPerPixel != 4)
{
SDL_Surface *tmp = Create32BppSurface(image->GetSize());
SDL_BlitSurface(m_surface, nullptr, tmp, nullptr);
SDL_FreeSurface(m_surface);
m_surface = tmp;
SDL_Surface *tmp = Create32BppSurface(size);
SDL_BlitSurface(surface, nullptr, tmp, nullptr);
SDL_FreeSurface(surface);
surface = tmp;
}

image->SetSize(ivec2(m_surface->w, m_surface->h));
image->SetSize(size);
u8vec4 *data = image->Lock<PixelFormat::RGBA_8>();
memcpy(data, m_surface->pixels, 4 * m_surface->w * m_surface->h);
memcpy(data, surface->pixels, 4 * size.x * size.y);
image->Unlock();

SDL_FreeSurface(surface);

return true;
}

bool SdlImageCodec::Save(Image *image, char const *path)
{
int ret = SDL_SaveBMP(m_surface, path);
ivec2 size = image->GetSize();
SDL_Surface *surface = Create32BppSurface(size);

return ret == 0;
}
u8vec4 *data = image->Lock<PixelFormat::RGBA_8>();
memcpy(surface->pixels, data, 4 * size.x * size.y);
image->Unlock();

bool SdlImageCodec::Close()
{
SDL_FreeSurface(m_surface);
int ret = SDL_SaveBMP(surface, path);
SDL_FreeSurface(surface);

return true;
return ret == 0;
}

SDL_Surface *SdlImageCodec::Create32BppSurface(ivec2 size)


+ 3
- 13
src/image/codec/zed-image.cpp View File

@@ -25,14 +25,12 @@ namespace lol
* Image implementation class
*/

DECLARE_IMAGE_CODEC(ZedImageCodec, 0)
class ZedImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual bool Close();

virtual uint8_t *GetData() const;
virtual bool RetrieveTiles(Array<ivec2, ivec2>& tiles)
{
bool result = m_tiles.Count() > 0;
@@ -47,6 +45,8 @@ private:
Array<ivec2, ivec2> m_tiles;
};

DECLARE_IMAGE_CODEC(ZedImageCodec, 0)

/*
* Public Image class
*/
@@ -307,15 +307,5 @@ bool ZedImageCodec::Save(Image *image, char const *path)
return true;
}

bool ZedImageCodec::Close()
{
return true;
}

uint8_t * ZedImageCodec::GetData() const
{
return m_pixels;
}

} /* namespace lol */


+ 3
- 7
src/image/codec/zed-palette-image.cpp View File

@@ -24,14 +24,15 @@ namespace lol
* Image implementation class
*/

DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 0)
class ZedPaletteImageCodec : public ImageCodec
{
public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual bool Close();
};

DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 0)

/*
* Public Image class
*/
@@ -86,10 +87,5 @@ bool ZedPaletteImageCodec::Save(Image *image, char const *path)
return true;
}

bool ZedPaletteImageCodec::Close()
{
return true;
}

} /* namespace lol */


+ 21
- 92
src/image/image-private.h View File

@@ -22,121 +22,50 @@ namespace lol
class ImageData
{
friend class Image;
friend class ImageBank;
friend class ImageCodec;

public:
ImageData()
: m_size(0, 0),
m_format(PixelFormat::Unknown),
m_refcount(0),
m_codecdata(nullptr)
m_format(PixelFormat::Unknown)
{}

ivec2 m_size;

Map<int, void *> m_pixels;
PixelFormat m_format;

int m_refcount;

/* protected: */ /* FIXME: fix the ImageCodec subclasses access rights */
class ImageCodecData *m_codecdata;
};

class ImageCodec
{
friend class ImageBank;
friend class ImageCodecData;

public:
bool (*m_tryload)(Image *image, char const *path);
ImageCodec *m_next;
int m_priority;

static void RegisterCodec(ImageCodec *codec)
{
Helper(codec);
}

private:
static void Load(Image *image, char const *path)
{
ImageCodec *codec = Helper(nullptr);
bool success = false;

while (codec && !success)
{
success = codec->m_tryload(image, path);
codec = codec->m_next;
}
}

static ImageCodec *Helper(ImageCodec *set)
{
static ImageCodec *codec_list = nullptr;

if (!set)
return codec_list;

ImageCodec **codec = &codec_list;
while (*codec && (*codec)->m_priority > set->m_priority)
codec = &(*codec)->m_next;
set->m_next = *codec;
*codec = set;

return nullptr;
}
};

/*
* Codec-specific data that is stored in some images
*/
class ImageCodecData
{
friend class Image;
friend class ImageBank;

public:
inline ImageCodecData() {}
virtual ~ImageCodecData() {}

virtual bool Load(Image *, char const *) = 0;
virtual bool Save(Image *, char const *) = 0;
virtual bool Load(Image *image, char const *path) = 0;
virtual bool Save(Image *image, char const *path) = 0;

virtual bool RetrieveTiles(Array<ivec2, ivec2>& tiles) { return false; }
/* TODO: this should become more fine-grained */
int m_priority;
};

#define REGISTER_IMAGE_CODEC(name) \
extern void Register##name(); \
Register##name();

#define DECLARE_IMAGE_CODEC(name, prio) \
template<typename T> class name##ImageCodec : public ImageCodec \
extern ImageCodec *Register##name(); \
{ \
public: \
name##ImageCodec() \
{ \
static ImageCodec codec; \
codec.m_tryload = Load; \
codec.m_priority = prio; \
RegisterCodec(&codec); \
} \
static bool Load(Image *image, char const *path) \
/* Insert image codecs in a sorted list */ \
ImageCodec *codec = Register##name(); \
int i = 0, prio = codec->m_priority; \
for ( ; i < codeclist.Count(); ++i) \
{ \
T *codecdata = new T(); \
bool ret = codecdata->Load(image, path); \
delete codecdata; \
return ret; \
if (codeclist[i]->m_priority <= prio) \
break; \
} \
}; \
class name; \
name##ImageCodec<name> name##ImageCodecInstance; \
void Register##name() \
codeclist.Insert(codec, i); \
}

#define DECLARE_IMAGE_CODEC(name, priority) \
ImageCodec *Register##name() \
{ \
(void)&name##ImageCodecInstance; \
} \
class name : public ImageCodecData
ImageCodec *ret = new name(); \
ret->m_priority = priority; \
return ret; \
}

} /* namespace lol */



+ 48
- 62
src/image/image.cpp View File

@@ -30,7 +30,7 @@ namespace lol
* The bug was reported to Microsoft and fixed by them, but the fix
* is not yet available.
* https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */
static bool RegisterAllCodecs()
static bool RegisterAllCodecs(Array<ImageCodec *> &codeclist)
{
#if defined __ANDROID__
REGISTER_IMAGE_CODEC(AndroidImageCodec)
@@ -61,90 +61,74 @@ static bool RegisterAllCodecs()
static class ImageBank
{
public:
void Init();
Image *Create(char const *path);
ImageBank();

void Unref(Image *img);
bool Load(Image *image, char const *path);
bool Save(Image *image, char const *path);

private:
Array<ImageCodec *> m_codecs;
Map<String, Image *> m_images;
}
g_image_bank;

void ImageBank::Init()
ImageBank::ImageBank()
{
/* Initialise codecs (see above) */
static bool init = RegisterAllCodecs();
UNUSED(init);
RegisterAllCodecs(m_codecs);
}

Image *ImageBank::Create(char const *path)
bool ImageBank::Load(Image *image, char const *path)
{
Init();

/* Is our image already in the bank? If so, no need to create it. */
if (!m_images.HasKey(path))
{
m_images[path] = new Image();
ImageCodec::Load(m_images[path], path);
}

Image *img = m_images[path];
++img->m_data->m_refcount;
return img;
/* FIXME: priority is ignored */
for (auto codec : m_codecs)
if (codec->Load(image, path))
return true;
return false;
}

void ImageBank::Unref(Image *img)
bool ImageBank::Save(Image *image, char const *path)
{
ASSERT(img->m_data->m_refcount > 0);
if (--img->m_data->m_refcount == 0)
{
/* FIXME: unload images etc. here */
/* XXX: we’re gonna hit a problem here because we didn’t keep
* the image path within the object, so unless we store it
* ourselves we’re good for a O(n) lookup… which we can’t do
* on Map objects anyway. */
/* TODO: 1. remove image from Map
2. delete img; */
}
/* FIXME: priority is ignored */
for (auto codec : m_codecs)
if (codec->Save(image, path))
return true;
return false;
}


/*
* Static image methods
* Public Image class
*/

Image *Image::Create(char const *path)
Image::Image()
: m_data(new ImageData())
{
return g_image_bank.Create(path);
}

/*
* Public Image class
*/
Image::Image(char const *path)
: m_data(new ImageData())
{
Load(path);
}

Image::Image()
Image::Image(ivec2 size)
: m_data(new ImageData())
{
SetSize(size);
}

Image::~Image()
{
delete m_data->m_codecdata;
delete m_data;
}

void Image::Destroy()
bool Image::Load(char const *path)
{
g_image_bank.Unref(this);
return g_image_bank.Load(this, path);
}

bool Image::Save(char const *path)
{
/* FIXME: add autoloading of save codecs */
if (!m_data->m_codecdata)
return false;
return m_data->m_codecdata->Save(this, path);
return g_image_bank.Save(this, path);
}

ivec2 Image::GetSize() const
@@ -177,13 +161,6 @@ PixelFormat Image::GetFormat() const
return m_data->m_format;
}

void *Image::LockGeneric()
{
ASSERT(m_data->m_format != PixelFormat::Unknown);

return m_data->m_pixels[(int)m_data->m_format];
}

/* The Lock() method and its explicit specialisations */
template<PixelFormat T>
typename PixelType<T>::type *Image::Lock()
@@ -195,19 +172,28 @@ typename PixelType<T>::type *Image::Lock()
if (!m_data->m_pixels.HasKey((int)T))
{
m_data->m_pixels[(int)T] =
new typename PixelType<T>::type(m_data->m_size.x * m_data->m_size.y);
new typename PixelType<T>::type[m_data->m_size.x * m_data->m_size.y];
}

return (typename PixelType<T>::type *)m_data->m_pixels[(int)T];
}

template typename PixelType<PixelFormat::Y_8>::type *
template PixelType<PixelFormat::Y_8>::type *
Image::Lock<PixelFormat::Y_8>();
template typename PixelType<PixelFormat::RGB_8>::type *
template PixelType<PixelFormat::RGB_8>::type *
Image::Lock<PixelFormat::RGB_8>();
template typename PixelType<PixelFormat::RGBA_8>::type *
template PixelType<PixelFormat::RGBA_8>::type *
Image::Lock<PixelFormat::RGBA_8>();

/* Special case for the "any" format */
template<>
void *Image::Lock<PixelFormat::Unknown>()
{
ASSERT(m_data->m_format != PixelFormat::Unknown);

return m_data->m_pixels[(int)m_data->m_format];
}

void Image::Unlock()
{
/* TODO: ensure we are actually unlocking something we locked */
@@ -216,9 +202,9 @@ void Image::Unlock()

bool Image::RetrieveTiles(Array<ivec2, ivec2>& tiles) const
{
if (!m_data->m_codecdata)
return false;
return m_data->m_codecdata->RetrieveTiles(tiles);
/* TODO: re-implement this */
//return m_data->m_codecdata->RetrieveTiles(tiles);
return false;
}

} /* namespace lol */


+ 8
- 12
src/lol/image/image.h View File

@@ -21,7 +21,6 @@
namespace lol
{

/* FIXME: is it possible to avoid the cast to int here? */
template <PixelFormat T> struct PixelType { typedef void type; };
template<> struct PixelType<PixelFormat::Y_8> { typedef uint8_t type; };
template<> struct PixelType<PixelFormat::RGB_8> { typedef u8vec3 type; };
@@ -29,31 +28,28 @@ template<> struct PixelType<PixelFormat::RGBA_8> { typedef u8vec4 type; };

class Image
{
friend class ImageBank;
friend class ImageCodec;

public:
Image();
Image(ivec2 size);
/* XXX: use of this ctor should be discouraged, as it will not
* return information about a possible error. */
Image(char const *path);
~Image();

static Image *Create(char const *path);

bool Load(char const *path);
bool Save(char const *path);
void Destroy();

ivec2 GetSize() const;
void SetSize(ivec2);

PixelFormat GetFormat() const;
void *LockGeneric();
template<PixelFormat T> typename PixelType<T>::type *Lock();
void Unlock();

ivec2 GetSize() const;
void SetSize(ivec2);

bool RetrieveTiles(Array<ivec2, ivec2>& tiles) const;

private:
class ImageData *m_data;
String m_path;
};

} /* namespace lol */


+ 4
- 4
src/tileset.cpp View File

@@ -140,7 +140,7 @@ TileSet::TileSet(char const *path, Image* image, ivec2 size, ivec2 count)

void TileSet::Init(char const *path)
{
Init(path, Image::Create(path));
Init(path, new Image(path));
}

void TileSet::Init(char const *path, Image* image)
@@ -190,7 +190,7 @@ void TileSet::TickDraw(float seconds)
{
if (m_data->m_image)
{
m_data->m_image->Destroy();
delete m_data->m_image;
m_data->m_image = nullptr;
}
else
@@ -207,7 +207,7 @@ void TileSet::TickDraw(float seconds)
int w = m_data->m_texture_size.x;
int h = m_data->m_texture_size.y;

uint8_t *pixels = (uint8_t *)m_data->m_image->LockGeneric();
uint8_t *pixels = (uint8_t *)m_data->m_image->Lock<PixelFormat::Unknown>();
bool resized = false;
if (w != m_data->m_image_size.x || h != m_data->m_image_size.y)
{
@@ -225,7 +225,7 @@ void TileSet::TickDraw(float seconds)

if (resized)
delete[] pixels;
m_data->m_image->Destroy();
delete m_data->m_image;
m_data->m_image = nullptr;
}
}


+ 4
- 5
test/unit/image.cpp View File

@@ -24,13 +24,13 @@ LOLUNIT_FIXTURE(ImageTest)
{
LOLUNIT_TEST(OpenImage)
{
Image *image = Image::Create("data/gradient.png");
Image image("data/gradient.png");

ivec2 size = image->GetSize();
ivec2 size = image.GetSize();
LOLUNIT_ASSERT_EQUAL(size.x, 256);
LOLUNIT_ASSERT_EQUAL(size.y, 16);

u8vec4 *data = image->Lock<PixelFormat::RGBA_8>();
u8vec4 *data = image.Lock<PixelFormat::RGBA_8>();
LOLUNIT_ASSERT(data);

LOLUNIT_ASSERT_EQUAL((int)data[0].r, 0x00);
@@ -41,8 +41,7 @@ LOLUNIT_FIXTURE(ImageTest)
LOLUNIT_ASSERT_EQUAL((int)data[255].g, 0xff);
LOLUNIT_ASSERT_EQUAL((int)data[255].b, 0xff);

image->Unlock();
image->Destroy();
image.Unlock();
}
};



Loading…
Cancel
Save