1// Aseprite Document Library
2// Copyright (c) 2022 Igara Studio S.A.
3// Copyright (c) 2001-2016 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/base.h"
13#include "base/cfile.h"
14#include "doc/color_scales.h"
15#include "doc/image.h"
16#include "doc/palette.h"
17
18#include <cstdio>
19#include <cstdlib>
20#include <memory>
21
22#define PROCOL_MAGIC_NUMBER 0xB123
23
24namespace doc {
25namespace file {
26
27using namespace base;
28
29// Loads a COL file (Animator and Animator Pro format)
30std::unique_ptr<Palette> load_col_file(const char* filename)
31{
32 int c, r, g, b;
33
34 FILE* f = std::fopen(filename, "rb");
35 if (!f)
36 return nullptr;
37
38 // Get file size.
39 std::fseek(f, 0, SEEK_END);
40 std::size_t size = std::ftell(f);
41 std::div_t d = std::div(size-8, 3);
42 std::fseek(f, 0, SEEK_SET);
43
44 bool pro = (size == 768)? false: true; // is Animator Pro format?
45 if (!(size) || (pro && d.rem)) { // Invalid format
46 fclose(f);
47 return NULL;
48 }
49
50 // Animator format
51 std::unique_ptr<Palette> pal = nullptr;
52 if (!pro) {
53 pal = std::make_unique<Palette>(frame_t(0), 256);
54
55 for (c=0; c<256; c++) {
56 r = fgetc(f);
57 g = fgetc(f);
58 b = fgetc(f);
59 if (ferror(f))
60 break;
61
62 pal->setEntry(c, rgba(scale_6bits_to_8bits(std::clamp(r, 0, 63)),
63 scale_6bits_to_8bits(std::clamp(g, 0, 63)),
64 scale_6bits_to_8bits(std::clamp(b, 0, 63)), 255));
65 }
66 }
67 // Animator Pro format
68 else {
69 int magic, version;
70
71 fgetl(f); // Skip file size
72 magic = fgetw(f); // File format identifier
73 version = fgetw(f); // Version file
74
75 // Unknown format
76 if (magic != PROCOL_MAGIC_NUMBER || version != 0) {
77 fclose(f);
78 return nullptr;
79 }
80
81 pal = std::make_unique<Palette>(frame_t(0), std::min(d.quot, 256));
82
83 for (c=0; c<pal->size(); c++) {
84 r = fgetc(f);
85 g = fgetc(f);
86 b = fgetc(f);
87 if (ferror(f))
88 break;
89
90 pal->setEntry(c, rgba(std::clamp(r, 0, 255),
91 std::clamp(g, 0, 255),
92 std::clamp(b, 0, 255), 255));
93 }
94 }
95
96 fclose(f);
97 return pal;
98}
99
100// Saves an Animator Pro COL file
101bool save_col_file(const Palette* pal, const char* filename)
102{
103 FILE *f = fopen(filename, "wb");
104 if (!f)
105 return false;
106
107 fputl(8+768, f); // File size
108 fputw(PROCOL_MAGIC_NUMBER, f); // File format identifier
109 fputw(0, f); // Version file
110
111 uint32_t c;
112 for (int i=0; i<256; i++) {
113 c = pal->getEntry(i);
114
115 fputc(rgba_getr(c), f);
116 fputc(rgba_getg(c), f);
117 fputc(rgba_getb(c), f);
118 if (ferror(f))
119 break;
120 }
121
122 fclose(f);
123 return true;
124}
125
126} // namespace file
127} // namespace doc
128