source: trunk/src/image/codec/gdiplus-image.cpp @ 1408

Last change on this file since 1408 was 1408, checked in by sam, 9 years ago

win32: better error reporting in the GDI+ loader, based on a patch by ponce.

  • Property svn:keywords set to Id
File size: 2.9 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#if defined USE_GDIPLUS
16
17#include <cmath>
18
19#include <algorithm>
20
21using namespace std;
22
23#include <windows.h>
24#include <gdiplus.h>
25
26#include "core.h"
27#include "../../image/image-private.h"
28
29namespace lol
30{
31
32/*
33 * Image implementation class
34 */
35
36DECLARE_IMAGE_LOADER(GdiPlusImageData, 100)
37{
38public:
39    virtual bool Open(char const *);
40    virtual bool Close();
41
42    virtual void *GetData() const;
43
44private:
45    Gdiplus::Bitmap *bitmap;
46    Gdiplus::BitmapData bdata;
47};
48
49/*
50 * Public Image class
51 */
52
53bool GdiPlusImageData::Open(char const *path)
54{
55    size_t len;
56    len = mbstowcs(NULL, path, 0);
57    wchar_t *wpath = new wchar_t[len + 1];
58    if (mbstowcs(wpath, path, len + 1) == (size_t)-1)
59    {
60#if !LOL_RELEASE
61        Log::Error("invalid image name %s\n", path);
62#endif
63        delete[] wpath;
64        return false;
65    }
66
67    ULONG_PTR token;
68    Gdiplus::GdiplusStartupInput input;
69    Gdiplus::GdiplusStartup(&token, &input, NULL);
70
71    for (wchar_t const *wname = wpath; *wname; wname++)
72        if ((bitmap = Gdiplus::Bitmap::FromFile(wname, 0)))
73            break;
74
75    delete[] wpath;
76    if (!bitmap)
77    {
78#if !LOL_RELEASE
79        Log::Error("could not load %s\n", path);
80#endif
81        return false;
82    }
83
84    if (bitmap->GetLastStatus() != Gdiplus::Ok)
85    {
86#if !LOL_RELEASE
87        Log::Error("error %d loading %s\n",
88                   (unsigned)bitmap->GetLastStatus(), path);
89#endif
90        delete bitmap;
91        return false;
92    }
93
94    size = ivec2(bitmap->GetWidth(), bitmap->GetHeight());
95    format = Image::FORMAT_RGBA;
96
97    Gdiplus::Rect rect(0, 0, size.x, size.y);
98    if(bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead,
99                        PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
100    {
101#if !LOL_RELEASE
102        Log::Error("could not lock bits in %s\n", path);
103#endif
104        delete bitmap;
105        return false;
106    }
107
108    /* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't
109     * know about ARGB, only RGBA. So we swap bytes. We could also fix
110     * this in the shader. */
111    uint8_t *p = static_cast<uint8_t *>(bdata.Scan0);
112    for (int y = 0; y < size.y; y++)
113        for (int x = 0; x < size.x; x++)
114        {
115            uint8_t tmp = p[2];
116            p[2] = p[0];
117            p[0] = tmp;
118            p += 4;
119        }
120
121    return true;
122}
123
124bool GdiPlusImageData::Close()
125{
126    bitmap->UnlockBits(&bdata);
127    delete bitmap;
128
129    return true;
130}
131
132void * GdiPlusImageData::GetData() const
133{
134    return bdata.Scan0;
135}
136
137} /* namespace lol */
138
139#endif /* defined USE_GDIPLUS */
140
Note: See TracBrowser for help on using the repository browser.