rays 0.4.0 → 0.5.0
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 +28 -8
- data/.doc/ext/rays/bounds.cpp +1 -1
- data/.doc/ext/rays/camera.cpp +5 -5
- data/.doc/ext/rays/color.cpp +1 -1
- data/.doc/ext/rays/color_space.cpp +10 -6
- data/.doc/ext/rays/font.cpp +116 -18
- data/.doc/ext/rays/image.cpp +27 -4
- data/.doc/ext/rays/matrix.cpp +1 -1
- data/.doc/ext/rays/painter.cpp +5 -5
- data/.doc/ext/rays/point.cpp +1 -1
- data/.doc/ext/rays/polygon.cpp +4 -4
- data/.doc/ext/rays/polyline.cpp +2 -2
- data/.doc/ext/rays/shader.cpp +2 -2
- data/.github/workflows/release-gem.yml +2 -49
- data/.github/workflows/tag.yml +5 -28
- data/.github/workflows/test.yml +1 -37
- data/ChangeLog.md +21 -0
- data/Gemfile.lock +13 -8
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +28 -8
- data/ext/rays/bounds.cpp +1 -1
- data/ext/rays/camera.cpp +5 -5
- data/ext/rays/color.cpp +1 -1
- data/ext/rays/color_space.cpp +10 -6
- data/ext/rays/defs.h +3 -3
- data/ext/rays/extconf.rb +6 -5
- data/ext/rays/font.cpp +120 -18
- data/ext/rays/image.cpp +27 -4
- data/ext/rays/matrix.cpp +1 -1
- data/ext/rays/painter.cpp +5 -5
- data/ext/rays/point.cpp +1 -1
- data/ext/rays/polygon.cpp +4 -4
- data/ext/rays/polyline.cpp +2 -2
- data/ext/rays/shader.cpp +2 -2
- data/include/rays/bitmap.h +2 -0
- data/include/rays/font.h +46 -4
- data/include/rays/image.h +9 -5
- data/include/rays/painter.h +3 -1
- data/include/rays/ruby/color_space.h +2 -0
- data/include/rays/shader.h +3 -0
- data/lib/rays/font.rb +4 -1
- data/lib/rays/image.rb +2 -0
- data/lib/rays/painter.rb +5 -5
- data/rays.gemspec +3 -3
- data/src/bitmap.cpp +107 -0
- data/src/color.cpp +17 -0
- data/src/font.cpp +121 -25
- data/src/font.h +7 -5
- data/src/image.cpp +102 -100
- data/src/ios/font.mm +77 -24
- data/src/opengl/color_space.cpp +4 -1
- data/src/opengl/painter.cpp +86 -18
- data/src/opengl/shader.cpp +15 -13
- data/src/opengl/texture.cpp +2 -2
- data/src/opengl/win32/opengl.cpp +17 -12
- data/src/osx/font.mm +77 -24
- data/src/painter.cpp +12 -12
- data/src/painter.h +5 -1
- data/src/polygon.cpp +21 -21
- data/src/polyline.cpp +4 -4
- data/src/sdl/bitmap.cpp +16 -10
- data/src/sdl/font.cpp +56 -50
- data/src/win32/bitmap.cpp +22 -13
- data/src/win32/font.cpp +43 -44
- data/src/win32/gdi.cpp +43 -46
- data/src/win32/gdi.h +6 -1
- data/src/win32/rays.cpp +18 -1
- data/test/test_bitmap.rb +28 -10
- data/test/test_font.rb +58 -0
- data/test/test_image.rb +29 -6
- data/test/test_painter.rb +39 -0
- metadata +8 -8
- data/.github/workflows/utils.rb +0 -127
data/src/osx/font.mm
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#import <ApplicationServices/ApplicationServices.h>
|
|
7
7
|
#import <AppKit/AppKit.h>
|
|
8
8
|
#include <xot/string.h>
|
|
9
|
+
#include <xot/util.h>
|
|
9
10
|
#include "rays/exception.h"
|
|
10
11
|
|
|
11
12
|
|
|
@@ -17,6 +18,8 @@ namespace Rays
|
|
|
17
18
|
|
|
18
19
|
typedef std::shared_ptr<const __CFAttributedString> CFAttributedStringPtr;
|
|
19
20
|
|
|
21
|
+
typedef std::shared_ptr<const __CTFontDescriptor> CTFontDescriptorPtr;
|
|
22
|
+
|
|
20
23
|
typedef std::shared_ptr<CGDataProvider> CGDataProviderPtr;
|
|
21
24
|
|
|
22
25
|
typedef std::shared_ptr<CGFont> CGFontPtr;
|
|
@@ -29,8 +32,6 @@ namespace Rays
|
|
|
29
32
|
|
|
30
33
|
CTFontRef font = NULL;
|
|
31
34
|
|
|
32
|
-
String path;
|
|
33
|
-
|
|
34
35
|
~Data ()
|
|
35
36
|
{
|
|
36
37
|
if (font)
|
|
@@ -43,6 +44,63 @@ namespace Rays
|
|
|
43
44
|
};// RawFont::Data
|
|
44
45
|
|
|
45
46
|
|
|
47
|
+
static const struct {int weight; CGFloat native;} NATIVE_WEIGHTS[] =
|
|
48
|
+
{
|
|
49
|
+
{Font::WEIGHT_MIN, -1.0},
|
|
50
|
+
{Font::WEIGHT_THIN, NSFontWeightUltraLight},
|
|
51
|
+
{Font::WEIGHT_EXTRALIGHT, NSFontWeightThin},
|
|
52
|
+
{Font::WEIGHT_LIGHT, NSFontWeightLight},
|
|
53
|
+
{Font::WEIGHT_NORMAL, NSFontWeightRegular},
|
|
54
|
+
{Font::WEIGHT_MEDIUM, NSFontWeightMedium},
|
|
55
|
+
{Font::WEIGHT_SEMIBOLD, NSFontWeightSemibold},
|
|
56
|
+
{Font::WEIGHT_BOLD, NSFontWeightBold},
|
|
57
|
+
{Font::WEIGHT_EXTRABOLD, NSFontWeightHeavy},
|
|
58
|
+
{Font::WEIGHT_BLACK, NSFontWeightBlack},
|
|
59
|
+
{Font::WEIGHT_MAX, 1.0}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
static CGFloat
|
|
63
|
+
to_native_weight (int weight)
|
|
64
|
+
{
|
|
65
|
+
size_t last = sizeof(NATIVE_WEIGHTS) / sizeof(NATIVE_WEIGHTS[0]) - 1;
|
|
66
|
+
for (size_t i = 1; i <= last; ++i)
|
|
67
|
+
{
|
|
68
|
+
if (weight > NATIVE_WEIGHTS[i].weight) continue;
|
|
69
|
+
|
|
70
|
+
const auto& lo = NATIVE_WEIGHTS[i - 1];
|
|
71
|
+
const auto& hi = NATIVE_WEIGHTS[i];
|
|
72
|
+
CGFloat t = (CGFloat) (weight - lo.weight) / (hi.weight - lo.weight);
|
|
73
|
+
return lo.native + (hi.native - lo.native) * t;
|
|
74
|
+
}
|
|
75
|
+
return NATIVE_WEIGHTS[last].native;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static CTFontRef
|
|
79
|
+
create_styled_font (CTFontRef base, coord size, int weight, bool italic)
|
|
80
|
+
{
|
|
81
|
+
Xot::CFStringPtr family(CTFontCopyFamilyName(base), Xot::safe_cfrelease);
|
|
82
|
+
if (!family) return NULL;
|
|
83
|
+
|
|
84
|
+
NSDictionary* traits =
|
|
85
|
+
@{
|
|
86
|
+
(id) kCTFontWeightTrait: @(to_native_weight(weight)),
|
|
87
|
+
(id) kCTFontSymbolicTrait: @(italic ? kCTFontTraitItalic : 0)
|
|
88
|
+
};
|
|
89
|
+
NSDictionary* attributes =
|
|
90
|
+
@{
|
|
91
|
+
(id) kCTFontFamilyNameAttribute: (__bridge NSString*) family.get(),
|
|
92
|
+
(id) kCTFontTraitsAttribute: traits
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
CTFontDescriptorPtr descriptor(
|
|
96
|
+
CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef) attributes),
|
|
97
|
+
Xot::safe_cfrelease);
|
|
98
|
+
if (!descriptor) return NULL;
|
|
99
|
+
|
|
100
|
+
return CTFontCreateWithFontDescriptor(descriptor.get(), size, NULL);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
46
104
|
static CTLinePtr
|
|
47
105
|
make_line (CTFontRef font, const char* str)
|
|
48
106
|
{
|
|
@@ -63,15 +121,15 @@ namespace Rays
|
|
|
63
121
|
CFDictionaryCreate(
|
|
64
122
|
NULL, (const void**) &keys, (const void**) &values, nkeys,
|
|
65
123
|
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks),
|
|
66
|
-
|
|
124
|
+
Xot::safe_cfrelease);
|
|
67
125
|
|
|
68
126
|
CFAttributedStringPtr attrstr(
|
|
69
127
|
CFAttributedStringCreate(NULL, Xot::String(str).to_cfstr().get(), attr.get()),
|
|
70
|
-
|
|
128
|
+
Xot::safe_cfrelease);
|
|
71
129
|
|
|
72
130
|
return CTLinePtr(
|
|
73
131
|
CTLineCreateWithAttributedString(attrstr.get()),
|
|
74
|
-
|
|
132
|
+
Xot::safe_cfrelease);
|
|
75
133
|
}
|
|
76
134
|
|
|
77
135
|
const FontFamilyMap&
|
|
@@ -118,7 +176,6 @@ namespace Rays
|
|
|
118
176
|
|
|
119
177
|
RawFont rawfont;
|
|
120
178
|
rawfont.self->font = ctfont;
|
|
121
|
-
rawfont.self->path = path;
|
|
122
179
|
return rawfont;
|
|
123
180
|
}
|
|
124
181
|
|
|
@@ -127,20 +184,23 @@ namespace Rays
|
|
|
127
184
|
{
|
|
128
185
|
}
|
|
129
186
|
|
|
130
|
-
RawFont::RawFont (const char* name, coord size)
|
|
187
|
+
RawFont::RawFont (const char* name, coord size, int weight, bool italic)
|
|
131
188
|
{
|
|
132
|
-
|
|
189
|
+
CTFontRef font = name
|
|
133
190
|
? CTFontCreateWithName(Xot::String(name).to_cfstr().get(), size, NULL)
|
|
134
191
|
: CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, NULL);
|
|
135
|
-
}
|
|
136
192
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
193
|
+
if (font && (weight != Font::WEIGHT_NORMAL || italic))
|
|
194
|
+
{
|
|
195
|
+
CTFontRef styled = create_styled_font(font, size, weight, italic);
|
|
196
|
+
if (styled)
|
|
197
|
+
{
|
|
198
|
+
CFRelease(font);
|
|
199
|
+
font = styled;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
self->font = font;
|
|
144
204
|
}
|
|
145
205
|
|
|
146
206
|
RawFont::~RawFont ()
|
|
@@ -189,17 +249,10 @@ namespace Rays
|
|
|
189
249
|
{
|
|
190
250
|
if (!*this) return "";
|
|
191
251
|
|
|
192
|
-
Xot::CFStringPtr str(CTFontCopyFullName(self->font),
|
|
252
|
+
Xot::CFStringPtr str(CTFontCopyFullName(self->font), Xot::safe_cfrelease);
|
|
193
253
|
return Xot::to_s(str);
|
|
194
254
|
}
|
|
195
255
|
|
|
196
|
-
coord
|
|
197
|
-
RawFont::size () const
|
|
198
|
-
{
|
|
199
|
-
if (!*this) return 0;
|
|
200
|
-
return CTFontGetSize(self->font);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
256
|
coord
|
|
204
257
|
RawFont::get_width (const char* str) const
|
|
205
258
|
{
|
data/src/painter.cpp
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include "rays/debug.h"
|
|
8
8
|
#include "polygon.h"
|
|
9
9
|
#include "image.h"
|
|
10
|
+
#include "font.h"
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
namespace Rays
|
|
@@ -741,21 +742,20 @@ namespace Rays
|
|
|
741
742
|
return self->state.clip;
|
|
742
743
|
}
|
|
743
744
|
|
|
744
|
-
static bool
|
|
745
|
-
has_same_font (const Font& font, const char* name, coord size, bool smooth)
|
|
746
|
-
{
|
|
747
|
-
return
|
|
748
|
-
font.size() == size &&
|
|
749
|
-
font.smooth() == smooth &&
|
|
750
|
-
font.name() == (name ? name : get_default_font().name().c_str());
|
|
751
|
-
}
|
|
752
|
-
|
|
753
745
|
void
|
|
754
|
-
Painter::set_font (
|
|
746
|
+
Painter::set_font (
|
|
747
|
+
const char* name, coord size, int weight, bool italic, bool smooth)
|
|
755
748
|
{
|
|
756
|
-
if (
|
|
749
|
+
if (weight < 0)
|
|
750
|
+
weight = Font::DEFAULT_WEIGHT;
|
|
751
|
+
|
|
752
|
+
if (Font_has_same_attributes(
|
|
753
|
+
self->state.font, name, size, weight, italic, smooth))
|
|
754
|
+
{
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
757
|
|
|
758
|
-
set_font(Font(name, size, smooth));
|
|
758
|
+
set_font(Font(name, size, weight, italic, smooth));
|
|
759
759
|
}
|
|
760
760
|
|
|
761
761
|
void
|
data/src/painter.h
CHANGED
|
@@ -179,7 +179,9 @@ namespace Rays
|
|
|
179
179
|
|
|
180
180
|
PAINTING = Xot::bit(1, Painter::FLAG_LAST),
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
CLEAR_DEPTH = Xot::bit(2, Painter::FLAG_LAST),
|
|
183
|
+
|
|
184
|
+
UNBATCHABLE_STATE_CHANGED = Xot::bit(3, Painter::FLAG_LAST),
|
|
183
185
|
|
|
184
186
|
};// Flag
|
|
185
187
|
|
|
@@ -237,6 +239,8 @@ namespace Rays
|
|
|
237
239
|
Painter* painter, const Font& font, const char* line, coord x, coord y,
|
|
238
240
|
coord width = 0, coord height = 0);
|
|
239
241
|
|
|
242
|
+
bool Painter_get_pixel (Color* color, Painter* painter, coord x, coord y);
|
|
243
|
+
|
|
240
244
|
|
|
241
245
|
}// Rays
|
|
242
246
|
|
data/src/polygon.cpp
CHANGED
|
@@ -147,18 +147,18 @@ namespace Rays
|
|
|
147
147
|
{
|
|
148
148
|
draw_polygon(
|
|
149
149
|
painter, MODE_TRIANGLES,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
ptexcoords ?
|
|
150
|
+
points.data(), points.size(),
|
|
151
|
+
indices.data(), indices.size(),
|
|
152
|
+
pcolors->data(),
|
|
153
|
+
ptexcoords ? ptexcoords->data() : NULL);
|
|
154
154
|
}
|
|
155
155
|
else
|
|
156
156
|
{
|
|
157
157
|
draw_polygon(
|
|
158
158
|
painter, MODE_TRIANGLES, color,
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
ptexcoords ?
|
|
159
|
+
points.data(), points.size(),
|
|
160
|
+
indices.data(), indices.size(),
|
|
161
|
+
ptexcoords ? ptexcoords->data() : NULL);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
|
|
@@ -227,7 +227,7 @@ namespace Rays
|
|
|
227
227
|
size_t index_offset = 0;
|
|
228
228
|
for (const auto& seg : segments)
|
|
229
229
|
{
|
|
230
|
-
Polyline polyline(
|
|
230
|
+
Polyline polyline(points.data() + seg.begin, seg.end - seg.begin);
|
|
231
231
|
if (!seg.hole)
|
|
232
232
|
{
|
|
233
233
|
triangulate(polylines, index_offset);
|
|
@@ -902,7 +902,7 @@ namespace Rays
|
|
|
902
902
|
points.emplace_back(make_ellipse_point(
|
|
903
903
|
x, y, width, height, radian_from, radian_to, nsegment, seg));
|
|
904
904
|
}
|
|
905
|
-
append(Polyline(
|
|
905
|
+
append(Polyline(points.data(), points.size(), true));
|
|
906
906
|
|
|
907
907
|
if (has_hole)
|
|
908
908
|
{
|
|
@@ -916,7 +916,7 @@ namespace Rays
|
|
|
916
916
|
hole_x, hole_y, hole_size.x, hole_size.y,
|
|
917
917
|
radian_from, radian_to, nsegment, seg));
|
|
918
918
|
}
|
|
919
|
-
append(Polyline(
|
|
919
|
+
append(Polyline(points.data(), points.size(), true, NULL, NULL, true));
|
|
920
920
|
}
|
|
921
921
|
}
|
|
922
922
|
|
|
@@ -961,7 +961,7 @@ namespace Rays
|
|
|
961
961
|
}
|
|
962
962
|
}
|
|
963
963
|
|
|
964
|
-
append(Polyline(
|
|
964
|
+
append(Polyline(points.data(), points.size(), true));
|
|
965
965
|
}
|
|
966
966
|
|
|
967
967
|
Point make_ellipse_point (
|
|
@@ -1040,7 +1040,7 @@ namespace Rays
|
|
|
1040
1040
|
array.reserve(size + 1);
|
|
1041
1041
|
array.insert(array.begin(), points, points + size);
|
|
1042
1042
|
array.emplace_back(points[0]);
|
|
1043
|
-
polygon->self->append(Polyline(
|
|
1043
|
+
polygon->self->append(Polyline(array.data(), array.size(), true, false));
|
|
1044
1044
|
}
|
|
1045
1045
|
#endif
|
|
1046
1046
|
return p;
|
|
@@ -1138,9 +1138,9 @@ namespace Rays
|
|
|
1138
1138
|
}
|
|
1139
1139
|
|
|
1140
1140
|
p.self->append(Polyline(
|
|
1141
|
-
|
|
1142
|
-
pcolors_ ?
|
|
1143
|
-
ptexcoords_ ?
|
|
1141
|
+
points_.data(), points_.size(), true,
|
|
1142
|
+
pcolors_ ? pcolors_->data() : NULL,
|
|
1143
|
+
ptexcoords_ ? ptexcoords_->data() : NULL));
|
|
1144
1144
|
if (size >= 4)
|
|
1145
1145
|
{
|
|
1146
1146
|
p.self->append(Polyline(
|
|
@@ -1297,9 +1297,9 @@ namespace Rays
|
|
|
1297
1297
|
}
|
|
1298
1298
|
|
|
1299
1299
|
p.self->append(Polyline(
|
|
1300
|
-
|
|
1301
|
-
pcolors_ ?
|
|
1302
|
-
ptexcoords_ ?
|
|
1300
|
+
points_.data(), points_.size(), true,
|
|
1301
|
+
pcolors_ ? pcolors_->data() : NULL,
|
|
1302
|
+
ptexcoords_ ? ptexcoords_->data() : NULL));
|
|
1303
1303
|
for (size_t i = 2; i < in_last; i += 2)
|
|
1304
1304
|
{
|
|
1305
1305
|
p.self->append(Polyline(
|
|
@@ -1410,7 +1410,7 @@ namespace Rays
|
|
|
1410
1410
|
}
|
|
1411
1411
|
}
|
|
1412
1412
|
|
|
1413
|
-
return create_line(
|
|
1413
|
+
return create_line(result.data(), result.size(), loop);
|
|
1414
1414
|
}
|
|
1415
1415
|
|
|
1416
1416
|
Polygon
|
|
@@ -1632,7 +1632,7 @@ namespace Rays
|
|
|
1632
1632
|
for (const auto& polyline : lhs)
|
|
1633
1633
|
polylines.emplace_back(polyline);
|
|
1634
1634
|
polylines.emplace_back(rhs);
|
|
1635
|
-
return Polygon(
|
|
1635
|
+
return Polygon(polylines.data(), polylines.size());
|
|
1636
1636
|
}
|
|
1637
1637
|
|
|
1638
1638
|
Polygon
|
|
@@ -1641,7 +1641,7 @@ namespace Rays
|
|
|
1641
1641
|
std::vector<Polyline> polylines;
|
|
1642
1642
|
for (const auto& polyline : lhs) polylines.emplace_back(polyline);
|
|
1643
1643
|
for (const auto& polyline : rhs) polylines.emplace_back(polyline);
|
|
1644
|
-
return Polygon(
|
|
1644
|
+
return Polygon(polylines.data(), polylines.size());
|
|
1645
1645
|
}
|
|
1646
1646
|
|
|
1647
1647
|
Polygon
|
data/src/polyline.cpp
CHANGED
|
@@ -129,7 +129,7 @@ namespace Rays
|
|
|
129
129
|
|
|
130
130
|
Polyline pl;
|
|
131
131
|
pl.self->reset(
|
|
132
|
-
|
|
132
|
+
cleaned.data(), NULL, NULL, cleaned.size(), loop, loop, hole,
|
|
133
133
|
[](const IntPoint& point) {return from_clipper(point);});
|
|
134
134
|
return pl;
|
|
135
135
|
}
|
|
@@ -224,21 +224,21 @@ namespace Rays
|
|
|
224
224
|
Polyline::points () const
|
|
225
225
|
{
|
|
226
226
|
const auto& v = self->points;
|
|
227
|
-
return !v.empty() ?
|
|
227
|
+
return !v.empty() ? v.data() : NULL;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
const Color*
|
|
231
231
|
Polyline::colors () const
|
|
232
232
|
{
|
|
233
233
|
const auto& pv = self->pcolors;
|
|
234
|
-
return pv && !pv->empty() ?
|
|
234
|
+
return pv && !pv->empty() ? pv->data() : NULL;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
const Coord3*
|
|
238
238
|
Polyline::texcoords () const
|
|
239
239
|
{
|
|
240
240
|
const auto& pv = self->ptexcoords;
|
|
241
|
-
return pv && !pv->empty() ?
|
|
241
|
+
return pv && !pv->empty() ? pv->data() : NULL;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
size_t
|
data/src/sdl/bitmap.cpp
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
7
7
|
#include <stb_image_write.h>
|
|
8
8
|
|
|
9
|
+
#include <memory>
|
|
9
10
|
#include <SDL.h>
|
|
10
11
|
#include <xot/util.h>
|
|
11
12
|
#include "rays/exception.h"
|
|
@@ -157,11 +158,11 @@ namespace Rays
|
|
|
157
158
|
const auto& cs = bitmap.color_space();
|
|
158
159
|
int w = bitmap.width();
|
|
159
160
|
int h = bitmap.height();
|
|
160
|
-
int
|
|
161
|
+
int row_size = w * cs.Bpp();
|
|
161
162
|
|
|
162
|
-
std::unique_ptr<uchar[]> pixels(new uchar[h *
|
|
163
|
+
std::unique_ptr<uchar[]> pixels(new uchar[h * row_size]);
|
|
163
164
|
for (int y = 0; y < h; ++y)
|
|
164
|
-
memcpy(pixels.get() +
|
|
165
|
+
memcpy(pixels.get() + row_size * y, bitmap.at<uchar>(0, y), row_size);
|
|
165
166
|
|
|
166
167
|
String ext = extension;
|
|
167
168
|
ext.downcase();
|
|
@@ -196,6 +197,10 @@ namespace Rays
|
|
|
196
197
|
p.end();
|
|
197
198
|
bmp = img.bitmap();
|
|
198
199
|
}
|
|
200
|
+
|
|
201
|
+
if (bmp.color_space().has_alpha())
|
|
202
|
+
bmp = bmp.dup(false);// stb_image_write expects straight alpha
|
|
203
|
+
|
|
199
204
|
save_bitmap(bmp, path);
|
|
200
205
|
}
|
|
201
206
|
|
|
@@ -206,16 +211,17 @@ namespace Rays
|
|
|
206
211
|
argument_error(__FILE__, __LINE__);
|
|
207
212
|
|
|
208
213
|
int w = 0, h = 0, Bpp = 0;
|
|
209
|
-
uchar
|
|
214
|
+
std::unique_ptr<uchar, decltype(&stbi_image_free)>
|
|
215
|
+
pixels(stbi_load(path, &w, &h, &Bpp, 0), stbi_image_free);
|
|
210
216
|
if (!pixels)
|
|
211
217
|
rays_error(__FILE__, __LINE__, "failed to load: '%s'", path);
|
|
212
218
|
|
|
213
219
|
ColorSpace cs;
|
|
214
220
|
switch (Bpp)
|
|
215
221
|
{
|
|
216
|
-
case 1: cs = GRAY_8;
|
|
217
|
-
case 3: cs = RGB_888;
|
|
218
|
-
case 4: cs = RGBA_8888; break
|
|
222
|
+
case 1: cs = GRAY_8; break;
|
|
223
|
+
case 3: cs = RGB_888; break;
|
|
224
|
+
case 4: cs = ColorSpace(RGBA_8888, false); break;// stb_image gives straight alpha
|
|
219
225
|
default:
|
|
220
226
|
rays_error(__FILE__, __LINE__, "unsupported image file: '%s'", path);
|
|
221
227
|
}
|
|
@@ -224,11 +230,11 @@ namespace Rays
|
|
|
224
230
|
if (!bmp)
|
|
225
231
|
rays_error(__FILE__, __LINE__, "failed to create Bitmap object");
|
|
226
232
|
|
|
227
|
-
int
|
|
233
|
+
int size = Bpp * w;
|
|
228
234
|
for (int y = 0; y < h; ++y)
|
|
229
|
-
memcpy(bmp.at<uchar>(0, y), pixels +
|
|
235
|
+
memcpy(bmp.at<uchar>(0, y), pixels.get() + size * y, size);
|
|
230
236
|
|
|
231
|
-
return bmp;
|
|
237
|
+
return cs.has_alpha() ? bmp.dup(true) : bmp;
|
|
232
238
|
}
|
|
233
239
|
|
|
234
240
|
|