ソースを参照

image: first GIF encoder iteration.

undefined
Sam Hocevar 10年前
コミット
28e8fd6834
5個のファイルの変更134行の追加14行の削除
  1. +8
    -0
      build/lol-build
  2. +111
    -14
      src/image/codec/gdiplus-image.cpp
  3. +6
    -0
      src/image/image-private.h
  4. +8
    -0
      src/image/image.cpp
  5. +1
    -0
      src/lol/image/image.h

+ 8
- 0
build/lol-build ファイルの表示

@@ -288,6 +288,14 @@ build()
{
cd "$top_srcdir"
case "$platform" in
win*-i386)
# Because of locking issues in Wine’s winepath.exe, we only
# build the static libraries in parallel.
make -j$LOL_PARALLEL -C src/bullet
make -j$LOL_PARALLEL -C src/lua
make -j$LOL_PARALLEL -C src/ liblolcore.a
make
;;
*)
make -j$LOL_PARALLEL
;;


+ 111
- 14
src/image/codec/gdiplus-image.cpp ファイルの表示

@@ -38,6 +38,7 @@ class GdiPlusImageCodec : public ImageCodec
public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual bool Save(array<Image *> const &images, char const *path);
};

DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100)
@@ -54,9 +55,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
status = Gdiplus::GdiplusStartup(&token, &input, nullptr);
if (status != Gdiplus::Ok)
{
#if !LOL_BUILD_RELEASE
Log::Error("error %d while initialising GDI+\n", status);
#endif
return false;
}

@@ -69,9 +68,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
wchar_t *wpath = new wchar_t[len + 1];
if (mbstowcs(wpath, fullpath.C(), len + 1) == (size_t)-1)
{
#if !LOL_BUILD_RELEASE
Log::Error("invalid image name %s\n", fullpath.C());
#endif
delete[] wpath;
continue;
}
@@ -84,11 +81,9 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
status = bitmap->GetLastStatus();
if (status != Gdiplus::Ok)
{
#if !LOL_BUILD_RELEASE
if (status != Gdiplus::InvalidParameter)
Log::Error("error %d loading %s\n",
status, fullpath.C());
#endif
delete bitmap;
bitmap = nullptr;
}
@@ -101,9 +96,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)

if (!bitmap)
{
#if !LOL_BUILD_RELEASE
Log::Error("could not load %s\n", path);
#endif
return false;
}

@@ -113,9 +106,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
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 bitmap;
return false;
}
@@ -187,12 +178,8 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)

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(size.x, size.y,
PixelFormat32bppARGB);

Gdiplus::BitmapData bdata;
Gdiplus::Rect rect(0, 0, size.x, size.y);

@@ -230,6 +217,116 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)
return true;
}

bool GdiPlusImageCodec::Save(array<Image *> const &images, char const *path)
{
ULONG_PTR token;
Gdiplus::GdiplusStartupInput input;
Gdiplus::GdiplusStartup(&token, &input, nullptr);

wchar_t const *fmt = L"image/gif";

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[encoder_size];
Gdiplus::GetImageEncoders(num, encoder_size, codecs);
CLSID clsid;
for (unsigned int i = 0; i < num; i++)
{
if (wcscmp(codecs[i].MimeType, fmt) == 0)
{
clsid = codecs[i].Clsid;
break;
}
}

// FIXME: clsid can be uninitialised

size_t len;
len = mbstowcs(nullptr, path, 0);
wchar_t *wpath = new wchar_t[len + 1];
if (mbstowcs(wpath, path, len + 1) == (size_t)-1)
{
Log::Error("could not convert GDI+ filename '%s' to widechar\n", path);
delete[] wpath;
delete[] codecs;
return false;
}

Gdiplus::Image *root_image = nullptr;

#if 0
Gdiplus::Bitmap *tmp = new Gdiplus::Bitmap(1, 1, PixelFormat32bppARGB);
unsigned int param_count = tmp->GetEncoderParameterListSize(&clsid);
printf("%d parameters\n", param_count);
delete tmp;
#endif

for (int i = 0; i < images.Count(); ++i)
{
ivec2 size = images[i]->GetSize();

Gdiplus::Bitmap *b = new Gdiplus::Bitmap(size.x, size.y,
PixelFormat32bppARGB);
Gdiplus::BitmapData bdata;
Gdiplus::Rect rect(0, 0, size.x, size.y);

if (b->LockBits(&rect, (unsigned int)Gdiplus::ImageLockModeWrite,
PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
{
Log::Error("could not lock GDI+ image bits\n");
delete b;
delete[] wpath;
delete[] codecs;
return false;
}

u8vec4 *psrc = images[i]->Lock<PixelFormat::RGBA_8>();
u8vec4 *psrc0 = psrc;
u8vec4 *pdst = static_cast<u8vec4 *>(bdata.Scan0);
for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++)
*pdst++ = (*psrc++).bgra;
images[i]->Unlock(psrc0);
b->UnlockBits(&bdata);

Gdiplus::Status ret;
if (i == 0)
{
root_image = b;
b = nullptr;
ret = root_image->Save(wpath, &clsid, nullptr);
}
else
{
ret = root_image->SaveAdd(b, nullptr);
}

if (ret != Gdiplus::Ok)
{
Log::Error("could not save GDI+ image '%s'\n", path);
delete[] wpath;
delete[] codecs;
delete root_image;
delete b;
return false;
}

delete b;
}

delete[] wpath;
delete[] codecs;
delete root_image;

return true;
}

} /* namespace lol */

#endif /* defined USE_GDIPLUS */


+ 6
- 0
src/image/image-private.h ファイルの表示

@@ -72,6 +72,12 @@ public:
virtual bool Load(Image *image, char const *path) = 0;
virtual bool Save(Image *image, char const *path) = 0;

/* TODO: For animated GIFs. Maybe move this to a Movie object instead? */
virtual bool Save(array<Image *> const &images, char const *path)
{
return false;
}

/* TODO: this should become more fine-grained */
int m_priority;
};


+ 8
- 0
src/image/image.cpp ファイルの表示

@@ -144,6 +144,14 @@ bool Image::Save(char const *path)
return false;
}

bool Image::Save(array<Image *> const &images, char const *path)
{
for (auto codec : g_image_loader.m_codecs)
if (codec->Save(images, path))
return true;
return false;
}

ivec2 Image::GetSize() const
{
return m_data->m_size;


+ 1
- 0
src/lol/image/image.h ファイルの表示

@@ -72,6 +72,7 @@ public:

bool Load(char const *path);
bool Save(char const *path);
static bool Save(array<Image *> const &images, char const *path);

/* Low level access */
ivec2 GetSize() const;


読み込み中…
キャンセル
保存