rays 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.doc/ext/rays/bitmap.cpp +100 -33
- data/.doc/ext/rays/bounds.cpp +2 -2
- data/.doc/ext/rays/camera.cpp +2 -2
- data/.doc/ext/rays/color.cpp +2 -2
- data/.doc/ext/rays/color_space.cpp +3 -3
- data/.doc/ext/rays/font.cpp +5 -4
- data/.doc/ext/rays/image.cpp +1 -1
- data/.doc/ext/rays/matrix.cpp +4 -4
- data/.doc/ext/rays/painter.cpp +1 -1
- data/.doc/ext/rays/point.cpp +2 -2
- data/.doc/ext/rays/polygon.cpp +3 -3
- data/.doc/ext/rays/polyline.cpp +3 -3
- data/.doc/ext/rays/rays.cpp +10 -10
- data/.doc/ext/rays/shader.cpp +2 -2
- data/.github/workflows/release-gem.yml +2 -2
- data/.github/workflows/tag.yml +1 -1
- data/.github/workflows/test.yml +10 -1
- data/ChangeLog.md +14 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +17 -2
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +100 -33
- data/ext/rays/bounds.cpp +2 -2
- data/ext/rays/camera.cpp +2 -2
- data/ext/rays/color.cpp +2 -2
- data/ext/rays/color_space.cpp +3 -3
- data/ext/rays/defs.h +2 -0
- data/ext/rays/extconf.rb +4 -2
- data/ext/rays/font.cpp +5 -4
- data/ext/rays/image.cpp +1 -1
- data/ext/rays/matrix.cpp +4 -4
- data/ext/rays/painter.cpp +1 -1
- data/ext/rays/point.cpp +2 -2
- data/ext/rays/polygon.cpp +3 -3
- data/ext/rays/polyline.cpp +3 -3
- data/ext/rays/rays.cpp +10 -10
- data/ext/rays/shader.cpp +2 -2
- data/include/rays/color_space.h +4 -4
- data/include/rays/defs.h +7 -0
- data/include/rays/rays.h +8 -0
- data/include/rays/ruby/bitmap.h +2 -2
- data/include/rays/ruby/bounds.h +2 -2
- data/include/rays/ruby/camera.h +2 -2
- data/include/rays/ruby/color.h +2 -2
- data/include/rays/ruby/color_space.h +2 -2
- data/include/rays/ruby/exception.h +3 -3
- data/include/rays/ruby/font.h +2 -2
- data/include/rays/ruby/image.h +2 -2
- data/include/rays/ruby/matrix.h +2 -2
- data/include/rays/ruby/painter.h +2 -2
- data/include/rays/ruby/point.h +2 -2
- data/include/rays/ruby/polygon.h +2 -2
- data/include/rays/ruby/polyline.h +2 -2
- data/include/rays/ruby/rays.h +6 -6
- data/include/rays/ruby/shader.h +2 -2
- data/include/rays/ruby.h +3 -1
- data/include/rays.h +3 -0
- data/lib/rays/bitmap.rb +7 -0
- data/lib/rays/extension.rb +4 -0
- data/rays.gemspec +2 -2
- data/src/coord.h +2 -2
- data/src/font.cpp +1 -0
- data/src/image.cpp +0 -29
- data/src/ios/bitmap.mm +23 -30
- data/src/ios/font.mm +4 -1
- data/src/ios/opengl.mm +23 -10
- data/src/ios/rays.mm +5 -3
- data/src/matrix.h +1 -1
- data/src/opengl.h +7 -8
- data/src/osx/bitmap.mm +23 -30
- data/src/osx/font.mm +4 -1
- data/src/osx/opengl.mm +31 -19
- data/src/osx/rays.mm +5 -3
- data/src/painter.cpp +1 -0
- data/src/shader.cpp +3 -0
- data/src/texture.cpp +3 -25
- data/src/texture.h +0 -2
- data/src/win32/bitmap.cpp +167 -65
- data/src/win32/camera.cpp +119 -0
- data/src/win32/font.cpp +179 -40
- data/src/win32/gdi.cpp +2 -4
- data/src/win32/gdi.h +1 -1
- data/src/win32/opengl.cpp +127 -0
- data/src/win32/rays.cpp +16 -9
- data/test/helper.rb +2 -5
- data/test/test_bitmap.rb +3 -1
- data/test/test_image.rb +8 -14
- data/test/test_painter.rb +4 -4
- metadata +8 -8
- data/include/rays/opengl.h +0 -20
- data/src/win32/font.h +0 -24
data/src/osx/bitmap.mm
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
#import "bitmap.h"
|
3
3
|
|
4
4
|
|
5
|
-
#include <assert.h>
|
6
5
|
#import <Cocoa/Cocoa.h>
|
7
6
|
#include "rays/exception.h"
|
8
7
|
#include "../color_space.h"
|
@@ -60,7 +59,7 @@ namespace Rays
|
|
60
59
|
|
61
60
|
ColorSpace color_space;
|
62
61
|
|
63
|
-
void* pixels
|
62
|
+
void* pixels = NULL;
|
64
63
|
|
65
64
|
CGContextRef context = NULL;
|
66
65
|
|
@@ -122,37 +121,40 @@ namespace Rays
|
|
122
121
|
|
123
122
|
static void
|
124
123
|
setup_bitmap (
|
125
|
-
Bitmap*
|
124
|
+
Bitmap* bitmap,
|
126
125
|
int w, int h, const ColorSpace& cs,
|
127
|
-
const void*
|
126
|
+
const void* pixels = NULL, bool clear_pixels = true)
|
128
127
|
{
|
129
|
-
if (
|
128
|
+
if (w <= 0 || h <= 0 || !cs)
|
130
129
|
argument_error(__FILE__, __LINE__);
|
131
130
|
|
132
|
-
|
131
|
+
Bitmap::Data* self = bitmap->self.get();
|
133
132
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
self->clear();
|
134
|
+
|
135
|
+
self->width = w;
|
136
|
+
self->height = h;
|
137
|
+
self->color_space = cs;
|
138
|
+
self->modified = true;
|
138
139
|
|
139
140
|
size_t size = w * h * cs.Bpp();
|
140
|
-
|
141
|
+
self->pixels = new uchar[size];
|
141
142
|
|
142
|
-
if (
|
143
|
-
memcpy(
|
143
|
+
if (pixels)
|
144
|
+
memcpy(self->pixels, pixels, size);
|
144
145
|
else if (clear_pixels)
|
145
|
-
memset(
|
146
|
+
memset(self->pixels, 0, size);
|
146
147
|
}
|
147
148
|
|
148
|
-
|
149
|
-
|
149
|
+
Bitmap
|
150
|
+
Bitmap_from (const Texture& tex)
|
150
151
|
{
|
151
|
-
if (!
|
152
|
+
if (!tex)
|
152
153
|
argument_error(__FILE__, __LINE__);
|
153
154
|
|
155
|
+
Bitmap bmp;
|
154
156
|
setup_bitmap(
|
155
|
-
|
157
|
+
&bmp, tex.width(), tex.height(), tex.color_space(), NULL, false);
|
156
158
|
|
157
159
|
GLenum format, type;
|
158
160
|
ColorSpace_get_gl_format_and_type(&format, &type, tex.color_space());
|
@@ -160,18 +162,12 @@ namespace Rays
|
|
160
162
|
FrameBuffer fb(tex);
|
161
163
|
FrameBufferBinder binder(fb.id());
|
162
164
|
|
163
|
-
for (int y = 0; y <
|
165
|
+
for (int y = 0; y < bmp.height(); ++y)
|
164
166
|
{
|
165
|
-
GLvoid* ptr = (GLvoid*)
|
166
|
-
glReadPixels(0, y,
|
167
|
+
GLvoid* ptr = (GLvoid*) bmp.at<uchar>(0, y);
|
168
|
+
glReadPixels(0, y, bmp.width(), 1, format, type, ptr);
|
167
169
|
}
|
168
|
-
}
|
169
170
|
|
170
|
-
Bitmap
|
171
|
-
Bitmap_from (const Texture& texture)
|
172
|
-
{
|
173
|
-
Bitmap bmp;
|
174
|
-
setup_bitmap(&bmp, texture);
|
175
171
|
return bmp;
|
176
172
|
}
|
177
173
|
|
@@ -206,15 +202,12 @@ namespace Rays
|
|
206
202
|
if (*str == '\0') return;
|
207
203
|
|
208
204
|
font.draw_string(bitmap->self->get_context(), bitmap->height(), str, x, y);
|
209
|
-
|
210
205
|
Bitmap_set_modified(bitmap);
|
211
206
|
}
|
212
207
|
|
213
208
|
void
|
214
209
|
Bitmap_set_modified (Bitmap* bitmap, bool modified)
|
215
210
|
{
|
216
|
-
assert(bitmap);
|
217
|
-
|
218
211
|
bitmap->self->modified = modified;
|
219
212
|
}
|
220
213
|
|
data/src/osx/font.mm
CHANGED
@@ -154,11 +154,14 @@ namespace Rays
|
|
154
154
|
{
|
155
155
|
CGContextRef context = (CGContextRef) context_;
|
156
156
|
|
157
|
-
if (
|
157
|
+
if (!context || !str)
|
158
158
|
argument_error(__FILE__, __LINE__);
|
159
159
|
|
160
160
|
if (*str == '\0') return;
|
161
161
|
|
162
|
+
if (!*this)
|
163
|
+
invalid_state_error(__FILE__, __LINE__);
|
164
|
+
|
162
165
|
CTLinePtr line = make_line(self->font, str);
|
163
166
|
if (!line)
|
164
167
|
rays_error(__FILE__, __LINE__, "creating CTLineRef failed.");
|
data/src/osx/opengl.mm
CHANGED
@@ -3,30 +3,18 @@
|
|
3
3
|
|
4
4
|
|
5
5
|
#import <AppKit/AppKit.h>
|
6
|
+
#include "rays/rays.h"
|
7
|
+
#include "rays/exception.h"
|
6
8
|
|
7
9
|
|
8
10
|
namespace Rays
|
9
11
|
{
|
10
12
|
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
{
|
15
|
-
NSOpenGLContext* c = (NSOpenGLContext*) context;
|
16
|
-
[c makeCurrentContext];
|
17
|
-
}
|
18
|
-
|
19
|
-
Context
|
20
|
-
OpenGL_get_context ()
|
14
|
+
static NSOpenGLContext*
|
15
|
+
get_opengl_offscreen_context ()
|
21
16
|
{
|
22
|
-
|
23
|
-
}
|
24
|
-
|
25
|
-
|
26
|
-
Context
|
27
|
-
get_offscreen_context ()
|
28
|
-
{
|
29
|
-
static Context context = NULL;
|
17
|
+
static NSOpenGLContext* context = nil;
|
30
18
|
if (!context)
|
31
19
|
{
|
32
20
|
NSOpenGLPixelFormatAttribute attribs[] =
|
@@ -44,11 +32,35 @@ namespace Rays
|
|
44
32
|
};
|
45
33
|
NSOpenGLPixelFormat* pf = [[[NSOpenGLPixelFormat alloc]
|
46
34
|
initWithAttributes: attribs] autorelease];
|
47
|
-
context = [[
|
48
|
-
initWithFormat: pf shareContext: nil] autorelease];
|
35
|
+
context = [[NSOpenGLContext alloc] initWithFormat: pf shareContext: nil];
|
49
36
|
}
|
50
37
|
return context;
|
51
38
|
}
|
52
39
|
|
53
40
|
|
41
|
+
void
|
42
|
+
OpenGL_init ()
|
43
|
+
{
|
44
|
+
activate_offscreen_context();
|
45
|
+
}
|
46
|
+
|
47
|
+
void
|
48
|
+
OpenGL_fin ()
|
49
|
+
{
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
Context
|
54
|
+
get_offscreen_context ()
|
55
|
+
{
|
56
|
+
return get_opengl_offscreen_context();
|
57
|
+
}
|
58
|
+
|
59
|
+
void
|
60
|
+
activate_offscreen_context ()
|
61
|
+
{
|
62
|
+
[get_opengl_offscreen_context() makeCurrentContext];
|
63
|
+
}
|
64
|
+
|
65
|
+
|
54
66
|
}// Rays
|
data/src/osx/rays.mm
CHANGED
@@ -25,18 +25,20 @@ namespace Rays
|
|
25
25
|
init ()
|
26
26
|
{
|
27
27
|
if (global::pool)
|
28
|
-
rays_error(__FILE__, __LINE__, "
|
28
|
+
rays_error(__FILE__, __LINE__, "already initialized.");
|
29
29
|
|
30
30
|
global::pool = [[NSAutoreleasePool alloc] init];
|
31
31
|
|
32
|
-
|
32
|
+
OpenGL_init();
|
33
33
|
}
|
34
34
|
|
35
35
|
void
|
36
36
|
fin ()
|
37
37
|
{
|
38
38
|
if (!global::pool)
|
39
|
-
rays_error(__FILE__, __LINE__, "
|
39
|
+
rays_error(__FILE__, __LINE__, "not initialized.");
|
40
|
+
|
41
|
+
OpenGL_fin();
|
40
42
|
|
41
43
|
[global::pool release];
|
42
44
|
global::pool = nil;
|
data/src/painter.cpp
CHANGED
data/src/shader.cpp
CHANGED
@@ -156,6 +156,9 @@ namespace Rays
|
|
156
156
|
// restore premultiplied rgb values
|
157
157
|
" vec3 rgb__ = col__.a != 0.0 ? col__.rgb / col__.a : col__.rgb;\n"
|
158
158
|
" gl_FragColor = " + V_COLOR + " * vec4(rgb__, col__.a);\n"
|
159
|
+
#elif defined(WIN32)
|
160
|
+
" float a__ = (col__.r + col__.g + col__.b) / 3.0;\n"
|
161
|
+
" gl_FragColor = " + V_COLOR + " * vec4(1.0, 1.0, 1.0, a__);\n"
|
159
162
|
#else
|
160
163
|
" gl_FragColor = " + V_COLOR + " * col__;\n"
|
161
164
|
#endif
|
data/src/texture.cpp
CHANGED
@@ -17,8 +17,6 @@ namespace Rays
|
|
17
17
|
struct Texture::Data
|
18
18
|
{
|
19
19
|
|
20
|
-
Context context = NULL;
|
21
|
-
|
22
20
|
GLuint id = 0;
|
23
21
|
|
24
22
|
int width, height, width_pow2, height_pow2;
|
@@ -53,22 +51,15 @@ namespace Rays
|
|
53
51
|
{
|
54
52
|
if (!has_id()) return;
|
55
53
|
|
56
|
-
Context current_context = OpenGL_get_context();
|
57
|
-
|
58
|
-
assert(context);
|
59
|
-
OpenGL_set_context(context);
|
60
|
-
|
61
54
|
glDeleteTextures(1, &id);
|
55
|
+
OpenGL_check_error(__FILE__, __LINE__);
|
62
56
|
|
63
|
-
|
64
|
-
|
65
|
-
context = NULL;
|
66
|
-
id = 0;
|
57
|
+
id = 0;
|
67
58
|
}
|
68
59
|
|
69
60
|
bool has_id () const
|
70
61
|
{
|
71
|
-
return
|
62
|
+
return id > 0;
|
72
63
|
}
|
73
64
|
|
74
65
|
};// Texture::Data
|
@@ -185,13 +176,6 @@ namespace Rays
|
|
185
176
|
{
|
186
177
|
assert(self && !self->has_id());
|
187
178
|
|
188
|
-
if (self->context)
|
189
|
-
invalid_state_error(__FILE__, __LINE__);
|
190
|
-
|
191
|
-
self->context = OpenGL_get_context();
|
192
|
-
if (!self->context)
|
193
|
-
opengl_error(__FILE__, __LINE__);
|
194
|
-
|
195
179
|
glGenTextures(1, &self->id);
|
196
180
|
glBindTexture(GL_TEXTURE_2D, self->id);
|
197
181
|
if (glIsTexture(self->id) == GL_FALSE)
|
@@ -313,12 +297,6 @@ namespace Rays
|
|
313
297
|
return self->color_space;
|
314
298
|
}
|
315
299
|
|
316
|
-
Context
|
317
|
-
Texture::context () const
|
318
|
-
{
|
319
|
-
return self->context;
|
320
|
-
}
|
321
|
-
|
322
300
|
GLuint
|
323
301
|
Texture::id () const
|
324
302
|
{
|
data/src/texture.h
CHANGED
data/src/win32/bitmap.cpp
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
#include "../bitmap.h"
|
2
2
|
|
3
3
|
|
4
|
-
#
|
5
|
-
#include
|
4
|
+
#define STB_IMAGE_IMPLEMENTATION
|
5
|
+
#include <stb_image.h>
|
6
|
+
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
7
|
+
#include <stb_image_write.h>
|
8
|
+
|
9
|
+
#include "rays/exception.h"
|
10
|
+
#include "../color_space.h"
|
11
|
+
#include "../font.h"
|
12
|
+
#include "../texture.h"
|
13
|
+
#include "../frame_buffer.h"
|
6
14
|
#include "gdi.h"
|
7
15
|
|
8
16
|
|
@@ -15,60 +23,55 @@ namespace Rays
|
|
15
23
|
|
16
24
|
int width, height, pitch;
|
17
25
|
|
18
|
-
ColorSpace
|
26
|
+
ColorSpace color_space;
|
19
27
|
|
20
|
-
void* pixels;
|
28
|
+
void* pixels = NULL;
|
21
29
|
|
22
30
|
Win32::MemoryDC memdc;
|
23
31
|
|
24
32
|
bool modified;
|
25
33
|
|
26
34
|
Data ()
|
27
|
-
: pixels(NULL), modified(true)
|
28
35
|
{
|
36
|
+
clear();
|
29
37
|
}
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
init_bitmap_pixels (Bitmap* bmp)
|
36
|
-
{
|
37
|
-
if (!*bmp) return false;
|
38
|
-
|
39
|
-
memset(bmp->data(), 0, bmp->size());
|
40
|
-
|
41
|
-
if (!bmp->color_space().has_alpha())
|
42
|
-
return true;
|
39
|
+
~Data ()
|
40
|
+
{
|
41
|
+
clear();
|
42
|
+
}
|
43
43
|
|
44
|
-
|
45
|
-
for (int y = 0; y < bmp->height(); ++y)
|
44
|
+
void clear ()
|
46
45
|
{
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
p += Bpp;
|
54
|
-
}
|
46
|
+
if (memdc) memdc = Win32::MemoryDC();
|
47
|
+
|
48
|
+
width = height = pitch = 0;
|
49
|
+
color_space = COLORSPACE_UNKNOWN;
|
50
|
+
pixels = NULL;
|
51
|
+
modified = false;
|
55
52
|
}
|
56
53
|
|
57
|
-
|
58
|
-
}
|
54
|
+
};// Bitmap::Data
|
59
55
|
|
60
|
-
|
61
|
-
|
56
|
+
|
57
|
+
static void
|
58
|
+
setup_bitmap (
|
59
|
+
Bitmap* bitmap,
|
60
|
+
int w, int h, const ColorSpace& cs,
|
61
|
+
const void* pixels = NULL, bool clear_pixels = true, HDC hdc = NULL)
|
62
62
|
{
|
63
|
-
if (w <= 0 || h <= 0 || !cs
|
64
|
-
|
63
|
+
if (w <= 0 || h <= 0 || !cs)
|
64
|
+
argument_error(__FILE__, __LINE__);
|
65
|
+
|
66
|
+
Bitmap::Data* self = bitmap->self.get();
|
65
67
|
|
66
|
-
|
68
|
+
self->clear();
|
67
69
|
|
68
|
-
self->width
|
69
|
-
self->height
|
70
|
-
self->
|
71
|
-
self->
|
70
|
+
self->width = w;
|
71
|
+
self->height = h;
|
72
|
+
self->pitch = w * cs.Bpp();
|
73
|
+
self->color_space = cs;
|
74
|
+
self->modified = true;
|
72
75
|
|
73
76
|
int padding = 4 - self->pitch % 4;
|
74
77
|
if (padding < 4) self->pitch += padding;
|
@@ -81,32 +84,49 @@ namespace Rays
|
|
81
84
|
header.biWidth = self->width;
|
82
85
|
header.biHeight = -self->height;
|
83
86
|
header.biPlanes = 1;
|
84
|
-
header.biBitCount = self->
|
87
|
+
header.biBitCount = self->color_space.bpp();
|
85
88
|
header.biCompression = BI_RGB;
|
86
89
|
|
87
90
|
Win32::DC dc = hdc ? Win32::DC(hdc) : Win32::screen_dc();
|
88
91
|
|
89
92
|
HBITMAP hbmp = CreateDIBSection(
|
90
93
|
dc.handle(), &bmpinfo, DIB_RGB_COLORS, (void**) &self->pixels, NULL, 0);
|
91
|
-
if (!hbmp)
|
94
|
+
if (!hbmp)
|
95
|
+
rays_error(__FILE__, __LINE__);
|
92
96
|
|
93
97
|
self->memdc = Win32::MemoryDC(dc.handle(), Win32::Bitmap(hbmp, true));
|
94
|
-
if (!self->memdc)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
not_implemented_error(__FILE__, __LINE__);
|
98
|
+
if (!self->memdc)
|
99
|
+
rays_error(__FILE__, __LINE__);
|
100
|
+
|
101
|
+
size_t size = self->pitch * self->height;
|
102
|
+
if (pixels)
|
103
|
+
memcpy(self->pixels, pixels, size);
|
104
|
+
else if (clear_pixels)
|
105
|
+
memset(self->pixels, 0, size);
|
103
106
|
}
|
104
107
|
|
105
108
|
Bitmap
|
106
|
-
Bitmap_from (const Texture&
|
109
|
+
Bitmap_from (const Texture& tex)
|
107
110
|
{
|
111
|
+
if (!tex)
|
112
|
+
argument_error(__FILE__, __LINE__);
|
113
|
+
|
108
114
|
Bitmap bmp;
|
109
|
-
setup_bitmap(
|
115
|
+
setup_bitmap(
|
116
|
+
&bmp, tex.width(), tex.height(), tex.color_space(), NULL, false);
|
117
|
+
|
118
|
+
GLenum format, type;
|
119
|
+
ColorSpace_get_gl_format_and_type(&format, &type, tex.color_space());
|
120
|
+
|
121
|
+
FrameBuffer fb(tex);
|
122
|
+
FrameBufferBinder binder(fb.id());
|
123
|
+
|
124
|
+
for (int y = 0; y < bmp.height(); ++y)
|
125
|
+
{
|
126
|
+
GLvoid* ptr = (GLvoid*) bmp.at<uchar>(0, y);
|
127
|
+
glReadPixels(0, y, bmp.width(), 1, format, type, ptr);
|
128
|
+
}
|
129
|
+
|
110
130
|
return bmp;
|
111
131
|
}
|
112
132
|
|
@@ -126,8 +146,6 @@ namespace Rays
|
|
126
146
|
void
|
127
147
|
Bitmap_set_modified (Bitmap* bitmap, bool modified)
|
128
148
|
{
|
129
|
-
assert(bitmap);
|
130
|
-
|
131
149
|
bitmap->self->modified = modified;
|
132
150
|
}
|
133
151
|
|
@@ -137,16 +155,83 @@ namespace Rays
|
|
137
155
|
return bitmap.self->modified;
|
138
156
|
}
|
139
157
|
|
140
|
-
|
141
|
-
|
158
|
+
static const char*
|
159
|
+
get_ext (const char* path)
|
142
160
|
{
|
143
|
-
|
161
|
+
if (!path)
|
162
|
+
return NULL;
|
163
|
+
|
164
|
+
return strrchr(path, '.');
|
144
165
|
}
|
145
166
|
|
146
|
-
|
147
|
-
|
167
|
+
void
|
168
|
+
Bitmap_save (const Bitmap& bmp, const char* path)
|
148
169
|
{
|
149
|
-
|
170
|
+
const char* ext = get_ext(path);
|
171
|
+
if (!ext)
|
172
|
+
{
|
173
|
+
argument_error(
|
174
|
+
__FILE__, __LINE__, "invalid image file extension: '%s'", path);
|
175
|
+
}
|
176
|
+
|
177
|
+
const auto& cs = bmp.color_space();
|
178
|
+
size_t w = bmp.width();
|
179
|
+
size_t h = bmp.height();
|
180
|
+
size_t pitch = w * cs.Bpp();
|
181
|
+
|
182
|
+
std::unique_ptr<uchar[]> pixels(new uchar[h * pitch]);
|
183
|
+
for (size_t y = 0; y < h; ++y)
|
184
|
+
memcpy(pixels.get() + pitch * y, bmp.at<uchar>(0, y), pitch);
|
185
|
+
|
186
|
+
int ret = 0;
|
187
|
+
if (stricmp(ext, ".bmp") == 0)
|
188
|
+
ret = stbi_write_bmp(path, w, h, cs.Bpp(), pixels.get());
|
189
|
+
else
|
190
|
+
if (stricmp(ext, ".png") == 0)
|
191
|
+
ret = stbi_write_png(path, w, h, cs.Bpp(), pixels.get(), 0);
|
192
|
+
else
|
193
|
+
if (stricmp(ext, ".jpg") == 0 || stricmp(ext, ".jpeg") == 0)
|
194
|
+
ret = stbi_write_jpg(path, w, h, cs.Bpp(), pixels.get(), 90);
|
195
|
+
else
|
196
|
+
if (stricmp(ext, ".tga") == 0)
|
197
|
+
ret = stbi_write_tga(path, w, h, cs.Bpp(), pixels.get());
|
198
|
+
else
|
199
|
+
argument_error(__FILE__, __LINE__, "unknown image file type");
|
200
|
+
|
201
|
+
if (!ret)
|
202
|
+
rays_error(__FILE__, __LINE__, "failed to save: '%s'", path);
|
203
|
+
}
|
204
|
+
|
205
|
+
Bitmap
|
206
|
+
Bitmap_load (const char* path)
|
207
|
+
{
|
208
|
+
if (!path)
|
209
|
+
argument_error(__FILE__, __LINE__);
|
210
|
+
|
211
|
+
int w = 0, h = 0, Bpp = 0;
|
212
|
+
uchar* pixels = stbi_load(path, &w, &h, &Bpp, 0);
|
213
|
+
if (!pixels)
|
214
|
+
rays_error(__FILE__, __LINE__, "failed to load: '%s'", path);
|
215
|
+
|
216
|
+
ColorSpace cs;
|
217
|
+
switch (Bpp)
|
218
|
+
{
|
219
|
+
case 1: cs = GRAY_8; break;
|
220
|
+
case 3: cs = RGB_888; break;
|
221
|
+
case 4: cs = RGBA_8888; break;
|
222
|
+
default:
|
223
|
+
rays_error(__FILE__, __LINE__, "unsupported image file: '%s'", path);
|
224
|
+
}
|
225
|
+
|
226
|
+
Bitmap bmp(w, h, cs);
|
227
|
+
if (!bmp)
|
228
|
+
rays_error(__FILE__, __LINE__, "failed to create Bitmap object");
|
229
|
+
|
230
|
+
int pitch = Bpp * w;
|
231
|
+
for (int y = 0; y < h; ++y)
|
232
|
+
memcpy(bmp.at<uchar>(0, y), pixels + pitch * y, pitch);
|
233
|
+
|
234
|
+
return bmp;
|
150
235
|
}
|
151
236
|
|
152
237
|
|
@@ -154,31 +239,45 @@ namespace Rays
|
|
154
239
|
{
|
155
240
|
}
|
156
241
|
|
157
|
-
Bitmap::Bitmap (
|
242
|
+
Bitmap::Bitmap (
|
243
|
+
int width, int height, const ColorSpace& color_space, const void* pixels)
|
158
244
|
{
|
159
|
-
setup_bitmap(this, width, height,
|
245
|
+
setup_bitmap(this, width, height, color_space, pixels);
|
160
246
|
}
|
161
247
|
|
162
248
|
Bitmap::~Bitmap ()
|
163
249
|
{
|
164
250
|
}
|
165
251
|
|
252
|
+
Bitmap
|
253
|
+
Bitmap::dup () const
|
254
|
+
{
|
255
|
+
return Bitmap(width(), height(), color_space(), pixels());
|
256
|
+
}
|
257
|
+
|
166
258
|
int
|
167
259
|
Bitmap::width () const
|
168
260
|
{
|
261
|
+
if (!*this) return 0;
|
169
262
|
return self->width;
|
170
263
|
}
|
171
264
|
|
172
265
|
int
|
173
266
|
Bitmap::height () const
|
174
267
|
{
|
268
|
+
if (!*this) return 0;
|
175
269
|
return self->height;
|
176
270
|
}
|
177
271
|
|
178
272
|
const ColorSpace&
|
179
273
|
Bitmap::color_space () const
|
180
274
|
{
|
181
|
-
|
275
|
+
if (!*this)
|
276
|
+
{
|
277
|
+
static const ColorSpace UNKNOWN = COLORSPACE_UNKNOWN;
|
278
|
+
return UNKNOWN;
|
279
|
+
}
|
280
|
+
return self->color_space;
|
182
281
|
}
|
183
282
|
|
184
283
|
int
|
@@ -196,6 +295,7 @@ namespace Rays
|
|
196
295
|
void*
|
197
296
|
Bitmap::pixels ()
|
198
297
|
{
|
298
|
+
if (!*this) return NULL;
|
199
299
|
return self->pixels;
|
200
300
|
}
|
201
301
|
|
@@ -208,9 +308,11 @@ namespace Rays
|
|
208
308
|
Bitmap::operator bool () const
|
209
309
|
{
|
210
310
|
return
|
211
|
-
self &&
|
212
|
-
self->
|
213
|
-
self->
|
311
|
+
self->width > 0 &&
|
312
|
+
self->height > 0 &&
|
313
|
+
self->pitch > 0 &&
|
314
|
+
self->color_space &&
|
315
|
+
self->pixels;
|
214
316
|
}
|
215
317
|
|
216
318
|
bool
|