1 #include "lua/internal.hpp"
2 #include "core/framebuffer.hpp"
3 #include "library/framebuffer.hpp"
4 #include "library/png-codec.hpp"
5 #include "library/string.hpp"
6 #include "library/zip.hpp"
7 #include "lua/bitmap.hpp"
8 #include "library/threadtypes.hpp"
12 lua_bitmap::lua_bitmap(lua_state
& L
, uint32_t w
, uint32_t h
)
16 pixels
.resize(width
* height
);
17 memset(&pixels
[0], 0, width
* height
);
20 lua_bitmap::~lua_bitmap()
22 render_kill_request(this);
25 std::string
lua_bitmap::print()
27 return (stringfmt() << width
<< "*" << height
).str();
30 lua_dbitmap::lua_dbitmap(lua_state
& L
, uint32_t w
, uint32_t h
)
34 pixels
.resize(width
* height
);
37 lua_dbitmap::~lua_dbitmap()
39 render_kill_request(this);
42 std::string
lua_dbitmap::print()
44 return (stringfmt() << width
<< "*" << height
).str();
47 lua_palette::lua_palette(lua_state
& L
)
51 lua_palette::~lua_palette()
55 std::string
lua_palette::print()
57 size_t s
= colors
.size();
58 return (stringfmt() << s
<< " " << ((s
!= 1) ? "colors" : "color")).str();
61 std::vector
<char> lua_dbitmap::save_png() const
63 png_encodedable_image img
;
66 img
.has_palette
= false;
67 img
.has_alpha
= false;
68 img
.data
.resize(width
* height
);
69 for(size_t i
= 0; i
< width
* height
; i
++) {
70 const premultiplied_color
& c
= pixels
[i
];
73 img
.data
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
75 std::ostringstream tmp1
;
77 std::string tmp2
= tmp1
.str();
78 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
81 std::vector
<char> lua_bitmap::save_png(const lua_palette
& pal
) const
83 png_encodedable_image img
;
86 img
.has_palette
= true;
87 img
.has_alpha
= false;
88 img
.data
.resize(width
* height
);
89 img
.palette
.resize(pal
.colors
.size());
90 for(size_t i
= 0; i
< width
* height
; i
++) {
91 img
.data
[i
] = pixels
[i
];
93 for(size_t i
= 0; i
< pal
.colors
.size(); i
++) {
94 const premultiplied_color
& c
= pal
.colors
[i
];
97 img
.palette
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
99 std::ostringstream tmp1
;
101 std::string tmp2
= tmp1
.str();
102 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
107 const char* base64chars
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
109 struct render_object_bitmap
: public render_object
111 render_object_bitmap(int32_t _x
, int32_t _y
, lua_obj_pin
<lua_bitmap
> _bitmap
,
112 lua_obj_pin
<lua_palette
> _palette
) throw()
120 render_object_bitmap(int32_t _x
, int32_t _y
, lua_obj_pin
<lua_dbitmap
> _bitmap
) throw()
127 ~render_object_bitmap() throw()
131 bool kill_request(void* obj
) throw()
133 return kill_request_ifeq(p
.object(), obj
) ||
134 kill_request_ifeq(b
.object(), obj
) ||
135 kill_request_ifeq(b2
.object(), obj
);
138 template<bool T
> void composite_op(struct framebuffer
<T
>& scr
) throw()
141 p
->palette_mutex
.lock();
142 uint32_t originx
= scr
.get_origin_x();
143 uint32_t originy
= scr
.get_origin_y();
146 premultiplied_color
* palette
;
148 palette
= &p
->colors
[0];
149 for(auto& c
: p
->colors
)
151 pallim
= p
->colors
.size();
155 for(auto& c
: b2
->pixels
)
165 clip_range(originx
, scr
.get_width(), x
, xmin
, xmax
);
166 clip_range(originy
, scr
.get_height(), y
, ymin
, ymax
);
167 for(int32_t r
= ymin
; r
< ymax
; r
++) {
168 typename framebuffer
<T
>::element_t
* rptr
= scr
.rowptr(y
+ r
+ originy
);
169 size_t eptr
= x
+ xmin
+ originx
;
171 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++) {
172 uint16_t i
= b
->pixels
[r
* b
->width
+ c
];
174 palette
[i
].apply(rptr
[eptr
]);
177 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++)
178 b2
->pixels
[r
* b2
->width
+ c
].apply(rptr
[eptr
]);
181 p
->palette_mutex
.unlock();
183 void operator()(struct framebuffer
<false>& x
) throw() { composite_op(x
); }
184 void operator()(struct framebuffer
<true>& x
) throw() { composite_op(x
); }
185 void clone(render_queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
189 lua_obj_pin
<lua_bitmap
> b
;
190 lua_obj_pin
<lua_dbitmap
> b2
;
191 lua_obj_pin
<lua_palette
> p
;
194 function_ptr_luafun
gui_bitmap(lua_func_misc
, "gui.bitmap_draw", [](lua_state
& L
, const std::string
& fname
)
198 int32_t x
= L
.get_numeric_argument
<int32_t>(1, fname
.c_str());
199 int32_t y
= L
.get_numeric_argument
<int32_t>(2, fname
.c_str());
200 if(lua_class
<lua_bitmap
>::is(L
, 3)) {
201 lua_class
<lua_bitmap
>::get(L
, 3, fname
.c_str());
202 lua_class
<lua_palette
>::get(L
, 4, fname
.c_str());
203 auto b
= lua_class
<lua_bitmap
>::pin(L
, 3, fname
.c_str());
204 auto p
= lua_class
<lua_palette
>::pin(L
, 4, fname
.c_str());
205 lua_render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
, p
);
206 } else if(lua_class
<lua_dbitmap
>::is(L
, 3)) {
207 lua_class
<lua_dbitmap
>::get(L
, 3, fname
.c_str());
208 auto b
= lua_class
<lua_dbitmap
>::pin(L
, 3, fname
.c_str());
209 lua_render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
);
211 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 3 for gui.bitmap_draw.");
215 function_ptr_luafun
gui_cpalette(lua_func_misc
, "gui.palette_new", [](lua_state
& L
, const std::string
& fname
)
217 lua_class
<lua_palette
>::create(L
);
221 function_ptr_luafun
gui_cbitmap(lua_func_misc
, "gui.bitmap_new", [](lua_state
& L
, const std::string
& fname
)
223 uint32_t w
= L
.get_numeric_argument
<uint32_t>(1, fname
.c_str());
224 uint32_t h
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
225 bool d
= L
.get_bool(3, fname
.c_str());
228 L
.get_numeric_argument
<int64_t>(4, c
, fname
.c_str());
229 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::create(L
, w
, h
);
230 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
231 b
->pixels
[i
] = premultiplied_color(c
);
234 L
.get_numeric_argument
<uint16_t>(4, c
, fname
.c_str());
235 lua_bitmap
* b
= lua_class
<lua_bitmap
>::create(L
, w
, h
);
236 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
242 function_ptr_luafun
gui_epalette(lua_func_misc
, "gui.palette_set", [](lua_state
& L
, const std::string
& fname
)
244 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, 1, fname
.c_str());
245 uint16_t c
= L
.get_numeric_argument
<uint16_t>(2, fname
.c_str());
246 int64_t nval
= L
.get_numeric_argument
<int64_t>(3, fname
.c_str());
247 premultiplied_color
nc(nval
);
248 //The mutex lock protects only the internals of colors array.
249 if(p
->colors
.size() <= c
) {
250 p
->palette_mutex
.lock();
251 p
->colors
.resize(static_cast<uint32_t>(c
) + 1);
252 p
->palette_mutex
.unlock();
258 function_ptr_luafun
pset_bitmap(lua_func_misc
, "gui.bitmap_pset", [](lua_state
& L
, const std::string
& fname
)
260 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
261 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
262 if(lua_class
<lua_bitmap
>::is(L
, 1)) {
263 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, 1, fname
.c_str());
264 uint16_t c
= L
.get_numeric_argument
<uint16_t>(4, fname
.c_str());
265 if(x
>= b
->width
|| y
>= b
->height
)
267 b
->pixels
[y
* b
->width
+ x
] = c
;
268 } else if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
269 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
270 int64_t c
= L
.get_numeric_argument
<int64_t>(4, fname
.c_str());
271 if(x
>= b
->width
|| y
>= b
->height
)
273 b
->pixels
[y
* b
->width
+ x
] = premultiplied_color(c
);
275 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_pset.");
279 inline int64_t demultiply_color(const premultiplied_color
& c
)
284 return c
.orig
| ((uint32_t)(256 - c
.origa
) << 24);
287 function_ptr_luafun
pget_bitmap(lua_func_misc
, "gui.bitmap_pget", [](lua_state
& L
, const std::string
& fname
)
289 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
290 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
291 if(lua_class
<lua_bitmap
>::is(L
, 1)) {
292 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, 1, fname
.c_str());
293 if(x
>= b
->width
|| y
>= b
->height
)
295 L
.pushnumber(b
->pixels
[y
* b
->width
+ x
]);
296 } else if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
297 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
298 if(x
>= b
->width
|| y
>= b
->height
)
300 L
.pushnumber(demultiply_color(b
->pixels
[y
* b
->width
+ x
]));
302 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_pget.");
306 function_ptr_luafun
size_bitmap(lua_func_misc
, "gui.bitmap_size", [](lua_state
& L
, const std::string
& fname
)
308 if(lua_class
<lua_bitmap
>::is(L
, 1)) {
309 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, 1, fname
.c_str());
310 L
.pushnumber(b
->width
);
311 L
.pushnumber(b
->height
);
312 } else if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
313 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
314 L
.pushnumber(b
->width
);
315 L
.pushnumber(b
->height
);
317 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_size.");
323 bool iskey(uint16_t& c
) const { return false; }
324 bool iskey(premultiplied_color
& c
) const { return false; }
327 struct colorkey_direct
329 colorkey_direct(uint64_t _ck
)
331 premultiplied_color
c(_ck
);
335 bool iskey(premultiplied_color
& c
) const { return (c
.orig
== ck
&& c
.origa
== cka
); }
340 struct colorkey_palette
342 colorkey_palette(uint64_t _ck
) { ck
= _ck
; }
343 bool iskey(uint16_t& c
) const { return (c
== ck
); }
347 template<class colorkey
> struct srcdest_direct
349 srcdest_direct(lua_dbitmap
& dest
, lua_dbitmap
& src
, const colorkey
& _ckey
)
352 darray
= &dest
.pixels
[0];
353 sarray
= &src
.pixels
[0];
355 sheight
= src
.height
;
357 dheight
= dest
.height
;
359 void copy(size_t didx
, size_t sidx
)
361 premultiplied_color c
= sarray
[sidx
];
365 size_t swidth
, sheight
, dwidth
, dheight
;
367 premultiplied_color
* sarray
;
368 premultiplied_color
* darray
;
369 const colorkey
& ckey
;
372 template<class colorkey
> struct srcdest_palette
374 srcdest_palette(lua_bitmap
& dest
, lua_bitmap
& src
, const colorkey
& _ckey
)
377 darray
= &dest
.pixels
[0];
378 sarray
= &src
.pixels
[0];
380 sheight
= src
.height
;
382 dheight
= dest
.height
;
384 void copy(size_t didx
, size_t sidx
)
386 uint16_t c
= sarray
[sidx
];
390 size_t swidth
, sheight
, dwidth
, dheight
;
394 const colorkey
& ckey
;
397 template<class colorkey
> struct srcdest_paletted
399 typedef premultiplied_color ptype
;
400 srcdest_paletted(lua_dbitmap
& dest
, lua_bitmap
& src
, lua_palette
& palette
, const colorkey
& _ckey
)
401 : ckey(_ckey
), transparent(-1)
403 darray
= &dest
.pixels
[0];
404 sarray
= &src
.pixels
[0];
405 limit
= palette
.colors
.size();
406 pal
= &palette
.colors
[0];
408 sheight
= src
.height
;
410 dheight
= dest
.height
;
412 void copy(size_t didx
, size_t sidx
)
414 uint16_t c
= sarray
[sidx
];
416 darray
[didx
] = (c
< limit
) ? pal
[c
] : transparent
;
418 size_t swidth
, sheight
, dwidth
, dheight
;
421 premultiplied_color
* darray
;
422 premultiplied_color
* pal
;
424 premultiplied_color transparent
;
425 const colorkey
& ckey
;
428 template<class srcdest
>
429 void blit(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
)
431 while((dx
+ w
> sd
.dwidth
|| sx
+ w
> sd
.swidth
) && w
> 0)
433 while((dy
+ h
> sd
.dheight
|| sy
+ h
> sd
.sheight
) && h
> 0)
435 size_t sidx
= sy
* sd
.swidth
+ sx
;
436 size_t didx
= dy
* sd
.dwidth
+ dx
;
437 size_t srskip
= sd
.swidth
- w
;
438 size_t drskip
= sd
.dwidth
- w
;
439 for(uint32_t j
= 0; j
< h
; j
++) {
440 for(uint32_t i
= 0; i
< w
; i
++) {
450 function_ptr_luafun
blit_bitmap(lua_func_misc
, "gui.bitmap_blit", [](lua_state
& L
, const std::string
& fname
)
455 bool dst_d
= lua_class
<lua_dbitmap
>::is(L
, dsts
= slot
);
456 bool dst_p
= lua_class
<lua_bitmap
>::is(L
, slot
++);
458 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_blit");
459 uint32_t dx
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
460 uint32_t dy
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
461 bool src_d
= lua_class
<lua_dbitmap
>::is(L
, srcs
= slot
);
462 bool src_p
= lua_class
<lua_bitmap
>::is(L
, slot
++);
464 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 4 for gui.bitmap_blit");
466 slot
++; //Reserve slot 5 for palette.
467 uint32_t sx
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
468 uint32_t sy
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
469 uint32_t w
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
470 uint32_t h
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
471 int64_t ck
= 0x100000000ULL
;
472 L
.get_numeric_argument
<int64_t>(slot
++, ck
, fname
.c_str());
475 lua_dbitmap
* db
= lua_class
<lua_dbitmap
>::get(L
, dsts
, fname
.c_str());
476 lua_dbitmap
* sb
= lua_class
<lua_dbitmap
>::get(L
, srcs
, fname
.c_str());
477 if(ck
== 0x100000000ULL
)
478 blit(srcdest_direct
<colorkey_none
>(*db
, *sb
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
);
480 blit(srcdest_direct
<colorkey_direct
>(*db
, *sb
, colorkey_direct(ck
)), dx
, dy
, sx
, sy
, w
,
482 } else if(dst_p
&& src_p
) {
483 lua_bitmap
* db
= lua_class
<lua_bitmap
>::get(L
, dsts
, fname
.c_str());
484 lua_bitmap
* sb
= lua_class
<lua_bitmap
>::get(L
, srcs
, fname
.c_str());
486 blit(srcdest_palette
<colorkey_none
>(*db
, *sb
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
);
488 blit(srcdest_palette
<colorkey_palette
>(*db
, *sb
, colorkey_palette(ck
)), dx
, dy
, sx
, sy
,
490 } else if(dst_d
&& src_p
) {
491 lua_dbitmap
* db
= lua_class
<lua_dbitmap
>::get(L
, dsts
, fname
.c_str());
492 lua_bitmap
* sb
= lua_class
<lua_bitmap
>::get(L
, srcs
, fname
.c_str());
493 lua_palette
* pal
= lua_class
<lua_palette
>::get(L
, srcs
+ 1, fname
.c_str());
495 blit(srcdest_paletted
<colorkey_none
>(*db
, *sb
, *pal
, colorkey_none()), dx
, dy
, sx
, sy
,
498 blit(srcdest_paletted
<colorkey_palette
>(*db
, *sb
, *pal
, colorkey_palette(ck
)), dx
, dy
,
501 throw std::runtime_error("If parameter 1 to gui.bitmap_blit is paletted, parameter 4 must be "
506 int bitmap_load_fn(lua_state
& L
, std::function
<lua_loaded_bitmap()> src
)
511 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
512 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
513 b
->pixels
[i
] = premultiplied_color(bitmap
.bitmap
[i
]);
516 lua_bitmap
* b
= lua_class
<lua_bitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
517 lua_palette
* p
= lua_class
<lua_palette
>::create(L
);
518 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
519 b
->pixels
[i
] = bitmap
.bitmap
[i
];
520 p
->colors
.resize(bitmap
.palette
.size());
521 for(size_t i
= 0; i
< bitmap
.palette
.size(); i
++)
522 p
->colors
[i
] = premultiplied_color(bitmap
.palette
[i
]);
527 function_ptr_luafun
gui_loadbitmap(lua_func_misc
, "gui.bitmap_load", [](lua_state
& L
,
528 const std::string
& fname
) -> int {
530 std::string name
= L
.get_string(1, fname
.c_str());
531 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
532 name2
= L
.get_string(2, fname
.c_str());
533 return bitmap_load_fn(L
, [&name
, &name2
]() -> lua_loaded_bitmap
{
534 std::string name3
= resolve_file_relative(name
, name2
);
535 return lua_loaded_bitmap::load(name3
);
539 function_ptr_luafun
gui_loadbitmap2(lua_func_misc
, "gui.bitmap_load_str", [](lua_state
& L
,
540 const std::string
& fname
) -> int {
541 std::string contents
= L
.get_string(1, fname
.c_str());
542 return bitmap_load_fn(L
, [&contents
]() -> lua_loaded_bitmap
{
543 std::istringstream
strm(contents
);
544 return lua_loaded_bitmap::load(strm
);
548 inline int64_t mangle_color(uint32_t c
)
553 return ((256 - (c
>> 24) - (c
>> 31)) << 24) | (c
& 0xFFFFFF);
556 int base64val(char ch
)
558 if(ch
>= 'A' && ch
<= 'Z')
560 if(ch
>= 'a' && ch
<= 'z')
562 if(ch
>= '0' && ch
<= '9')
568 if(ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n')
575 std::string
base64_encode(const std::string
& str
)
577 std::ostringstream x
;
581 mem
= (mem
<< 8) + (unsigned char)i
;
583 uint8_t c1
= (mem
>> 18) & 0x3F;
584 uint8_t c2
= (mem
>> 12) & 0x3F;
585 uint8_t c3
= (mem
>> 6) & 0x3F;
586 uint8_t c4
= mem
& 0x3F;
587 x
<< base64chars
[c1
];
588 x
<< base64chars
[c2
];
589 x
<< base64chars
[c3
];
590 x
<< base64chars
[c4
];
596 uint8_t c1
= (mem
>> 10) & 0x3F;
597 uint8_t c2
= (mem
>> 4) & 0x3F;
598 uint8_t c3
= (mem
<< 2) & 0x3F;
599 x
<< base64chars
[c1
];
600 x
<< base64chars
[c2
];
601 x
<< base64chars
[c3
];
605 uint8_t c1
= (mem
>> 2) & 0x3F;
606 uint8_t c2
= (mem
<< 4) & 0x3F;
607 x
<< base64chars
[c1
];
608 x
<< base64chars
[c2
];
614 std::string
base64_decode(const std::string
& str
)
618 uint32_t memsize
= 1;
620 std::ostringstream x
;
622 int v
= base64val(i
);
625 posmod
= (posmod
+ 1) & 3;
626 if(v
== -2 && (posmod
== 1 || posmod
== 2))
627 throw std::runtime_error("Invalid Base64");
633 throw std::runtime_error("Invalid Base64");
634 memory
= memory
* 64 + v
;
635 memsize
= memsize
* 64;
638 x
<< static_cast<uint8_t>(memory
/ memsize
);
646 int bitmap_load_png_fn(lua_state
& L
, T
& src
)
648 png_decoded_image
img(src
);
649 if(img
.has_palette
) {
650 lua_bitmap
* b
= lua_class
<lua_bitmap
>::create(L
, img
.width
, img
.height
);
651 lua_palette
* p
= lua_class
<lua_palette
>::create(L
);
652 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
653 b
->pixels
[i
] = img
.data
[i
];
654 p
->colors
.resize(img
.palette
.size());
655 for(size_t i
= 0; i
< img
.palette
.size(); i
++)
656 p
->colors
[i
] = premultiplied_color(mangle_color(img
.palette
[i
]));
659 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::create(L
, img
.width
, img
.height
);
660 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
661 b
->pixels
[i
] = premultiplied_color(mangle_color(img
.data
[i
]));
666 void bitmap_save_png_fn(lua_state
& L
, std::function
<void(const std::vector
<char>& buf
)> fn
, int index
,
667 const std::string
& fname
)
669 std::vector
<char> buf
;
670 if(lua_class
<lua_bitmap
>::is(L
, index
)) {
671 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, index
, fname
.c_str());
672 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, index
+ 1, fname
.c_str());
673 buf
= b
->save_png(*p
);
674 } else if(lua_class
<lua_dbitmap
>::is(L
, index
)) {
675 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, index
, fname
.c_str());
678 (stringfmt() << "Expected BITMAP or DBITMAP as argument " << index
679 << " for gui.bitmap_save_png.").throwex();
684 function_ptr_luafun
gui_loadbitmappng(lua_func_misc
, "gui.bitmap_load_png", [](lua_state
& L
,
685 const std::string
& fname
) -> int {
687 std::string name
= L
.get_string(1, fname
.c_str());
688 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
689 name2
= L
.get_string(2, fname
.c_str());
690 std::string filename
= resolve_file_relative(name
, name2
);
691 return bitmap_load_png_fn(L
, filename
);
694 function_ptr_luafun
gui_loadbitmappng2(lua_func_misc
, "gui.bitmap_load_png_str", [](lua_state
& L
,
695 const std::string
& fname
) -> int {
696 std::string contents
= base64_decode(L
.get_string(1, fname
.c_str()));
697 std::istringstream
strm(contents
);
698 return bitmap_load_png_fn(L
, strm
);
701 function_ptr_luafun
gui_savebitmappng(lua_func_misc
, "gui.bitmap_save_png", [](lua_state
& L
,
702 const std::string
& fname
) -> int {
704 std::string name
, name2
;
705 if(L
.type(index
) == LUA_TSTRING
) {
706 name
= L
.get_string(index
, fname
.c_str());
709 if(L
.type(index
) == LUA_TSTRING
) {
710 name2
= L
.get_string(index
, fname
.c_str());
714 std::string filename
= resolve_file_relative(name
, name2
);
715 std::ofstream
strm(filename
, std::ios::binary
);
717 throw std::runtime_error("Can't open output file");
718 bitmap_save_png_fn(L
, [&strm
](const std::vector
<char>& x
) { strm
.write(&x
[0], x
.size()); },
721 throw std::runtime_error("Can't write output file");
724 std::ostringstream strm
;
725 bitmap_save_png_fn(L
, [&strm
](const std::vector
<char>& x
) { strm
.write(&x
[0], x
.size()); }, 1,
727 L
.pushlstring(base64_encode(strm
.str()));
732 int bitmap_palette_fn(lua_state
& L
, std::istream
& s
)
734 lua_palette
* p
= lua_class
<lua_palette
>::create(L
);
737 std::getline(s
, line
);
740 if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
741 int64_t cr
, cg
, cb
, ca
;
742 cr
= parse_value
<uint8_t>(r
[1]);
743 cg
= parse_value
<uint8_t>(r
[2]);
744 cb
= parse_value
<uint8_t>(r
[3]);
745 ca
= 256 - parse_value
<uint16_t>(r
[4]);
748 p
->colors
.push_back(premultiplied_color(-1));
750 p
->colors
.push_back(premultiplied_color((ca
<< 24) | (cr
<< 16)
752 } else if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
754 cr
= parse_value
<uint8_t>(r
[1]);
755 cg
= parse_value
<uint8_t>(r
[2]);
756 cb
= parse_value
<uint8_t>(r
[3]);
757 p
->colors
.push_back(premultiplied_color((cr
<< 16) | (cg
<< 8) | cb
));
758 } else if(regex_match("[ \t]*transparent[ \t]*", line
)) {
759 p
->colors
.push_back(premultiplied_color(-1));
760 } else if(!regex_match("[ \t]*(#.*)?", line
))
761 throw std::runtime_error("Invalid line format (" + line
+ ")");
766 function_ptr_luafun
gui_loadpalette(lua_func_misc
, "gui.bitmap_load_pal", [](lua_state
& L
,
767 const std::string
& fname
) -> int {
769 std::string name
= L
.get_string(1, fname
.c_str());
770 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
771 name2
= L
.get_string(2, fname
.c_str());
772 std::istream
& s
= open_file_relative(name
, name2
);
774 int r
= bitmap_palette_fn(L
, s
);
783 function_ptr_luafun
gui_loadpalette2(lua_func_misc
, "gui.bitmap_load_pal_str", [](lua_state
& L
,
784 const std::string
& fname
) -> int {
785 std::string content
= L
.get_string(1, fname
.c_str());
786 std::istringstream
s(content
);
787 return bitmap_palette_fn(L
, s
);
790 function_ptr_luafun
gui_dpalette(lua_func_misc
, "gui.palette_debug", [](lua_state
& L
,
791 const std::string
& fname
) -> int {
792 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, 1, fname
.c_str());
794 for(auto c
: p
->colors
)
795 messages
<< "Color #" << (i
++) << ": " << c
.orig
<< ":" << c
.origa
<< std::endl
;
799 inline premultiplied_color
tadjust(premultiplied_color c
, uint16_t adj
)
801 uint32_t rgb
= c
.orig
;
802 uint32_t a
= c
.origa
;
807 return premultiplied_color(-1);
809 return premultiplied_color(rgb
| ((uint32_t)(256 - a
) << 24));
812 function_ptr_luafun
adjust_trans(lua_func_misc
, "gui.adjust_transparency", [](lua_state
& L
,
813 const std::string
& fname
) -> int {
814 uint16_t tadj
= L
.get_numeric_argument
<uint16_t>(2, fname
.c_str());
815 if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
816 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
817 for(auto& c
: b
->pixels
)
818 c
= tadjust(c
, tadj
);
819 } else if(lua_class
<lua_palette
>::is(L
, 1)) {
820 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, 1, fname
.c_str());
821 for(auto& c
: p
->colors
)
822 c
= tadjust(c
, tadj
);
824 throw std::runtime_error("Expected BITMAP or PALETTE as argument 1 for "
825 "gui.adjust_transparency");
831 DECLARE_LUACLASS(lua_palette
, "PALETTE");
832 DECLARE_LUACLASS(lua_bitmap
, "BITMAP");
833 DECLARE_LUACLASS(lua_dbitmap
, "DBITMAP");