1 // colourspace.h
2 // LiVES
3 // (c) G. Finch 2004 - 2020 <salsaman+lives@gmail.com>
4 // Released under the GPL 3 or later
5 // see file ../COPYING for licensing details
6 
7 // headers for palette conversions
8 
9 #ifndef HAS_LIVES_COLOURSPACE_H
10 #define HAS_LIVES_COLOURSPACE_H
11 
12 #ifdef USE_16BIT_PCONV
13 #define USE_EXTEND
14 #endif
15 
16 //#define WEED_ADVANCED_PALETTES
17 
18 #define WEED_LEAF_CLIP "clip"
19 #define WEED_LEAF_FRAME "frame"
20 #define WEED_LEAF_HOST_PIXEL_DATA_CONTIGUOUS "host_contiguous"
21 #define WEED_LEAF_HOST_PIXBUF_SRC "host_pixbuf_src"
22 #define WEED_LEAF_HOST_SURFACE_SRC "host_surface_src"
23 #define WEED_LEAF_PIXEL_BITS "pixel_bits"
24 #define WEED_LEAF_HOST_FLAGS "host_flags"
25 #define WEED_LEAF_RESIZE_THREAD "res_thread"
26 #define WEED_LEAF_PROGSCAN "progscan"
27 
28 #define DEF_SCREEN_GAMMA 1.4 // extra gammm boost
29 
30 /// rowstride alignment values
31 #define ALIGN_MIN 4
32 #define ALIGN_DEF 16
33 
34 // rgb / yuv conversion factors ////////////
35 #define FP_BITS 16 /// max fp bits
36 
37 #ifdef USE_EXTEND
38 #define SCALE_FACTOR 65793. /// (2 ^ 24 - 1) / (2 ^ 8 - 1), also 0xFF * SCALE_FACTOR = 0xFFFFFF
39 #else
40 #define SCALE_FACTOR (1 << FP_BITS)
41 #endif
42 
43 #define KR_YCBCR 0.2989
44 #define KB_YCBCR 0.114
45 
46 #define KR_I240 0.212
47 #define KB_I240 0.087
48 
49 #define KR_BT709 0.2126
50 #define KB_BT709 0.0722
51 
52 #define KR_BT2020 0.2627
53 #define KB_BT2020 0.0593
54 
55 #define YUV_CLAMP_MIN 16.
56 #define YUV_CLAMP_MINI 16
57 
58 #define Y_CLAMP_MAX 235.
59 #define Y_CLAMP_MAXI 235
60 
61 #define UV_CLAMP_MAX 240.
62 #define UV_CLAMP_MAXI 240
63 
64 #define CLAMP_FACTOR_Y ((Y_CLAMP_MAX-YUV_CLAMP_MIN)/255.) // unclamped -> clamped
65 #define CLAMP_FACTOR_UV ((UV_CLAMP_MAX-YUV_CLAMP_MIN)/255.) // unclamped -> clamped
66 
67 #define UV_BIAS 128.
68 
69 #define MAX_THREADS 65536
70 
71 typedef weed_plant_t weed_layer_t;
72 
73 /////////////////////////////////////////////
74 
75 typedef struct {
76   float offs, lin, thresh, pf;
77 } gamma_const_t;
78 
79 typedef struct {
80   uint8_t u0;
81   uint8_t y0;
82   uint8_t v0;
83   uint8_t y1;
84 } uyvy_macropixel;
85 
86 typedef struct {
87   uint8_t y0;
88   uint8_t u0;
89   uint8_t y1;
90   uint8_t v0;
91 } yuyv_macropixel;
92 
93 typedef struct {
94   uint8_t u2;
95   uint8_t y0;
96   uint8_t y1;
97   uint8_t v2;
98   uint8_t y2;
99   uint8_t y3;
100 } yuv411_macropixel;
101 
102 typedef struct {
103   void *src;
104   void *srcp[4];
105   size_t hsize;
106   size_t vsize;
107   boolean is_bottom;
108   size_t psize;
109   size_t xoffset;
110   int irowstrides[4];
111   int orowstrides[4];
112   void *dest;
113   void *destp[4];
114   boolean in_alpha;
115   boolean out_alpha;
116   boolean in_clamping;
117   boolean out_clamping;
118   int in_subspace;
119   int out_subspace;
120   int in_sampling;
121   int out_sampling;
122   boolean alpha_first;
123   boolean is_422;
124   void *lut;
125   int thread_id;
126 } lives_cc_params;
127 
128 #ifdef USE_SWSCALE
129 #include <libswscale/swscale.h>
130 
131 typedef struct {
132   weed_layer_t *layer;
133   int thread_id;
134   int iheight;
135   int width;
136   double file_gamma;
137   struct SwsContext *swscale;
138   const uint8_t *ipd[4];
139   const uint8_t  *opd[4];
140   const int *irw;
141   const int *orw;
142   int ret;
143 } lives_sw_params;
144 
145 #endif
146 
147 void rgb2hsv(uint8_t r, uint8_t g, uint8_t b, double *h, double *s, double *v);
148 void hsv2rgb(double h, double s, double v, uint8_t *r, uint8_t *g, uint8_t *b);
149 boolean pick_nice_colour(uint8_t r0, uint8_t g0, uint8_t b0, uint8_t *r1, uint8_t *g1, uint8_t *b1,
150                          double max, double lmin, double lmax);
151 
152 double cdist94(uint8_t r0, uint8_t g0, uint8_t b0, uint8_t r1, uint8_t g1, uint8_t b1);
153 
154 #ifdef WEED_ADVANCED_PALETTES
155 #define LIVES_VCHAN_grey	       	2048
156 #define LIVES_VCHAN_mono_b      	2049
157 #define LIVES_VCHAN_mono_w      	2050
158 
159 #define LIVES_VCHAN_cc			3000
160 #define LIVES_VCHAN_mm			3001
161 #define LIVES_VCHAN_yy			3002
162 #define LIVES_VCHAN_kk			3003
163 
164 #define LIVES_VCHAN_xxx  		4000
165 #define LIVES_VCHAN_yyy  		4001
166 #define LIVES_VCHAN_zzz		     	4002
167 
168 #define LIVES_VCHAN_hh  		4000
169 #define LIVES_VCHAN_ss  		4001
170 #define LIVES_VCHAN_vv		     	4002
171 
172 /// for fun / testing
173 #define LIVES_PALETTE_ABGR32		6
174 #define LIVES_PALETTE_YUV121010		8211
175 #define LIVES_PALETTE_RGB48		9001
176 #define LIVES_PALETTE_RGBA64		9003
177 #define LIVES_PALETTE_YUVA420P		9512
178 #define LIVES_PALETTE_YVU422P		9522
179 #define LIVES_PALETTE_AYUV8888		9545
180 #define LIVES_PALETTE_YUVFLOAT		9564
181 #define LIVES_PALETTE_YUVAFLOAT		9565
182 
183 const weed_macropixel_t *get_advanced_palette(int weed_palette);
184 boolean weed_palette_is_valid(int pal);
185 int get_simple_palette(weed_macropixel_t *mpx);
186 size_t pixel_size(int pal);
187 int weed_palette_get_pixels_per_macropixel(int pal);
188 int weed_palette_get_bits_per_macropixel(int pal);
189 int weed_palette_get_nplanes(int pal);
190 boolean weed_palette_is_rgb(int pal);
191 boolean weed_palette_is_yuv(int pal);
192 boolean weed_palette_is_alpha(int pal);
193 boolean weed_palette_has_alpha(int pal);
194 boolean weed_palette_is_float(int pal);
195 double weed_palette_get_plane_ratio_horizontal(int pal, int plane);
196 double weed_palette_get_plane_ratio_vertical(int pal, int plane);
197 
198 int weed_palette_get_alpha_plane(int pal);
199 int weed_palette_get_alpha_offset(int pal);
200 boolean weed_palette_red_first(int pal);
201 boolean weed_palettes_rbswapped(int pal0, int pal1);
202 boolean weed_palette_has_alpha_first(int pal);
203 boolean weed_palette_has_alpha_last(int pal);
204 #endif
205 
206 int32_t round_special(int32_t val);
207 
208 void init_conversions(int intent);
209 
210 void init_colour_engine(void);
211 
212 double get_luma8(uint8_t r, uint8_t g, uint8_t b);
213 double get_luma16(uint16_t r, uint16_t g, uint16_t b);
214 
215 /////////////////////////////////////// LAYERS ///////////////////////////////////////
216 
217 #define WEED_PLANT_LAYER 128
218 
219 #define WEED_LEAF_LAYER_TYPE "layer_type"
220 #define WEED_LAYER_TYPE_NONE	0
221 #define WEED_LAYER_TYPE_VIDEO	1
222 #define WEED_LAYER_TYPE_AUDIO	2
223 
224 #define WEED_IS_LAYER(plant) (weed_plant_get_type(plant) == WEED_PLANT_LAYER)
225 
226 // create / destroy / copy layers
227 weed_layer_t *weed_layer_new(int layer_type);
228 weed_layer_t *create_blank_layer(weed_layer_t *, const char *image_ext, int width, int height, int target_palette);
229 weed_layer_t *weed_layer_create(int width, int height, int *rowstrides, int current_palette);
230 weed_layer_t *weed_layer_create_full(int width, int height, int *rowstrides, int current_palette,
231                                      int YUV_clamping, int YUV_sampling, int YUV_subspace, int gamma_type);
232 weed_layer_t *weed_layer_copy(weed_layer_t *dlayer, weed_layer_t *slayer);
233 weed_layer_t *weed_layer_free(weed_layer_t *);
234 int weed_layer_unref(weed_layer_t *);
235 int weed_layer_ref(weed_layer_t *);
236 
237 // lives specific
238 weed_layer_t *lives_layer_new_for_frame(int clip, frames_t frame);
239 
240 void lives_layer_set_clip(weed_layer_t *, int clip);
241 void lives_layer_set_frame(weed_layer_t *, frames_t frame);
242 
243 int lives_layer_get_clip(weed_layer_t *);
244 frames_t lives_layer_get_frame(weed_layer_t *);
245 
246 // pixel_data
247 /// layer should be pre-set with palette, width in MACROPIXELS, and height
248 /// gamma_type will be set WEED_GAMMA_SRGB, old pixel_data will not be freed.
249 boolean create_empty_pixel_data(weed_layer_t *, boolean black_fill, boolean may_contig);
250 void pixel_data_planar_from_membuf(void **pixel_data, void *data, size_t size, int palette, boolean dest_contig);
251 void weed_layer_pixel_data_free(weed_layer_t *);
252 
253 #define WEED_GAMMA_MONITOR 1024
254 #define WEED_GAMMA_FILE 1025
255 #define WEED_GAMMA_VARIANT 2048
256 #define WEED_LAYER_ALPHA_PREMULT 1
257 
258 /// private flags
259 #define LIVES_LAYER_LOAD_IF_NEEDS_RESIZE 1
260 #define LIVES_LAYER_GET_SIZE_ONLY 2
261 
262 // private flags bitfield
263 #define LIVES_LAYER_HAS_SIZE_NOW (1 << 16)
264 
265 // layer transformation functions
266 void alpha_unpremult(weed_layer_t *, boolean un);
267 boolean copy_pixel_data(weed_layer_t *dst, weed_layer_t *src_or_null, size_t alignment);
268 boolean gamma_convert_layer(int gamma_type, weed_layer_t *);
269 boolean gamma_convert_layer_variant(double file_gamma, int tgamma, weed_layer_t *);
270 boolean gamma_convert_sub_layer(int gamma_type, double fileg, weed_layer_t *, int x, int y,
271                                 int width, int height, boolean may_thread);
272 boolean convert_layer_palette(weed_layer_t *, int outpl, int op_clamping);
273 boolean convert_layer_palette_with_sampling(weed_layer_t *, int outpl, int out_sampling);
274 boolean convert_layer_palette_full(weed_layer_t *, int outpl, int oclamping, int osampling, int osubspace, int tgamma);
275 void lives_layer_set_opaque(weed_layer_t *);
276 boolean consider_swapping(int *inpal, int *outpal);
277 
278 /// widths in PIXELS
279 boolean resize_layer(weed_layer_t *, int width, int height, LiVESInterpType interp, int opal_hint, int oclamp_hint);
280 boolean letterbox_layer(weed_layer_t *, int nwidth, int nheight, int width, int height, LiVESInterpType interp, int tpal,
281                         int tclamp);
282 boolean compact_rowstrides(weed_layer_t *);
283 
284 void gamma_conv_params(int gamma_type, weed_layer_t *inst, boolean is_in);
285 
286 // palette information functions
287 boolean weed_palette_is_lower_quality(int p1, int p2);
288 boolean rowstrides_differ(int n1, int *n1_array, int n2, int *n2_array);
289 
290 // lives_painter (cairo) functions
291 boolean weed_palette_is_painter_palette(int pal);
292 lives_painter_t *layer_to_lives_painter(weed_layer_t *);
293 boolean lives_painter_to_layer(lives_painter_t *cairo, weed_layer_t *);
294 
295 // pixbuf functions
296 #define weed_palette_is_pixbuf_palette(pal) ((pal == WEED_PALETTE_RGB24 || pal == WEED_PALETTE_RGBA32) ? TRUE : FALSE)
297 boolean lives_pixbuf_is_all_black(LiVESPixbuf *pixbuf);
298 void lives_pixbuf_set_opaque(LiVESPixbuf *pixbuf);
299 
300 LiVESPixbuf *layer_to_pixbuf(weed_layer_t *, boolean realpalette, boolean fordisp);
301 boolean pixbuf_to_layer(weed_layer_t *, LiVESPixbuf *) WARN_UNUSED;
302 
303 // layer info
304 int weed_layer_is_video(weed_layer_t *);
305 int weed_layer_is_audio(weed_layer_t *);
306 int weed_layer_get_palette(weed_layer_t *);
307 int weed_layer_get_palette_yuv(weed_layer_t *, int *clamping, int *sampling, int *subspace);
308 int weed_layer_get_yuv_clamping(weed_layer_t *);
309 int weed_layer_get_yuv_sampling(weed_layer_t *);
310 int weed_layer_get_yuv_subspace(weed_layer_t *);
311 uint8_t *weed_layer_get_pixel_data_packed(weed_layer_t *);
312 void **weed_layer_get_pixel_data(weed_layer_t *, int *nplanes);
313 float **weed_layer_get_audio_data(weed_layer_t *, int *naudchans);
314 int weed_layer_get_audio_rate(weed_layer_t *layer);
315 int weed_layer_get_naudchans(weed_layer_t *layer);
316 int weed_layer_get_audio_length(weed_layer_t *layer);
317 int *weed_layer_get_rowstrides(weed_layer_t *, int *nplanes);
318 int weed_layer_get_rowstride(weed_layer_t *); ///< for packed palettes
319 int weed_layer_get_width(weed_layer_t *);
320 int weed_layer_get_width_pixels(weed_layer_t *);
321 int weed_layer_get_height(weed_layer_t *);
322 int weed_layer_get_palette(weed_layer_t *);
323 int weed_layer_get_gamma(weed_layer_t *);
324 int weed_layer_get_flags(weed_layer_t *);
325 
326 // weed_layer_get_rowstride
327 
328 /// functions all return the input layer for convenience; no checking for valid values is done
329 /// if layer is NULL or not weed_layer then NULL is returned
330 weed_layer_t *weed_layer_set_palette(weed_layer_t *, int palette);
331 weed_layer_t *weed_layer_set_palette_yuv(weed_layer_t *, int palette, int clamping, int sampling, int subspace);
332 weed_layer_t *weed_layer_set_yuv_clamping(weed_layer_t *, int clamping);
333 weed_layer_t *weed_layer_set_yuv_sampling(weed_layer_t *, int sampling);
334 weed_layer_t *weed_layer_set_yuv_subspace(weed_layer_t *, int subspace);
335 weed_layer_t *weed_layer_set_gamma(weed_layer_t *, int gamma_type);
336 
337 /// width in macropixels of the layer palette
338 weed_layer_t *weed_layer_set_width(weed_layer_t *, int width);
339 weed_layer_t *weed_layer_set_height(weed_layer_t *, int height);
340 weed_layer_t *weed_layer_set_size(weed_layer_t *, int width, int height);
341 weed_layer_t *weed_layer_set_rowstrides(weed_layer_t *, int *rowstrides, int nplanes);
342 weed_layer_t *weed_layer_set_rowstride(weed_layer_t *, int rowstride);
343 
344 weed_layer_t *weed_layer_set_flags(weed_layer_t *, int flags);
345 
346 weed_layer_t *weed_layer_set_pixel_data(weed_layer_t *, void **pixel_data, int nplanes);
347 weed_layer_t *weed_layer_set_pixel_data_packed(weed_layer_t *, void *pixel_data);
348 weed_layer_t *weed_layer_nullify_pixel_data(weed_layer_t *);
349 weed_layer_t *weed_layer_set_audio_data(weed_layer_t *, float **data, int arate, int naudchans, weed_size_t nsamps);
350 
351 /// utility funcs for GUI
352 int resize_all(int fileno, int width, int height, lives_img_type_t imgtype, boolean do_back, int *nbad, int *nmiss);
353 
354 #endif
355