1// Aseprite Document Library
2// Copyright (c) 2020-2022 Igara Studio S.A.
3// Copyright (c) 2001-2018 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "base/fstream_path.h"
13#include "base/serialization.h"
14#include "doc/palette.h"
15
16#include <algorithm>
17#include <cctype>
18#include <fstream>
19#include <memory>
20
21namespace doc {
22namespace file {
23
24using namespace base::serialization::big_endian;
25
26const int ActMaxColors = 256;
27
28std::unique_ptr<Palette> load_act_file(const char *filename)
29{
30 std::ifstream f(FSTREAM_PATH(filename), std::ios::binary);
31 if (f.bad())
32 return nullptr;
33
34 // Each color is a 24-bit RGB value
35 uint8_t rgb[ActMaxColors * 3] = { 0 };
36 f.read(reinterpret_cast<char*>(&rgb), sizeof(rgb));
37
38 int colors = ActMaxColors;
39 // If there's extra bytes, it's the number of colors to use
40 if (!f.eof()) {
41 colors = std::min(read16(f), (uint16_t)ActMaxColors);
42 }
43
44 std::unique_ptr<Palette> pal(new Palette(frame_t(0), colors));
45
46 uint8_t *c = rgb;
47 for (int i = 0; i < colors; ++i) {
48 uint8_t r = *(c++);
49 uint8_t g = *(c++);
50 uint8_t b = *(c++);
51
52 pal->setEntry(i, rgba(r, g, b, 255));
53 }
54
55 return pal;
56}
57
58bool save_act_file(const Palette *pal, const char *filename)
59{
60 std::ofstream f(FSTREAM_PATH(filename), std::ios::binary);
61 if (f.bad())
62 return false;
63
64 // Need to write 256 colors even if the palette is smaller
65 uint8_t rgb[ActMaxColors * 3] = { 0 };
66 uint8_t *c = rgb;
67
68 int colors = std::min(pal->size(), ActMaxColors);
69 for (int i = 0; i < colors; ++i) {
70 uint32_t col = pal->getEntry(i);
71
72 *(c++) = rgba_getr(col);
73 *(c++) = rgba_getg(col);
74 *(c++) = rgba_getb(col);
75 }
76 f.write(reinterpret_cast<char*>(&rgb), sizeof(rgb));
77
78 write16(f, colors);
79 write16(f, 0);
80
81 return true;
82}
83
84} // namespace file
85} // namespace doc
86