//! @file функции загрузки/сохрания картинки в файлы или память
#include "image.hpp"
#include "stb/stb_image.h" // 4 load
#include "a83/log.hpp"
#include "a83/string-util.hpp"
#include <fstream>
void Image::save(a83::Str name) {
  using namespace std;
  using namespace a83;
  if ( !check())
    return;
  IFERROR(name.empty(), "image file name is empty");
  convSep(name);
  a83::log("save image \"" + name + "\"");
  // pal8 to rgb24
  constexpr uint comp = 3;
  auto *rgb24_p = new uint8_t[size() * comp];
  for (int i = 0; i < size(); ++i) {
    uint8_t r, g, b;
    fast_get(i).to_rgb24(r, g, b);
    auto rgb24_index = i * comp;
    rgb24_p[rgb24_index + 0] = r;
    rgb24_p[rgb24_index + 1] = g;
    rgb24_p[rgb24_index + 2] = b;
  }
  stbi_write_png(name.c_str(), getX(), getY(), STBI_rgb, rgb24_p, 0);
  delete[] rgb24_p;
} // save
void Image::load_file(a83::Str name) {
  using namespace std;
  using namespace a83;
  IFERROR(name.empty(), "Image.load_file: image file name is empty");
  convSep(name);
  a83::log("Image.load_file \"" + name + "\"");
  fstream file(name, ios_base::binary | ios_base::in);
  IFERROR(file.bad() || !file, "Image.load_file: file not readed. file name " + name);
// определяет размер файла в байтах:
  file.seekp(0, ios::end);
  data_t mem;
  mem.size = file.tellp();
  file.seekp(0, ios::beg);
  IFERROR( !mem.size || mem.size == size_t(-1), "file size = 0");
  // RAW данные с файла
  mem.data = new uint8_t[mem.size];
  file.read(rcast(char*, mem.data), mem.size);
  load(mem);
} // load_file
void Image::load_arch(CN(Archive) arch, a83::Str name) {
  using namespace std;
  using namespace a83;
  IFERROR(name.empty(), "Image.load_arch: image file name is empty");
  convSep(name);
  a83::log("Image.load_arch \"" + name + "\"");
  auto mem = arch.get_file(name);
  load(mem);
} // load_arch
void Image::load(CN(data_t) mem) {
  IFERROR(mem.empty(), "Image.load: mem.empty");
  // декодирование:
  int x, y;
  int comp; // сколько цветовых каналов
  stbi_uc *decoded = nullptr;
  decoded = stbi_load_from_memory(rcast(stbi_uc*, mem.data), mem.size, &x, &y, &comp, STBI_rgb);
  IFERROR( !decoded, "Image.load: image data is not decoded");
// переносим данные на растр:
  init(x, y);
  // сконвертировать цвета
  int rgb_index = 0;
  for (int i = 0; i < x * y; ++i) {
    Color col = desaturate_mid(
      decoded[rgb_index + 0],
      decoded[rgb_index + 1],
      decoded[rgb_index + 2]);
    rgb_index += 3;
    fast_set(i, col);
  } // for size
  stbi_image_free(decoded);
} // load