30 #include "lv_common.h"
32 #include "private/lv_video_private.hpp"
33 #include "private/lv_video_blit.hpp"
34 #include "private/lv_video_convert.hpp"
35 #include "private/lv_video_fill.hpp"
36 #include "private/lv_video_transform.hpp"
37 #include "private/lv_video_bmp.hpp"
38 #include "private/lv_video_png.hpp"
60 , buffer (Buffer::create ())
70 void Video::Impl::set_buffer (
void* ptr)
72 if (buffer->is_allocated ()) {
74 "Cannot set a new pixel buffer for Video objects "
75 "with allocated buffers");
79 buffer->set_data (ptr);
83 if (buffer->get_data ()) {
84 pixel_rows.resize (height);
85 precompute_row_table ();
89 void Video::Impl::precompute_row_table ()
91 auto ptr =
static_cast<uint8_t *
> (buffer->get_data ());
93 for (
int y = 0; y < height; y++, ptr += pitch)
114 self->set_dimension (width, height);
117 self->allocate_buffer ();
124 visual_return_val_if_fail (!area.
empty (),
nullptr);
128 auto vrect = src->get_extents ();
130 if (!vrect.contains (area))
133 "provided area (%d, %d, %d, %d) is not contained by "
134 "source area (%d, %d, %d, %d)",
135 area.x, area.y, area.width, area.height,
136 vrect.x, vrect.y, vrect.width, vrect.height);
140 self->m_impl->extents = area;
141 self->m_impl->parent = src;
143 self->set_attrs (area.width, area.height, src->m_impl->pitch, src->m_impl->depth);
144 self->m_impl->set_buffer (src->get_pixel_ptr (area.x, area.y));
146 self->m_impl->compose_type = src->m_impl->compose_type;
147 self->m_impl->compose_func = src->m_impl->compose_func;
149 self->m_impl->colorkey = src->m_impl->colorkey;
150 self->m_impl->alpha = src->m_impl->alpha;
152 self->set_palette (src->m_impl->palette);
157 VideoPtr Video::create_sub (Rect
const& drect, VideoConstPtr
const& src, Rect
const& srect)
159 auto sbound = src->m_impl->extents;
160 auto rsrect = drect.clip (sbound.clip (srect));
162 return create_sub (src, rsrect);
165 VideoPtr Video::wrap (
void *data,
bool owner,
int width,
int height,
VisVideoDepth depth,
int pitch)
172 VideoPtr
self (
new Video,
false);
175 self->set_dimension (width, height, pitch);
176 self->m_impl->set_buffer (data);
181 VideoPtr Video::create_from_file (std::string
const& path)
183 std::ifstream stream (path);
188 return create_from_stream (stream);
191 VideoPtr Video::create_from_stream (std::istream& input)
193 auto image = bitmap_load_bmp (input);
198 image = bitmap_load_png (input);
212 auto self = create (width, height, depth);
213 self->scale_depth (src, scale_method);
223 void Video::free_buffer ()
225 m_impl->pixel_rows.clear ();
227 m_impl->buffer->set (
nullptr, 0);
230 bool Video::allocate_buffer ()
232 visual_return_val_if_fail (m_impl->buffer,
false);
236 if (m_impl->buffer->is_allocated ()) {
244 if (get_size () == 0) {
245 m_impl->buffer->set_data (
nullptr);
249 m_impl->buffer->allocate (get_size ());
251 m_impl->pixel_rows.resize (m_impl->height);
252 m_impl->precompute_row_table ();
257 bool Video::has_allocated_buffer ()
const
259 return m_impl->buffer->is_allocated ();
264 set_depth (src->m_impl->depth);
265 set_dimension (src->m_impl->width, src->m_impl->height);
266 set_pitch (src->m_impl->pitch);
271 if (!compare_attrs_ignore_pitch (src))
274 if (m_impl->pitch != src->m_impl->pitch)
282 if (m_impl->depth != src->m_impl->depth)
285 if (m_impl->width != src->m_impl->width)
288 if (m_impl->height != src->m_impl->height)
295 void Video::set_palette (
Palette const& palette)
297 m_impl->palette = palette;
302 m_impl->palette = std::move (palette);
307 return m_impl->palette;
312 return m_impl->palette;
315 void Video::set_dimension (
int width,
int height,
int pitch)
317 m_impl->width = width;
318 m_impl->height = height;
319 m_impl->pitch = std::max (pitch, width * m_impl->bpp);
321 m_impl->buffer->set_size (m_impl->pitch * m_impl->height);
323 m_impl->extents =
Rect (width, height);
326 int Video::get_width ()
const
328 return m_impl->width;
331 int Video::get_height ()
const
333 return m_impl->height;
336 void Video::set_pitch (
int pitch)
338 if(pitch <= 0 || m_impl->bpp <= 0) {
342 m_impl->pitch = pitch;
343 m_impl->buffer->set_size (m_impl->pitch * m_impl->height);
346 int Video::get_pitch ()
const
348 return m_impl->pitch;
353 m_impl->depth = depth;
359 return m_impl->depth;
362 int Video::get_bpp ()
const
367 void Video::set_attrs (
int width,
int height,
int pitch,
VisVideoDepth depth)
370 set_dimension (width, height);
374 std::size_t Video::get_size ()
const
376 return m_impl->pitch * m_impl->height;
381 return m_impl->buffer;
384 void* Video::get_pixels ()
const
386 return m_impl->buffer->get_data ();
389 void* Video::get_pixel_ptr (
int x,
int y)
const
391 return static_cast<uint8_t*
> (get_pixels ()) + y * m_impl->pitch + x * m_impl->bpp;
394 Rect const& Video::get_extents ()
const
396 return m_impl->extents;
399 void Video::set_extents(
Rect area)
401 m_impl->extents = area;
406 m_impl->compose_type = type;
409 void Video::set_compose_colorkey (Color
const& color)
411 m_impl->colorkey->
set (0, 0, 0);
414 void Video::set_compose_surface (uint8_t alpha)
416 m_impl->alpha = alpha;
421 m_impl->compose_func = compose_func;
426 switch (src->m_impl->compose_type) {
428 return VideoBlit::blit_overlay_noalpha;
432 return VideoBlit::blit_overlay_noalpha;
434 return VideoBlit::blit_overlay_alphasrc;
437 return VideoBlit::blit_overlay_colorkey;
440 return VideoBlit::blit_overlay_surfacealpha;
443 return VideoBlit::blit_overlay_surfacealphacolorkey;
446 return src->m_impl->compose_func;
453 void Video::blit (
Rect const& drect,
458 auto func = get_compose_function (src, alpha);
460 compose (drect, src, srect, func);
463 void Video::compose (
Rect const& drect,
471 auto vsrc = create_sub (ndrect, src, srect);
472 compose (vsrc, drect.x, drect.y, compose_func);
475 void Video::blit_scale (Rect
const& drect,
476 VideoConstPtr
const& src,
483 return compose_scale (drect, src, srect, scale_method, func);
486 void Video::compose_scale (Rect
const& drect,
487 VideoConstPtr
const& src,
492 auto sbound = m_impl->extents;
493 if (!sbound.intersects (drect))
496 auto ssrc = create_sub (src, srect);
498 auto svid = create ();
499 svid->set_attrs (drect.width,
501 src->m_impl->bpp * drect.width,
503 svid->allocate_buffer ();
505 svid->scale (ssrc, scale_method);
510 compose (drect, svid, frect, compose_func);
517 compose (src, x, y, func);
522 visual_return_if_fail (compose_func !=
nullptr);
527 auto drect = get_extents ();
528 auto srect = src->get_extents ();
530 if (!drect.intersects (srect))
536 if (m_impl->depth != src->m_impl->depth) {
537 transform = create (src->m_impl->width, src->m_impl->height, m_impl->depth);
542 VideoConstPtr srcp = transform ? VideoConstPtr (transform) : src;
558 Rect trect (x, y, srect.width, srect.height);
560 auto dregion = create_sub (drect, VideoPtr (
this), trect);
562 auto redestrect = dregion->get_extents ();
564 auto tempregion = create_sub (srcp, srect);
565 auto sregion = create_sub (drect, tempregion, redestrect);
568 compose_func (dregion.get (), sregion.get ());
571 void Video::fill_alpha (uint8_t alpha)
575 auto vidbuf =
static_cast<uint8_t *
> (get_pixels ()) + 3;
578 for (
int y = 0; y < m_impl->height; y++) {
579 for (
int x = 0; x < m_impl->width; x++)
580 *(vidbuf += m_impl->bpp) = alpha;
582 vidbuf += m_impl->pitch - (m_impl->width * m_impl->bpp);
586 void Video::fill_alpha (uint8_t alpha,
Rect const& area)
590 auto rvid = create_sub (
this, area);
591 rvid->fill_alpha (alpha);
594 void Video::fill_color (
Color const& color)
596 switch (m_impl->depth) {
598 VideoFill::fill_color_index8 (*
this, color);
602 VideoFill::fill_color_rgb16 (*
this, color);
606 VideoFill::fill_color_rgb24 (*
this, color);
610 VideoFill::fill_color_argb32 (*
this, color);
618 void Video::fill_color (
Color const& color,
Rect const& area)
620 if (m_impl->extents.intersects (area))
623 auto svid = create_sub (
VideoPtr (
this), area);
624 svid->fill_color (color);
628 void Video::flip_pixel_bytes (VideoConstPtr
const& src)
630 visual_return_if_fail (compare_attrs (src));
632 switch (m_impl->depth) {
634 VideoConvert::flip_pixel_bytes_color16 (*
this, *src);
638 VideoConvert::flip_pixel_bytes_color24 (*
this, *src);
642 VideoConvert::flip_pixel_bytes_color32 (*
this, *src);
654 if (m_impl->width == src->m_impl->width && m_impl->height == src->m_impl->height)
655 blit (src, 0, 0,
false);
659 VideoTransform::rotate_90 (*
this, *src);
663 VideoTransform::rotate_180 (*
this, *src);
667 VideoTransform::rotate_270 (*
this, *src);
677 visual_return_if_fail (src->m_impl->depth == m_impl->depth);
681 blit (src, 0, 0,
false);
685 VideoTransform::mirror_x (*
this, *src);
689 VideoTransform::mirror_y (*
this, *src);
697 void Video::convert_depth (VideoConstPtr
const& src)
700 if (m_impl->depth == src->m_impl->depth) {
701 blit (src, 0, 0,
false);
706 visual_return_if_fail (src->m_impl->palette.size () == 256);
711 switch (m_impl->depth) {
713 VideoConvert::index8_to_rgb16 (*
this, *src);
717 VideoConvert::index8_to_rgb24 (*
this, *src);
721 VideoConvert::index8_to_argb32 (*
this, *src);
726 int (src->m_impl->depth), int (m_impl->depth));
732 switch (m_impl->depth) {
734 VideoConvert::rgb16_to_index8 (*
this, *src);
738 VideoConvert::rgb16_to_rgb24 (*
this, *src);
742 VideoConvert::rgb16_to_argb32 (*
this, *src);
747 int (src->m_impl->depth), int (m_impl->depth));
753 switch (m_impl->depth) {
755 VideoConvert::rgb24_to_index8 (*
this, *src);
759 VideoConvert::rgb24_to_rgb16 (*
this, *src);
763 VideoConvert::rgb24_to_argb32 (*
this, *src);
768 int (src->m_impl->depth), int (m_impl->depth));
774 switch (m_impl->depth) {
776 VideoConvert::argb32_to_index8 (*
this, *src);
780 VideoConvert::argb32_to_rgb16 (*
this, *src);
784 VideoConvert::argb32_to_rgb24 (*
this, *src);
789 int (src->m_impl->depth), int (m_impl->depth));
797 visual_return_if_fail (m_impl->depth == src->m_impl->depth);
798 visual_return_if_fail (is_valid_scale_method (method));
803 blit (src, 0, 0,
false);
807 switch (m_impl->depth) {
810 VideoTransform::scale_nearest_color8 (*
this, *src);
812 VideoTransform::scale_bilinear_color8 (*
this, *src);
818 VideoTransform::scale_nearest_color16 (*
this, *src);
820 VideoTransform::scale_bilinear_color16 (*
this, *src);
826 VideoTransform::scale_nearest_color24 (*
this, *src);
828 VideoTransform::scale_bilinear_color24 (*
this, *src);
834 VideoTransform::scale_nearest_color32 (*
this, *src);
836 VideoTransform::scale_bilinear_color32 (*
this, *src);
849 if (m_impl->depth != src->m_impl->depth) {
850 auto dtransform = create ();
851 dtransform->set_attrs (m_impl->width, m_impl->height, m_impl->width * m_impl->bpp, m_impl->depth);
852 dtransform->allocate_buffer ();
853 dtransform->convert_depth (src);
855 scale (dtransform, scale_method);
857 scale (src, scale_method);
869 return "8-bit indexed RGB";
878 return "32-bit ARGB";
895 return (depth & depthflag) > 0;
907 if ((i & depthflag) > 0) {
915 if ((i & depthflag) > 0) {
932 if ((i & depthflag) > 0) {
949 int firstentry = TRUE;
951 while (highest != i || firstentry) {