1 | // Aseprite Document Library |
2 | // Copyright (c) 2020 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/log.h" |
14 | #include "base/split_string.h" |
15 | #include "base/trim_string.h" |
16 | #include "doc/image.h" |
17 | #include "doc/palette.h" |
18 | |
19 | #include <cctype> |
20 | #include <fstream> |
21 | #include <iomanip> |
22 | #include <memory> |
23 | #include <sstream> |
24 | #include <string> |
25 | |
26 | namespace doc { |
27 | namespace file { |
28 | |
29 | std::unique_ptr<Palette> load_gpl_file(const char* filename) |
30 | { |
31 | std::ifstream f(FSTREAM_PATH(filename)); |
32 | if (f.bad()) return NULL; |
33 | |
34 | // Read first line, it must be "GIMP Palette" |
35 | std::string line; |
36 | if (!std::getline(f, line)) return NULL; |
37 | base::trim_string(line, line); |
38 | if (line != "GIMP Palette" ) return NULL; |
39 | |
40 | std::unique_ptr<Palette> pal(new Palette(frame_t(0), 0)); |
41 | std::string ; |
42 | bool hasAlpha = false; |
43 | |
44 | while (std::getline(f, line)) { |
45 | // Trim line. |
46 | base::trim_string(line, line); |
47 | |
48 | // Remove empty lines |
49 | if (line.empty()) |
50 | continue; |
51 | |
52 | // Concatenate comments |
53 | if (line[0] == '#') { |
54 | line = line.substr(1); |
55 | base::trim_string(line, line); |
56 | comment += line; |
57 | comment.push_back('\n'); |
58 | continue; |
59 | } |
60 | |
61 | // Remove properties (TODO add these properties in the palette) |
62 | if (!std::isdigit(line[0])) { |
63 | std::vector<std::string> parts; |
64 | base::split_string(line, parts, ":" ); |
65 | // Aseprite extension for palettes with alpha channel. |
66 | if (parts.size() == 2 && |
67 | parts[0] == "Channels" ) { |
68 | base::trim_string(parts[1], parts[1]); |
69 | if (parts[1] == "RGBA" ) |
70 | hasAlpha = true; |
71 | } |
72 | continue; |
73 | } |
74 | |
75 | int r, g, b, a = 255; |
76 | std::string entryName; |
77 | std::istringstream lineIn(line); |
78 | lineIn >> r >> g >> b; |
79 | if (hasAlpha) { |
80 | lineIn >> a; |
81 | } |
82 | lineIn >> entryName; |
83 | |
84 | if (lineIn.fail()) |
85 | continue; |
86 | |
87 | pal->addEntry(rgba(r, g, b, a)); |
88 | if (!entryName.empty()) { |
89 | base::trim_string(entryName, entryName); |
90 | if (!entryName.empty()) |
91 | pal->setEntryName(pal->size()-1, entryName); |
92 | } |
93 | } |
94 | |
95 | base::trim_string(comment, comment); |
96 | if (!comment.empty()) { |
97 | LOG(VERBOSE, "PAL: %s comment: %s\n" , filename, comment.c_str()); |
98 | pal->setComment(comment); |
99 | } |
100 | |
101 | return pal; |
102 | } |
103 | |
104 | bool save_gpl_file(const Palette* pal, const char* filename) |
105 | { |
106 | std::ofstream f(FSTREAM_PATH(filename)); |
107 | if (f.bad()) return false; |
108 | |
109 | const bool hasAlpha = pal->hasAlpha(); |
110 | |
111 | f << "GIMP Palette\n" ; |
112 | if (hasAlpha) |
113 | f << "Channels: RGBA\n" ; |
114 | f << "#\n" ; |
115 | |
116 | for (int i=0; i<pal->size(); ++i) { |
117 | uint32_t col = pal->getEntry(i); |
118 | f << std::setfill(' ') << std::setw(3) << ((int)rgba_getr(col)) << " " |
119 | << std::setfill(' ') << std::setw(3) << ((int)rgba_getg(col)) << " " |
120 | << std::setfill(' ') << std::setw(3) << ((int)rgba_getb(col)); |
121 | if (hasAlpha) |
122 | f << " " << std::setfill(' ') << std::setw(3) << ((int)rgba_geta(col)); |
123 | f << "\tUntitled\n" ; // TODO add support for color name entries |
124 | } |
125 | |
126 | return true; |
127 | } |
128 | |
129 | } // namespace file |
130 | } // namespace doc |
131 | |