| @ -0,0 +1,138 @@ | |||
| #pragma once | |||
| #include "gp/function.hpp" | |||
| #include "gp/buffer.hpp" | |||
| #include "gp/math.hpp" | |||
| #include "gp/bitops.hpp" | |||
| #include "gp/algorithm/tmp_manip.hpp" | |||
| #include <iostream> | |||
| namespace gp{ | |||
| template<bool lazy, typename color_type> | |||
| class bmp_viewport { | |||
| using src_t = typename gp::either<lazy, | |||
| gp::function<color_type(gp::vec2_g<int32_t>)>, | |||
| gp::buffer<gp::buffer<color_type>> | |||
| >::type; | |||
| src_t source; | |||
| gp::vec2_g<int32_t> resolution; | |||
| color_type get(int32_t x, int32_t y) { | |||
| gp_config::assertion(x>=0, "getting an x below zero"); | |||
| gp_config::assertion(y>=0, "getting an y below zero"); | |||
| if constexpr (lazy) { | |||
| return source({x, y}); | |||
| } else { | |||
| return source[x][y]; | |||
| } | |||
| } | |||
| public: | |||
| bmp_viewport(gp::vec2_g<int32_t> res, src_t src) | |||
| : source{src} | |||
| , resolution{res} | |||
| {} | |||
| gp::buffer<char>::associated_iterator write(gp::buffer<char> destination) { | |||
| using sle16 = /*gp::endian_wrapper<*/int16_t/*, gp::endian::little>*/; | |||
| using sbe16 = /*gp::endian_wrapper<*/int16_t/*, gp::endian::big>*/; | |||
| using sle32 = /*gp::endian_wrapper<*/int32_t/*, gp::endian::little>*/; | |||
| using sbe32 = /*gp::endian_wrapper<*/int32_t/*, gp::endian::big>*/; | |||
| auto it = destination.begin(); | |||
| *(it++) = 'B'; | |||
| *(it++) = 'M'; | |||
| auto& filesize = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| *(it++) = 0; | |||
| *(it++) = 0; | |||
| *(it++) = 0; | |||
| *(it++) = 0; | |||
| auto& pixel_array_offset = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| auto dib_start = it; | |||
| auto& dibsize = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| auto& width = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| width = resolution.x; | |||
| it = it+4; | |||
| auto& height = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| height = resolution.y; | |||
| auto& plane_cnt = gp::buffer<char>{it.data, (it+2).data}.cast<sle16>()[0]; | |||
| it = it+2; | |||
| plane_cnt = 1; | |||
| auto& bit_per_pixel = gp::buffer<char>{it.data, (it+2).data}.cast<sle16>()[0]; | |||
| it = it+2; | |||
| bit_per_pixel = sizeof(color_type)*8; // TODO: correct the size | |||
| auto& compression_method = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| compression_method = 0; | |||
| auto& image_size = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| auto& h_pixel_per_meter = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| h_pixel_per_meter = 2835; | |||
| auto& v_pixel_per_meter = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| v_pixel_per_meter = 2835; | |||
| auto& colors_in_palette = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| colors_in_palette = 0; | |||
| auto& important_colors = gp::buffer<char>{it.data, (it+4).data}.cast<sle32>()[0]; | |||
| it = it+4; | |||
| important_colors = 0; | |||
| auto dib_end = it; | |||
| dibsize = dib_end - dib_start; | |||
| auto pixel_array_start = it; | |||
| for(int32_t line = resolution.y - 1; line >= 0; line--) | |||
| { | |||
| int32_t len = 0; | |||
| for(int32_t row = 0; row < resolution.x; row++) | |||
| { | |||
| // TODO: add more default color modes | |||
| if constexpr (std::is_same<color_type, gp::vec4_g<uint8_t>>::value) | |||
| { | |||
| auto color = get(row, line); | |||
| *(it++) = color.x; | |||
| *(it++) = color.y; | |||
| *(it++) = color.z; | |||
| *(it++) = color.w; | |||
| } else { | |||
| it = it + sizeof(color_type); | |||
| } | |||
| len+=sizeof(color_type); | |||
| } | |||
| for(;len % 4; ++len) | |||
| { | |||
| *(it++) = 0; | |||
| } | |||
| } | |||
| auto pixel_array_end = it; | |||
| pixel_array_offset = pixel_array_start - destination.begin(); | |||
| filesize = pixel_array_end - destination.begin(); | |||
| image_size = pixel_array_end - pixel_array_start; | |||
| std::cout << width << std::endl; | |||
| std::cout << height << std::endl; | |||
| std::cout << filesize << std::endl; | |||
| std::cout << image_size << std::endl; | |||
| return it; | |||
| } | |||
| }; | |||
| } | |||