소스 검색

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

objects themselves.
undefined
Sam Hocevar 10 년 전
부모
커밋
227411f337
13개의 변경된 파일169개의 추가작업 그리고 293개의 파일을 삭제
  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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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 파일 보기

@@ -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();
}
};



불러오는 중...
취소
저장