15_pixel_view.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include <cstdio>
  2. #include <cerrno>
  3. #include <cassert>
  4. #include <algorithm>
  5. #include <thread>
  6. #include <chrono>
  7. #include "simple/graphical/initializer.h"
  8. #include "simple/graphical/software_window.h"
  9. #include "simple/graphical/pixel_format.h"
  10. #include "simple/graphical/algorithm/blit.h"
  11. #include "simple/graphical/algorithm/fill.h"
  12. #include "simple/graphical/pixels.h"
  13. #include "simple/support/algorithm.hpp"
  14. using namespace simple::graphical;
  15. using namespace simple::graphical::color_literals;
  16. using namespace std::chrono_literals;
  17. using simple::support::all_of;
  18. using simple::support::range;
  19. int main() try
  20. {
  21. initializer graphics;
  22. software_window win("pixel view", {400,400}, window::flags::borderless);
  23. surface playground{win.size(), pixel_format(pixel_format::type::rgb24)};
  24. // pixel_reader and pixel_writer are non-owning, lightweight
  25. // views on pixels data
  26. // surface format is dynamic so we have to select pixel type at runtime
  27. // in this case we know exactly which format to get
  28. const auto all_pixels = std::get<
  29. // pixel_writer can read and write pixels,
  30. pixel_writer<rgb_pixel, surface::byte>
  31. >(playground.pixels());
  32. // pixel_reader can only read
  33. const auto all_pixels_const = pixel_reader(all_pixels);
  34. // you can construct a reader from a writer but NOT vise versa
  35. // lets fill the surface with something ineresting
  36. const auto blue = playground.format().color(0x0000ff_rgb); // type erased color
  37. const auto box = range{int2::zero(), int2::one(200)};
  38. fill(pixel_writer(all_pixels, box), 0xff0000_rgb); // top left
  39. fill(pixel_writer(all_pixels, box + int2::i(200)), rgb_pixel::green()); // top right
  40. fill(pixel_writer(all_pixels, box + int2::j(200)), blue); // bottom left
  41. blit(playground, win.surface());
  42. win.update();
  43. std::this_thread::sleep_for(1s);
  44. // now lets copy everything to the bottom right corner in place
  45. // for an interesting effect
  46. const auto bottom_right = pixel_writer(all_pixels,box + 200);
  47. blit(all_pixels_const, bottom_right);
  48. blit(playground, win.surface());
  49. win.update();
  50. std::this_thread::sleep_for(3s);
  51. // dangerous stuff
  52. // raw_range is a range of raw bytes
  53. // the rows of pixels might not be consecutive in memory
  54. // there could be alignemnt padding between them
  55. // or worse pixels of a "parent" image
  56. // don't use this unless you know what you're doing
  57. //
  58. // in this case we know it's padding at worst
  59. auto raw_bytes = all_pixels.raw_range();
  60. // set it all to some value
  61. std::fill(raw_bytes.begin(), raw_bytes.end(), 13);
  62. // check the value through reader
  63. assert(( all_of(all_pixels_const.raw_range(),
  64. [](auto b){ return b == 13; }) ));
  65. blit(playground, win.surface());
  66. win.update();
  67. std::this_thread::sleep_for(1313ms);
  68. return 0;
  69. }
  70. catch(...)
  71. {
  72. if(errno)
  73. std::perror("ERROR");
  74. const char* sdl_error = SDL_GetError();
  75. if(*sdl_error)
  76. std::puts(sdl_error);
  77. throw;
  78. }