|
|
@ -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; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |