Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
lut3dgmic.cpp
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2019-2020 Philippe Weyland.
4 Copyright (C) 2020 Heiko Bauke.
5 Copyright (C) 2020 Pascal Obry.
6
7 darktable is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 darktable is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with darktable. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#define cimg_verbosity 0
22#include <gmic.h>
23#include <iostream>
24#include <string>
25
26extern "C"
27{
28 // otherwise the name will be mangled and the linker won't be able to see the function ...
29 void lut3d_decompress_clut(const unsigned char *const input_keypoints, const unsigned int nb_input_keypoints,
30 const unsigned int output_resolution, float *const output_clut_data,
31 const char *const filename);
32
33 unsigned int lut3d_get_cached_clut(float *const output_clut_data, const unsigned int output_resolution,
34 const char *const filename);
35
36 gboolean lut3d_read_gmz(int *const nb_keypoints, unsigned char *const keypoints, const char *const filename,
37 int *const nb_lut, void *widget, const char *const lutname, const gboolean newlutname);
38
39 void lut3d_add_lutname_to_list(void *g, const char *const lutname);
40
42}
43
44void lut3d_decompress_clut(const unsigned char *const input_keypoints, const unsigned int nb_input_keypoints,
45 const unsigned int output_resolution, float *const output_clut_data,
46 const char *const filename)
47{
48 gmic_list<float> image_list;
49 gmic_list<char> image_names;
50 gmic g_instance;
51 g_instance.verbosity = -1;
52 char gmic_cmd[512];
53 image_list.assign(1);
54 gmic_image<float> &img = image_list[0];
55 img.assign(1, nb_input_keypoints, 1, 6);
56 // set the keypoint image
57 float *ptr = img;
58 for(size_t i = 0; i < nb_input_keypoints * 6; ++i) *(ptr++) = (float)input_keypoints[i];
59
60 // decompress the keypoints to LUT
61 // -cut 0,255 is added to mask GMIC 2.6.4 compressed clut issue.
62 std::snprintf(gmic_cmd, sizeof(gmic_cmd), "-decompress_clut %u,%u,%u -cut 0,255", output_resolution,
63 output_resolution, output_resolution);
64 try
65 {
66 g_instance.run(gmic_cmd, image_list, image_names);
67 }
68 catch(gmic_exception &e) // In case something went wrong.
69 {
70 std::printf("[lut3d gmic] error: \"%s\"\n", e.what());
71 image_list.assign(0);
72 return;
73 }
74 // save in cache if possible - compatible G'MIC
75 try
76 {
77 std::snprintf(gmic_cmd, sizeof(gmic_cmd), "-o \"%s\",uchar", filename);
78 g_instance.run(gmic_cmd, image_list, image_names);
79 }
80 catch(...)
81 {
82 std::fprintf(stderr, "[lut3d gmic] error - saving cache lut (does the cache folder exist ?)\n");
83 }
84 // format for dt
85 try
86 {
87 g_instance.run("-div 255.0 -permute cxyz", image_list, image_names); // scale to [0,1]
88 }
89 catch(gmic_exception &e) // In case something went wrong.
90 {
91 std::printf("[lut3d gmic] error: \"%s\"\n", e.what());
92 image_list.assign(0);
93 return;
94 }
95 const size_t img_size
96 = image_list[0]._width * image_list[0]._height * image_list[0]._depth * image_list[0]._spectrum;
97 std::memcpy(output_clut_data, image_list[0]._data, img_size * sizeof(float));
98 image_list.assign(0);
99}
100
101unsigned int lut3d_get_cached_clut(float *const output_clut_data, const unsigned int output_resolution,
102 const char *const filename)
103{
104 gmic_list<float> image_list;
105 gmic_list<char> image_names;
106 char gmic_cmd[512];
107 gmic g_instance;
108 g_instance.verbosity = -1;
109 // get the cache file
110 try
111 {
112 std::snprintf(gmic_cmd, sizeof(gmic_cmd), "-i \"%s\"", filename);
113 g_instance.run(gmic_cmd, image_list, image_names);
114 }
115 catch(...)
116 { // no cached lut
117 image_list.assign(0);
118 return 0;
119 }
120 // expected LUT size ?
121 const unsigned int output_size = 3 * output_resolution * output_resolution * output_resolution;
122 unsigned int output_res = output_resolution;
123 size_t img_size = image_list[0]._width * image_list[0]._height * image_list[0]._depth * image_list[0]._spectrum;
124 if(output_size < img_size) // downsize the cached lut
125 {
126 std::snprintf(gmic_cmd, sizeof(gmic_cmd), "-r %u,%u,%u,3,3", output_resolution, output_resolution,
127 output_resolution);
128 try
129 {
130 g_instance.run(gmic_cmd, image_list, image_names);
131 }
132 catch(gmic_exception &e) // In case something went wrong.
133 {
134 std::printf("[lut3d gmic] error: \"%s\"\n", e.what());
135 image_list.assign(0);
136 return 0;
137 }
138 img_size = image_list[0]._width * image_list[0]._height * image_list[0]._depth * image_list[0]._spectrum;
139 }
140 else if(output_size > img_size) // reduce the expected lut size
141 {
142 output_res = image_list[0]._width;
143 }
144 // format for dt
145 try
146 {
147 g_instance.run("-div 255.0 -permute cxyz", image_list, image_names); // scale to [0,1]
148 }
149 catch(gmic_exception &e) // In case something went wrong.
150 {
151 std::printf("[lut3d gmic] error: \"%s\"\n", e.what());
152 image_list.assign(0);
153 return 0;
154 }
155 std::memcpy(output_clut_data, image_list[0]._data, img_size * sizeof(float));
156 image_list.assign(0);
157 return output_res;
158}
159
160gboolean lut3d_read_gmz(int *const nb_keypoints, unsigned char *const keypoints, const char *const filename,
161 int *const nb_lut, void *g, const char *const lutname, const gboolean newlutname)
162{
163 gmic_list<float> image_list;
164 gmic_list<char> image_names;
165 char gmic_cmd[512];
166 gmic g_instance;
167 g_instance.verbosity = -1;
168 gboolean lut_found = FALSE;
169 // read the compressed lut file
170 try
171 {
172 std::snprintf(gmic_cmd, sizeof(gmic_cmd), "-i \"%s\"", filename);
173 g_instance.run(gmic_cmd, image_list, image_names);
174 }
175 catch(gmic_exception &e) // In case something went wrong.
176 {
177 std::printf("[lut3d gmic] error: \"%s\"\n", e.what());
178 *nb_lut = 0;
179 image_list.assign(0);
180 image_names.assign(0);
181 return lut_found;
182 }
183 unsigned int l = 0;
184 if(lutname[0]) // find this specific lut
185 {
186 for(unsigned int i = 0; i < image_names._width; ++i)
187 {
188 if(strcmp(image_names[i]._data, lutname) == 0)
189 {
190 l = i;
191 lut_found = TRUE;
192 break;
193 }
194 }
195 }
196 *nb_lut = (int)image_names._width;
197 if(!newlutname)
198 { // list of luts for this new file
200 for(unsigned int i = 0; i < image_names._width; ++i)
201 {
202 lut3d_add_lutname_to_list(g, image_names[i]._data);
203 }
204 }
205
206 int nb_kp = *nb_keypoints = (int)image_list[l]._height;
207 if(image_list[l]._width == 1 && image_list[l]._height <= 2048 && image_list[l]._depth == 1
208 && image_list[l]._spectrum == 6)
209 { // color lut
210 gmic_image<float> &img = image_list[l];
211 for(int i = 0; i < nb_kp * 6; ++i) keypoints[i] = (unsigned char)img[i];
212 }
213 else if(image_list[l]._width == 1 && image_list[l]._height <= 2048 && image_list[l]._depth == 1
214 && image_list[l]._spectrum == 4)
215 { // black & white lut
216 gmic_image<float> &img = image_list[l];
217 for(int i = 0; i < nb_kp * 3; ++i) keypoints[i] = (unsigned char)img[i];
218 for(int i = 0; i < nb_kp; ++i)
219 keypoints[nb_kp * 3 + i] = keypoints[nb_kp * 4 + i] = keypoints[nb_kp * 5 + i]
220 = (unsigned char)img[nb_kp * 3 + i];
221 }
222 else
223 std::printf("[lut3d gmic] error: incompatible compressed LUT [%u] %s\n", l, image_names[l]._data);
224
225 image_list.assign(0);
226 image_names.assign(0);
227 return lut_found;
228}
229
230// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
231// vim: shiftwidth=2 expandtab tabstop=2 cindent
232// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void lut3d_decompress_clut(const unsigned char *const input_keypoints, const unsigned int nb_input_keypoints, const unsigned int output_resolution, float *const output_clut_data, const char *const filename)
Definition lut3dgmic.cpp:44
void lut3d_clear_lutname_list(void *g)
void lut3d_add_lutname_to_list(void *g, const char *const lutname)
unsigned int lut3d_get_cached_clut(float *const output_clut_data, const unsigned int output_resolution, const char *const filename)
gboolean lut3d_read_gmz(int *const nb_keypoints, unsigned char *const keypoints, const char *const filename, int *const nb_lut, void *widget, const char *const lutname, const gboolean newlutname)