Beatmup
gdi_bitmap.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <Windows.h>
20 #include <gdiplus.h>
21 #include "gdi_bitmap.h"
22 #include "../../gpu/pipeline.h"
23 #include "../../context.h"
24 #include "../../exception.h"
25 
26 
27 using namespace Beatmup;
28 
29 /**
30  A simple wrapper of IL image
31 */
33 public:
34  Gdiplus::Bitmap* bitmap;
35  Gdiplus::Rect size;
36  Gdiplus::BitmapData data;
37 
38 
39  static void init() {
40  static bool gdiStartedUp = false;
41  if (!gdiStartedUp) {
42  // Start Gdiplus
43  Gdiplus::GdiplusStartupInput gdiplusStartupInput;
44  ULONG_PTR gdiplusToken;
45  Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
46  }
47  }
48 
49 
50  static int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
51  UINT num = 0; // number of image encoders
52  UINT size = 0; // size of the image encoder array in bytes
53 
54  Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;
55 
56  Gdiplus::GetImageEncodersSize(&num, &size);
57  if (size == 0)
58  return -1; // Failure
59 
60  pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
61  if (pImageCodecInfo == NULL)
62  return -1; // Failure
63 
64  Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
65 
66  for (UINT j = 0; j < num; ++j)
67  {
68  if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
69  {
70  *pClsid = pImageCodecInfo[j].Clsid;
71  free(pImageCodecInfo);
72  return j; // Success
73  }
74  }
75 
76  free(pImageCodecInfo);
77  return -1; // Failure
78  }
79 
80 
81  inline Impl(Context &ctx, const wchar_t* filename) {
82  init();
83  bitmap = new Gdiplus::Bitmap(filename, 1);
84  size.X = size.Y = 0;
85  size.Width = bitmap->GetWidth();
86  size.Height = bitmap->GetHeight();
87  }
88 
89 
90  inline Impl(Context &ctx, int width, int height, PixelFormat format) {
91  init();
93  switch (format) {
94  case TripleByte:
95  pf = PixelFormat24bppRGB;
96  break;
97 
98  case QuadByte:
99  pf = PixelFormat32bppARGB;
100  break;
101 
102  default:
103  throw RuntimeError("Unsupported pixel format");
104  }
105  bitmap = new Gdiplus::Bitmap(width, height, pf);
106  size.X = size.Y = 0;
107  size.Width = bitmap->GetWidth();
108  size.Height = bitmap->GetHeight();
109  }
110 
111 
112  inline const PixelFormat getPixelFormat() const {
113  switch (bitmap->GetPixelFormat()) {
114  case PixelFormat8bppIndexed: return SingleByte;
115  case PixelFormat24bppRGB: return TripleByte;
116  case PixelFormat32bppARGB: return QuadByte;
117  }
118  throw RuntimeError("Unsupported pixel format");
119  }
120 
121 
122  inline const int getWidth() const {
123  return size.Width;
124  }
125 
126 
127  inline const int getHeight() const {
128  return size.Height;
129  }
130 
131 
132  inline int getStride() const {
133  return ceili(getBitsPerPixel() * getWidth(), 32) / 8;
134  }
135 
136 
137  inline void lockPixelData() {
138  bitmap->LockBits(&size, Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite, bitmap->GetPixelFormat(), &data);
139  }
140 
141 
142  inline void unlockPixelData() {
143  bitmap->UnlockBits(&data);
144  }
145 
146 
147  inline const pixbyte* getData(int x, int y) const {
148  return (const pixbyte*)data.Scan0 + x + y * data.Stride;
149  }
150 
151 
152  inline void save(const WCHAR* filename) {
153  CLSID clsid;
154  if (wcsstr(filename, L".jpg") || wcsstr(filename, L".jpeg")) {
155  if (GetEncoderClsid(L"image/jpeg", &clsid) < 0)
156  throw Beatmup::RuntimeError("Unable to get encoder class id");
157  }
158  else if (wcsstr(filename, L".png")) {
159  if (GetEncoderClsid(L"image/png", &clsid) < 0)
160  throw Beatmup::RuntimeError("Unable to get encoder class id");
161  }
162  bitmap->Save(filename, &clsid);
163  }
164 };
165 
166 
169 {
170  impl = new Impl(ctx, filename);
171 }
172 
173 
175  impl = new Impl(ctx, width, height, format);
176 }
177 
178 
180  return impl->getPixelFormat();
181 }
182 
183 
184 const int GDIBitmap::getWidth() const {
185  return impl->getWidth();
186 }
187 
188 
189 const int GDIBitmap::getHeight() const {
190  return impl->getHeight();
191 }
192 
193 
194 int GDIBitmap::getStride() const {
195  return impl->getStride();
196 }
197 
198 
200  return getBitsPerPixel() * getWidth() * getHeight() / 8;
201 }
202 
203 
205  impl->lockPixelData();
206 }
207 
208 
211 }
212 
213 
214 const pixbyte* GDIBitmap::getData(int x, int y) const {
215  return impl->getData(x, y);
216 }
217 
218 
219 void GDIBitmap::save(const wchar_t* filename) {
220  impl->save(filename);
221 }
A very basic class for any image.
Context & ctx
context managing this bitmap
const unsigned char getBitsPerPixel() const
Returns number of bits per pixel stored in each bitmap.
Basic class: task and memory management, any kind of static data.
Definition: context.h:59
void unlockPixelData()
Unlocks access to the CPU memory buffer containing pixel data.
Definition: gdi_bitmap.cpp:209
GDIBitmap(Context &ctx, const wchar_t *filename)
Definition: gdi_bitmap.cpp:167
const int getHeight() const
Height of the texture in pixels.
Definition: gdi_bitmap.cpp:189
void lockPixelData()
Locks access to the CPU memory buffer containing pixel data.
Definition: gdi_bitmap.cpp:204
const msize getMemorySize() const
Bitmap size in bytes.
Definition: gdi_bitmap.cpp:199
void save(const wchar_t *filename)
Definition: gdi_bitmap.cpp:219
const int getWidth() const
Width of the texture in pixels.
Definition: gdi_bitmap.cpp:184
const pixbyte * getData(int x, int y) const
Returns a pointer to given pixel.
Definition: gdi_bitmap.cpp:214
const PixelFormat getPixelFormat() const
Pixel format of the bitmap.
Definition: gdi_bitmap.cpp:179
int getStride() const
Definition: gdi_bitmap.cpp:194
A simple wrapper of IL image.
Definition: gdi_bitmap.cpp:32
const pixbyte * getData(int x, int y) const
Definition: gdi_bitmap.cpp:147
Impl(Context &ctx, const wchar_t *filename)
Definition: gdi_bitmap.cpp:81
void save(const WCHAR *filename)
Definition: gdi_bitmap.cpp:152
Impl(Context &ctx, int width, int height, PixelFormat format)
Definition: gdi_bitmap.cpp:90
Gdiplus::Bitmap * bitmap
Definition: gdi_bitmap.cpp:34
Gdiplus::BitmapData data
Definition: gdi_bitmap.cpp:36
const PixelFormat getPixelFormat() const
Definition: gdi_bitmap.cpp:112
const int getHeight() const
Definition: gdi_bitmap.cpp:127
static int GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
Definition: gdi_bitmap.cpp:50
const int getWidth() const
Definition: gdi_bitmap.cpp:122
uint32_t msize
memory size
Definition: basic_types.h:30
uint8_t pixbyte
Definition: basic_types.h:34
@ SingleByte
single channel of 8 bits per pixel (like grayscale), unsigned integer values
@ QuadByte
4 channels of 8 bits per pixel (like RGBA), unsigned integer values
@ TripleByte
3 channels of 8 bits per pixel (like RGB), unsigned integer values
#define ceili(x, y)
integer division x/y with ceiling
Definition: utils.hpp:21
JNIEnv jobject jint format
jobject jlong jint jint y
Beatmup::Context * ctx
JNIEnv jlong jstring filename
jlong jint width
jlong jint jint height
jobject jlong jint x