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

Last change on this file since 2506 was 2506, checked in by sam, 7 years ago

base: start removing occurrences of NULL on our long journey to nullptr.

  • Property svn:keywords set to Id
File size: 3.4 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2013 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://www.wtfpl.net/ 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 <algorithm>
18
19using namespace std;
20
21#include <windows.h>
22#include <gdiplus.h>
23
24#include "core.h"
25#include "../../image/image-private.h"
26
27namespace lol
28{
29
30/*
31 * Image implementation class
32 */
33
34DECLARE_IMAGE_LOADER(GdiPlusImageData, 100)
35{
36public:
37    virtual bool Open(char const *);
38    virtual bool Close();
39
40    virtual void *GetData() const;
41
42private:
43    Gdiplus::Bitmap *m_bitmap;
44    Gdiplus::BitmapData m_bdata;
45};
46
47/*
48 * Public Image class
49 */
50
51bool GdiPlusImageData::Open(char const *path)
52{
53    Gdiplus::Status status;
54    ULONG_PTR token;
55    Gdiplus::GdiplusStartupInput input;
56    status = Gdiplus::GdiplusStartup(&token, &input, nullptr);
57    if (status != Gdiplus::Ok)
58    {
59#if !LOL_RELEASE
60        Log::Error("error %d while initialising GDI+\n", status);
61#endif
62        return false;
63    }
64
65    Array<String> pathlist = System::GetPathList(path);
66    m_bitmap = nullptr;
67    for (int i = 0; i < pathlist.Count(); ++i)
68    {
69        size_t len;
70        len = mbstowcs(nullptr, pathlist[i].C(), 0);
71        wchar_t *wpath = new wchar_t[len + 1];
72        if (mbstowcs(wpath, pathlist[i].C(), len + 1) == (size_t)-1)
73        {
74#if !LOL_RELEASE
75            Log::Error("invalid image name %s\n", pathlist[i].C());
76#endif
77            delete[] wpath;
78            continue;
79        }
80
81        status = Gdiplus::Ok;
82        m_bitmap = Gdiplus::Bitmap::FromFile(wpath, 0);
83
84        if (m_bitmap)
85        {
86            status = m_bitmap->GetLastStatus();
87            if (status != Gdiplus::Ok)
88            {
89#if !LOL_RELEASE
90                if (status != Gdiplus::InvalidParameter)
91                    Log::Error("error %d loading %s\n",
92                               status, pathlist[i].C());
93#endif
94                delete m_bitmap;
95                m_bitmap = nullptr;
96            }
97        }
98
99        delete[] wpath;
100        if (m_bitmap)
101            break;
102    }
103
104    if (!m_bitmap)
105    {
106#if !LOL_RELEASE
107        Log::Error("could not load %s\n", path);
108#endif
109        return false;
110    }
111
112    size = ivec2(m_bitmap->GetWidth(), m_bitmap->GetHeight());
113    format = Image::FORMAT_RGBA;
114
115    Gdiplus::Rect rect(0, 0, size.x, size.y);
116    if(m_bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead,
117                          PixelFormat32bppARGB, &m_bdata) != Gdiplus::Ok)
118    {
119#if !LOL_RELEASE
120        Log::Error("could not lock bits in %s\n", path);
121#endif
122        delete m_bitmap;
123        return false;
124    }
125
126    /* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't
127     * know about ARGB, only RGBA. So we swap bytes. We could also fix
128     * this in the shader. */
129    uint8_t *p = static_cast<uint8_t *>(m_bdata.Scan0);
130    for (int y = 0; y < size.y; y++)
131        for (int x = 0; x < size.x; x++)
132        {
133            uint8_t tmp = p[2];
134            p[2] = p[0];
135            p[0] = tmp;
136            p += 4;
137        }
138
139    return true;
140}
141
142bool GdiPlusImageData::Close()
143{
144    m_bitmap->UnlockBits(&m_bdata);
145    delete m_bitmap;
146
147    return true;
148}
149
150void * GdiPlusImageData::GetData() const
151{
152    return m_bdata.Scan0;
153}
154
155} /* namespace lol */
156
157#endif /* defined USE_GDIPLUS */
158
Note: See TracBrowser for help on using the repository browser.