Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-or-later
3 : *
4 : * This file is part of colopresso
5 : *
6 : * Copyright (C) 2025-2026 COLOPL, Inc.
7 : *
8 : * Author: Go Kudo <g-kudo@colopl.co.jp>
9 : * Developed with AI (LLM) code assistance. See `NOTICE` for details.
10 : */
11 :
12 : #ifndef COLOPRESSO_INTERNAL_PNGX_H
13 : #define COLOPRESSO_INTERNAL_PNGX_H
14 :
15 : #include <colopresso.h>
16 :
17 : #include <assert.h>
18 : #include <stdbool.h>
19 : #include <stddef.h>
20 : #include <stdint.h>
21 :
22 : #include <png.h>
23 :
24 : #define PNGX_COMMON_ANCHOR_AUTO_LIMIT_DEFAULT 16u
25 : #define PNGX_COMMON_ANCHOR_DISTANCE_SQ_THRESHOLD 625u
26 : #define PNGX_COMMON_ANCHOR_IMPORTANCE_BOOST_BASE 0.4f
27 : #define PNGX_COMMON_ANCHOR_IMPORTANCE_BOOST_SCALE 0.5f
28 : #define PNGX_COMMON_ANCHOR_IMPORTANCE_FACTOR 0.45f
29 : #define PNGX_COMMON_ANCHOR_IMPORTANCE_THRESHOLD 0.4f
30 : #define PNGX_COMMON_ANCHOR_LOW_COUNT_PENALTY 0.5f
31 : #define PNGX_COMMON_ANCHOR_LOW_COUNT_THRESHOLD 4u
32 : #define PNGX_COMMON_ANCHOR_SCALE_DIVISOR 8192u
33 : #define PNGX_COMMON_ANCHOR_SCALE_MIN 12u
34 : #define PNGX_COMMON_ANCHOR_SCORE_THRESHOLD 0.35f
35 : #define PNGX_COMMON_DITHER_ALPHA_OPAQUE_THRESHOLD 248u
36 : #define PNGX_COMMON_DITHER_ALPHA_TRANSLUCENT_THRESHOLD 32u
37 : #define PNGX_COMMON_DITHER_BASE_LEVEL 0.62f
38 : #define PNGX_COMMON_DITHER_COVERAGE_THRESHOLD 0.35f
39 : #define PNGX_COMMON_DITHER_GRADIENT_MIN 0.02f
40 : #define PNGX_COMMON_DITHER_HIGH_GRADIENT_BOOST 0.12f
41 : #define PNGX_COMMON_DITHER_LOW_BIT_BOOST 0.05f
42 : #define PNGX_COMMON_DITHER_LOW_BIT_GRADIENT_BOOST 0.05f
43 : #define PNGX_COMMON_DITHER_LOW_GRADIENT_CUT 0.12f
44 : #define PNGX_COMMON_DITHER_MAX 0.95f
45 : #define PNGX_COMMON_DITHER_MID_GRADIENT_BOOST 0.05f
46 : #define PNGX_COMMON_DITHER_MID_LOW_GRADIENT_CUT 0.05f
47 : #define PNGX_COMMON_DITHER_MIN 0.2f
48 : #define PNGX_COMMON_DITHER_OPAQUE_HIGH_BOOST 0.05f
49 : #define PNGX_COMMON_DITHER_OPAQUE_LOW_CUT 0.08f
50 : #define PNGX_COMMON_DITHER_SPAN_THRESHOLD 2.0f
51 : #define PNGX_COMMON_DITHER_TARGET_CAP 0.9f
52 : #define PNGX_COMMON_DITHER_TARGET_CAP_LOW_BIT 0.96f
53 : #define PNGX_COMMON_DITHER_TRANSLUCENT_CUT 0.05f
54 : #define PNGX_COMMON_FIXED_PALETTE_DISTANCE_SQ 400u
55 : #define PNGX_COMMON_FIXED_PALETTE_MAX 256u
56 : #define PNGX_COMMON_FS_COEFF_1_16 (1.0f / 16.0f)
57 : #define PNGX_COMMON_FS_COEFF_3_16 (3.0f / 16.0f)
58 : #define PNGX_COMMON_FS_COEFF_5_16 (5.0f / 16.0f)
59 : #define PNGX_COMMON_FS_COEFF_7_16 (7.0f / 16.0f)
60 : #define PNGX_COMMON_LUMA_B_COEFF 0.0722f
61 : #define PNGX_COMMON_LUMA_G_COEFF 0.7152f
62 : #define PNGX_COMMON_LUMA_R_COEFF 0.2126f
63 : #define PNGX_COMMON_PREPARE_ALPHA_BASE 0.4f
64 : #define PNGX_COMMON_PREPARE_ALPHA_MULTIPLIER 0.6f
65 : #define PNGX_COMMON_PREPARE_ALPHA_THRESHOLD 0.85f
66 : #define PNGX_COMMON_PREPARE_ANCHOR_IMPORTANCE_BONUS 0.05f
67 : #define PNGX_COMMON_PREPARE_ANCHOR_IMPORTANCE_THRESHOLD 0.75f
68 : #define PNGX_COMMON_PREPARE_ANCHOR_MIX 0.55f
69 : #define PNGX_COMMON_PREPARE_ANCHOR_SATURATION 0.45f
70 : #define PNGX_COMMON_PREPARE_ANCHOR_SCORE_THRESHOLD 0.35f
71 : #define PNGX_COMMON_PREPARE_BOOST_BASE 0.08f
72 : #define PNGX_COMMON_PREPARE_BOOST_FACTOR 0.3f
73 : #define PNGX_COMMON_PREPARE_BOOST_THRESHOLD 0.25f
74 : #define PNGX_COMMON_PREPARE_BUCKET_ALPHA 170u
75 : #define PNGX_COMMON_PREPARE_BUCKET_IMPORTANCE 0.55f
76 : #define PNGX_COMMON_PREPARE_BUCKET_SATURATION 0.35f
77 : #define PNGX_COMMON_PREPARE_CHROMA_WEIGHT 0.35f
78 : #define PNGX_COMMON_PREPARE_CUT_FACTOR 0.65f
79 : #define PNGX_COMMON_PREPARE_CUT_THRESHOLD 0.08f
80 : #define PNGX_COMMON_PREPARE_GRADIENT_SCALE 0.5f
81 : #define PNGX_COMMON_PREPARE_MAP_MIN_VALUE 4u
82 : #define PNGX_COMMON_PREPARE_MIX_GRADIENT 0.3f
83 : #define PNGX_COMMON_PREPARE_MIX_IMPORTANCE 0.6f
84 : #define PNGX_COMMON_PREPARE_VIBRANT_ALPHA 127u
85 : #define PNGX_COMMON_PREPARE_VIBRANT_GRADIENT 0.05f
86 : #define PNGX_COMMON_PREPARE_VIBRANT_SATURATION 0.55f
87 : #define PNGX_COMMON_RESOLVE_ADAPTIVE_FLAT_CUT 0.12f
88 : #define PNGX_COMMON_RESOLVE_ADAPTIVE_GRADIENT_BOOST 0.06f
89 : #define PNGX_COMMON_RESOLVE_ADAPTIVE_SATURATION_BOOST 0.03f
90 : #define PNGX_COMMON_RESOLVE_ADAPTIVE_SATURATION_CUT 0.02f
91 : #define PNGX_COMMON_RESOLVE_ADAPTIVE_VIBRANT_CUT 0.05f
92 : #define PNGX_COMMON_RESOLVE_AUTO_BASE 0.35f
93 : #define PNGX_COMMON_RESOLVE_AUTO_GRADIENT_WEIGHT 0.35f
94 : #define PNGX_COMMON_RESOLVE_AUTO_OPAQUE_CUT 0.06f
95 : #define PNGX_COMMON_RESOLVE_AUTO_SATURATION_WEIGHT 0.15f
96 : #define PNGX_COMMON_RESOLVE_DEFAULT_GRADIENT 0.2f
97 : #define PNGX_COMMON_RESOLVE_DEFAULT_OPAQUE 1.0f
98 : #define PNGX_COMMON_RESOLVE_DEFAULT_SATURATION 0.2f
99 : #define PNGX_COMMON_RESOLVE_DEFAULT_VIBRANT 0.05f
100 : #define PNGX_COMMON_RESOLVE_MAX 0.90f
101 : #define PNGX_COMMON_RESOLVE_MIN 0.02f
102 : #define PNGX_PALETTE256_GRADIENT_PROFILE_DITHER_FLOOR 0.78f
103 : #define PNGX_PALETTE256_GRADIENT_PROFILE_GRADIENT_MEAN_MAX 0.16f
104 : #define PNGX_PALETTE256_GRADIENT_PROFILE_OPAQUE_RATIO_THRESHOLD 0.90f
105 : #define PNGX_PALETTE256_GRADIENT_PROFILE_SATURATION_MEAN_MAX 0.42f
106 : #define PNGX_PALETTE256_TUNE_GRADIENT_MEAN_MAX 0.14f
107 : #define PNGX_PALETTE256_TUNE_OPAQUE_RATIO_THRESHOLD 0.90f
108 : #define PNGX_PALETTE256_TUNE_QUALITY_MAX_TARGET 100
109 : #define PNGX_PALETTE256_TUNE_QUALITY_MIN_FLOOR 90
110 : #define PNGX_PALETTE256_TUNE_SATURATION_MEAN_MAX 0.35f
111 : #define PNGX_PALETTE256_TUNE_SPEED_MAX 1
112 : #define PNGX_REDUCED_ALPHA_DETAIL_WEIGHT 0.5f
113 : #define PNGX_REDUCED_ALPHA_LEVEL_LIMIT_FEW 4u
114 : #define PNGX_REDUCED_ALPHA_MIN_DITHER_FACTOR 0.04f
115 : #define PNGX_REDUCED_ALPHA_NEAR_TRANSPARENT 8u
116 : #define PNGX_REDUCED_ALPHA_OPAQUE_LIMIT 0.985f
117 : #define PNGX_REDUCED_ALPHA_RATIO_FEW 0.15f
118 : #define PNGX_REDUCED_ALPHA_RATIO_LOW 0.1f
119 : #define PNGX_REDUCED_ALPHA_RATIO_MINIMAL 0.07f
120 : #define PNGX_REDUCED_ALPHA_SIMPLE_DEFAULT_OPAQUE 1.0f
121 : #define PNGX_REDUCED_ALPHA_SIMPLE_DEFAULT_TRANSLUCENT 0.0f
122 : #define PNGX_REDUCED_ALPHA_SIMPLE_OPAQUE_RANGE 0.1f
123 : #define PNGX_REDUCED_ALPHA_SIMPLE_OPAQUE_REF 0.9f
124 : #define PNGX_REDUCED_ALPHA_SIMPLE_OPAQUE_WEIGHT 0.6f
125 : #define PNGX_REDUCED_ALPHA_SIMPLE_TRANSLUCENT_RANGE 0.12f
126 : #define PNGX_REDUCED_ALPHA_SIMPLE_TRANSLUCENT_REF 0.12f
127 : #define PNGX_REDUCED_ALPHA_SIMPLE_TRANSLUCENT_WEIGHT 0.4f
128 : #define PNGX_REDUCED_ALPHA_TRANSLUCENT_LIMIT 0.06f
129 : #define PNGX_REDUCED_HEAD_DOMINANCE_LIMIT 64
130 : #define PNGX_REDUCED_IMPORTANCE_LEVEL_FULL 232
131 : #define PNGX_REDUCED_IMPORTANCE_LEVEL_HIGH 184
132 : #define PNGX_REDUCED_IMPORTANCE_LEVEL_LOW 96
133 : #define PNGX_REDUCED_IMPORTANCE_LEVEL_MEDIUM 136
134 : #define PNGX_REDUCED_IMPORTANCE_SCALE_DENOM 255.0f
135 : #define PNGX_REDUCED_IMPORTANCE_SCALE_MIN 0.25f
136 : #define PNGX_REDUCED_IMPORTANCE_SCALE_RANGE 0.50f
137 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_BONUS_HIGH 2u
138 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_BONUS_MEDIUM 1u
139 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_BONUS_STRONG 3u
140 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_CAP 16u
141 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_SHIFT 5u
142 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_THRESHOLD_HIGH 150
143 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_THRESHOLD_MEDIUM 80
144 : #define PNGX_REDUCED_IMPORTANCE_WEIGHT_THRESHOLD_STRONG 220
145 : #define PNGX_REDUCED_LOW_WEIGHT_DIVISOR 2048u
146 : #define PNGX_REDUCED_LOW_WEIGHT_MAX 2048u
147 : #define PNGX_REDUCED_LOW_WEIGHT_MIN 32u
148 : #define PNGX_REDUCED_PASSTHROUGH_DEFAULT_GRADIENT 0.22f
149 : #define PNGX_REDUCED_PASSTHROUGH_DEFAULT_SATURATION 0.28f
150 : #define PNGX_REDUCED_PASSTHROUGH_DEFAULT_VIBRANT 0.06f
151 : #define PNGX_REDUCED_PASSTHROUGH_GRADIENT_WEIGHT 0.55f
152 : #define PNGX_REDUCED_PASSTHROUGH_RATIO_BASE 0.82f
153 : #define PNGX_REDUCED_PASSTHROUGH_RATIO_CAP 0.95f
154 : #define PNGX_REDUCED_PASSTHROUGH_RATIO_GAIN 0.10f
155 : #define PNGX_REDUCED_PASSTHROUGH_SATURATION_WEIGHT 0.30f
156 : #define PNGX_REDUCED_PASSTHROUGH_VIBRANT_WEIGHT 0.15f
157 : #define PNGX_REDUCED_PRIORITY_DETAIL_WEIGHT 0.4f
158 : #define PNGX_REDUCED_PRIORITY_MASS_WEIGHT 0.15f
159 : #define PNGX_REDUCED_PRIORITY_SPAN_WEIGHT 0.45f
160 : #define PNGX_REDUCED_RGBA32_PASSTHROUGH_GRID_DIVISOR 4
161 : #define PNGX_REDUCED_RGBA32_PASSTHROUGH_MIN_COLORS 512
162 : #define PNGX_REDUCED_ROUNDING_OFFSET 0.5f
163 : #define PNGX_REDUCED_STATS_FLAT_DEFAULT_GRADIENT 0.2f
164 : #define PNGX_REDUCED_STATS_FLAT_DEFAULT_SATURATION 0.25f
165 : #define PNGX_REDUCED_STATS_FLAT_DEFAULT_VIBRANT 0.05f
166 : #define PNGX_REDUCED_STATS_FLAT_GRADIENT_REF 0.18f
167 : #define PNGX_REDUCED_STATS_FLAT_GRADIENT_WEIGHT 0.5f
168 : #define PNGX_REDUCED_STATS_FLAT_SATURATION_REF 0.24f
169 : #define PNGX_REDUCED_STATS_FLAT_SATURATION_WEIGHT 0.35f
170 : #define PNGX_REDUCED_STATS_FLAT_VIBRANT_WEIGHT 0.15f
171 : #define PNGX_REDUCED_TARGET_ALPHA_SIMPLE_CLAMP 0.12f
172 : #define PNGX_REDUCED_TARGET_ALPHA_SIMPLE_SCALE 0.12f
173 : #define PNGX_REDUCED_TARGET_ALPHA_SIMPLE_THRESHOLD 0.1f
174 : #define PNGX_REDUCED_TARGET_BASE_MIN 512.0f
175 : #define PNGX_REDUCED_TARGET_COMBINED_CUT_BASE 0.45f
176 : #define PNGX_REDUCED_TARGET_COMBINED_CUT_CLAMP 0.28f
177 : #define PNGX_REDUCED_TARGET_DENSITY_GAP_CLAMP 0.15f
178 : #define PNGX_REDUCED_TARGET_DENSITY_GAP_SCALE 0.5f
179 : #define PNGX_REDUCED_TARGET_DENSITY_HIGH_SCALE 1.15f
180 : #define PNGX_REDUCED_TARGET_DENSITY_HIGH_THRESHOLD 0.35f
181 : #define PNGX_REDUCED_TARGET_DENSITY_LOW_SCALE 0.85f
182 : #define PNGX_REDUCED_TARGET_DENSITY_LOW_THRESHOLD 0.08f
183 : #define PNGX_REDUCED_TARGET_DENSITY_THRESHOLD 0.27f
184 : #define PNGX_REDUCED_TARGET_DETAIL_BOOST_CLAMP 0.10f
185 : #define PNGX_REDUCED_TARGET_DETAIL_BOOST_SCALE 0.25f
186 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_ALPHA_LIMIT 0.45f
187 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_BOOST 0.38f
188 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_DENSITY_LIMIT 0.35f
189 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_FLAT_LIMIT 0.32f
190 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_GENTLE_LIMIT 0.5f
191 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_HEAD_LIMIT 0.45f
192 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_STRONG_LIMIT 0.42f
193 : #define PNGX_REDUCED_TARGET_DETAIL_PRESSURE_TAIL_LIMIT 0.35f
194 : #define PNGX_REDUCED_TARGET_DETAIL_RELIEF_BASE 0.45f
195 : #define PNGX_REDUCED_TARGET_DETAIL_RELIEF_CLAMP 0.2f
196 : #define PNGX_REDUCED_TARGET_DETAIL_RELIEF_SCALE 0.35f
197 : #define PNGX_REDUCED_TARGET_DOMINANCE_GAIN_CLAMP 0.32f
198 : #define PNGX_REDUCED_TARGET_DOMINANCE_GAIN_SCALE 1.35f
199 : #define PNGX_REDUCED_TARGET_FLATNESS_CLAMP 0.18f
200 : #define PNGX_REDUCED_TARGET_FLATNESS_SCALE 0.18f
201 : #define PNGX_REDUCED_TARGET_FLATNESS_THRESHOLD 0.05f
202 : #define PNGX_REDUCED_TARGET_GENTLE_CLAMP 0.16f
203 : #define PNGX_REDUCED_TARGET_GENTLE_COLOR_RANGE 384.0f
204 : #define PNGX_REDUCED_TARGET_GENTLE_MAX_COLORS 1024u
205 : #define PNGX_REDUCED_TARGET_GENTLE_MIN_COLORS 640u
206 : #define PNGX_REDUCED_TARGET_GENTLE_SCALE 0.22f
207 : #define PNGX_REDUCED_TARGET_GRADIENT_RELIEF_DEFAULT 0.5f
208 : #define PNGX_REDUCED_TARGET_GRADIENT_RELIEF_REF 0.22f
209 : #define PNGX_REDUCED_TARGET_GRADIENT_RELIEF_SECONDARY_DEFAULT 0.35f
210 : #define PNGX_REDUCED_TARGET_GRADIENT_RELIEF_SECONDARY_REF 0.24f
211 : #define PNGX_REDUCED_TARGET_HEAD_CUT_BASE 0.32f
212 : #define PNGX_REDUCED_TARGET_HEAD_CUT_CLAMP 0.18f
213 : #define PNGX_REDUCED_TARGET_HEAD_CUT_RELIEF 0.28f
214 : #define PNGX_REDUCED_TARGET_HEAD_DOMINANCE_BUCKETS 48u
215 : #define PNGX_REDUCED_TARGET_HEAD_DOMINANCE_STRONG 0.58f
216 : #define PNGX_REDUCED_TARGET_HEAD_DOMINANCE_THRESHOLD 0.6f
217 : #define PNGX_REDUCED_TARGET_LOW_WEIGHT_RATIO_STRONG 0.46f
218 : #define PNGX_REDUCED_TARGET_LOW_WEIGHT_REDUCTION_BASE 0.26f
219 : #define PNGX_REDUCED_TARGET_LOW_WEIGHT_REDUCTION_CLAMP 0.18f
220 : #define PNGX_REDUCED_TARGET_LOW_WEIGHT_REDUCTION_DETAIL 0.12f
221 : #define PNGX_REDUCED_TARGET_LOW_WEIGHT_REDUCTION_START 0.38f
222 : #define PNGX_REDUCED_TARGET_RELIEF_CLAMP 0.2f
223 : #define PNGX_REDUCED_TARGET_RELIEF_GRADIENT_WEIGHT 0.65f
224 : #define PNGX_REDUCED_TARGET_RELIEF_SATURATION_WEIGHT 0.35f
225 : #define PNGX_REDUCED_TARGET_RELIEF_SCALE 0.25f
226 : #define PNGX_REDUCED_TARGET_SATURATION_RELIEF_DEFAULT 0.25f
227 : #define PNGX_REDUCED_TARGET_SATURATION_RELIEF_REF 0.3f
228 : #define PNGX_REDUCED_TARGET_TAIL_CUT_CLAMP 0.12f
229 : #define PNGX_REDUCED_TARGET_TAIL_GAIN_BASE 0.34f
230 : #define PNGX_REDUCED_TARGET_TAIL_GAIN_CLAMP 0.18f
231 : #define PNGX_REDUCED_TARGET_TAIL_GAIN_RELIEF 0.28f
232 : #define PNGX_REDUCED_TARGET_TAIL_RATIO_THRESHOLD 0.52f
233 : #define PNGX_REDUCED_TARGET_TAIL_WIDTH_BASE 0.4f
234 : #define PNGX_REDUCED_TARGET_TAIL_WIDTH_SCALE 0.65f
235 : #define PNGX_REDUCED_TARGET_UNIQUE_BASE_SCALE 12.0f
236 : #define PNGX_REDUCED_TARGET_UNIQUE_COLOR_THRESHOLD 1024u
237 : #define PNGX_REDUCED_TRIM_ALPHA_SIMPLE_CLAMP 0.08f
238 : #define PNGX_REDUCED_TRIM_ALPHA_SIMPLE_SCALE 0.08f
239 : #define PNGX_REDUCED_TRIM_ALPHA_SIMPLE_THRESHOLD 0.1f
240 : #define PNGX_REDUCED_TRIM_DENSITY_CLAMP 0.12f
241 : #define PNGX_REDUCED_TRIM_DENSITY_SCALE 0.25f
242 : #define PNGX_REDUCED_TRIM_DENSITY_THRESHOLD 0.22f
243 : #define PNGX_REDUCED_TRIM_DETAIL_PRESSURE_FLAT_LIMIT 0.42f
244 : #define PNGX_REDUCED_TRIM_DETAIL_PRESSURE_HEAD_LIMIT 0.48f
245 : #define PNGX_REDUCED_TRIM_DETAIL_PRESSURE_TAIL_LIMIT 0.52f
246 : #define PNGX_REDUCED_TRIM_FLATNESS_CLAMP 0.08f
247 : #define PNGX_REDUCED_TRIM_FLATNESS_SCALE 0.15f
248 : #define PNGX_REDUCED_TRIM_FLATNESS_THRESHOLD 0.08f
249 : #define PNGX_REDUCED_TRIM_FLATNESS_WEIGHT 0.45f
250 : #define PNGX_REDUCED_TRIM_HEAD_CLAMP 0.32f
251 : #define PNGX_REDUCED_TRIM_HEAD_DOMINANCE_THRESHOLD 0.58f
252 : #define PNGX_REDUCED_TRIM_HEAD_WEIGHT 0.55f
253 : #define PNGX_REDUCED_TRIM_MIN_COLOR_DIFF 64u
254 : #define PNGX_REDUCED_TRIM_MIN_COLOR_MARGIN 32u
255 : #define PNGX_REDUCED_TRIM_MIN_TRIGGER 0.03f
256 : #define PNGX_REDUCED_TRIM_TAIL_BASE_WEIGHT 0.4f
257 : #define PNGX_REDUCED_TRIM_TAIL_CLAMP 0.2f
258 : #define PNGX_REDUCED_TRIM_TAIL_DETAIL_WEIGHT 0.3f
259 : #define PNGX_REDUCED_TRIM_TAIL_RATIO_THRESHOLD 0.42f
260 : #define PNGX_REDUCED_TRIM_TOTAL_CLAMP 0.38f
261 : #define PNGX_REDUCED_TUNE_DEFAULT_GRADIENT 0.2f
262 : #define PNGX_REDUCED_TUNE_DEFAULT_OPAQUE 1.0f
263 : #define PNGX_REDUCED_TUNE_DEFAULT_SATURATION 0.3f
264 : #define PNGX_REDUCED_TUNE_DEFAULT_TRANSLUCENT 0.0f
265 : #define PNGX_REDUCED_TUNE_DEFAULT_VIBRANT 0.05f
266 : #define PNGX_REDUCED_TUNE_FLAT_GRADIENT_THRESHOLD 0.15f
267 : #define PNGX_REDUCED_TUNE_FLAT_SATURATION_THRESHOLD 0.28f
268 : #define PNGX_REDUCED_TUNE_FLAT_VIBRANT_THRESHOLD 0.08f
269 : #define PNGX_REDUCED_TUNE_VERY_FLAT_GRADIENT 0.08f
270 : #define PNGX_REDUCED_TUNE_VERY_FLAT_SATURATION 0.18f
271 : #define PNGX_REDUCED_VIBRANT_RATIO_LOW 0.04f
272 : #define PNGX_LIMITED_RGBA4444_BITS 4
273 : #define PNGX_RGBA_CHANNELS 4
274 : #define PNGX_CHROMA_BUCKET_BITS 4
275 : #define PNGX_CHROMA_BUCKET_SHIFT (8 - PNGX_CHROMA_BUCKET_BITS)
276 : #define PNGX_CHROMA_BUCKET_DIM 16
277 : #define PNGX_CHROMA_BUCKET_COUNT \
278 : (PNGX_CHROMA_BUCKET_DIM * PNGX_CHROMA_BUCKET_DIM * PNGX_CHROMA_BUCKET_DIM)
279 : #define PNGX_FULL_CHANNEL_BITS 8
280 : #define PNGX_IMPORTANCE_SCALE 65535.0f
281 : #define PNGX_MAX_DERIVED_COLORS 48
282 : #define PNGX_POSTPROCESS_DISABLE_DITHER_THRESHOLD 0.25f
283 : #define PNGX_POSTPROCESS_MAX_COLOR_DISTANCE_SQ 900
284 :
285 : #define PNGX_DEFINE_CLAMP(type) \
286 : static inline type clamp_##type(type value, type min_value, type max_value) \
287 : { \
288 : assert(min_value <= max_value); \
289 : \
290 : if (value < min_value) { \
291 : return min_value; \
292 : } \
293 : \
294 : if (value > max_value) { \
295 : return max_value; \
296 : } \
297 : \
298 : return value; \
299 : }
300 :
301 : #ifdef __cplusplus
302 : extern "C" {
303 : #endif
304 :
305 : typedef enum {
306 : PNGX_BRIDGE_RESULT_SUCCESS = 0,
307 : PNGX_BRIDGE_RESULT_INVALID_INPUT = 1,
308 : PNGX_BRIDGE_RESULT_OPTIMIZATION_FAILED = 2,
309 : PNGX_BRIDGE_RESULT_IO_ERROR = 3,
310 : } pngx_bridge_result_t;
311 :
312 : typedef enum {
313 : PNGX_BRIDGE_QUANT_STATUS_OK = 0,
314 : PNGX_BRIDGE_QUANT_STATUS_QUALITY_TOO_LOW = 1,
315 : PNGX_BRIDGE_QUANT_STATUS_ERROR = 2,
316 : } pngx_bridge_quant_status_t;
317 :
318 : typedef enum {
319 : PNGX_LOSSY_TYPE_PALETTE256 = COLOPRESSO_PNGX_LOSSY_TYPE_PALETTE256,
320 : PNGX_LOSSY_TYPE_LIMITED_RGBA4444 = COLOPRESSO_PNGX_LOSSY_TYPE_LIMITED_RGBA4444,
321 : PNGX_LOSSY_TYPE_REDUCED_RGBA32 = COLOPRESSO_PNGX_LOSSY_TYPE_REDUCED_RGBA32,
322 : } pngx_lossy_type_t;
323 :
324 : typedef struct {
325 : uint8_t optimization_level;
326 : bool strip_safe;
327 : bool optimize_alpha;
328 : } pngx_bridge_options_t;
329 :
330 : typedef struct {
331 : uint8_t optimization_level;
332 : bool strip_safe;
333 : bool optimize_alpha;
334 : } pngx_bridge_lossless_options_t;
335 :
336 : typedef struct {
337 : int32_t speed;
338 : uint8_t quality_min;
339 : uint8_t quality_max;
340 : uint32_t max_colors;
341 : int32_t min_posterization;
342 : float dithering_level;
343 : const uint8_t *importance_map;
344 : size_t importance_map_len;
345 : const cpres_rgba_color_t *fixed_colors;
346 : size_t fixed_colors_len;
347 : bool remap;
348 : } pngx_bridge_quant_params_t;
349 :
350 : typedef struct {
351 : cpres_rgba_color_t *palette;
352 : size_t palette_len;
353 : uint8_t *indices;
354 : size_t indices_len;
355 : int32_t quality;
356 : } pngx_bridge_quant_output_t;
357 :
358 : typedef struct {
359 : pngx_bridge_options_t bridge;
360 : bool lossy_enable;
361 : uint8_t lossy_type;
362 : uint16_t lossy_max_colors;
363 : int32_t lossy_reduced_colors;
364 : uint8_t lossy_reduced_bits_rgb;
365 : uint8_t lossy_reduced_alpha_bits;
366 : uint8_t lossy_quality_min;
367 : uint8_t lossy_quality_max;
368 : uint8_t lossy_speed;
369 : float lossy_dither_level;
370 : bool lossy_dither_auto;
371 : const cpres_rgba_color_t *protected_colors;
372 : int32_t protected_colors_count;
373 : bool saliency_map_enable;
374 : bool chroma_anchor_enable;
375 : bool adaptive_dither_enable;
376 : bool gradient_boost_enable;
377 : bool chroma_weight_enable;
378 : bool postprocess_smooth_enable;
379 : float postprocess_smooth_importance_cutoff;
380 : bool palette256_gradient_profile_enable;
381 : float palette256_gradient_profile_dither_floor;
382 : bool palette256_alpha_bleed_enable;
383 : uint16_t palette256_alpha_bleed_max_distance;
384 : uint8_t palette256_alpha_bleed_opaque_threshold;
385 : uint8_t palette256_alpha_bleed_soft_limit;
386 : float palette256_profile_opaque_ratio_threshold;
387 : float palette256_profile_gradient_mean_max;
388 : float palette256_profile_saturation_mean_max;
389 : float palette256_tune_opaque_ratio_threshold;
390 : float palette256_tune_gradient_mean_max;
391 : float palette256_tune_saturation_mean_max;
392 : int16_t palette256_tune_speed_max;
393 : int16_t palette256_tune_quality_min_floor;
394 : int16_t palette256_tune_quality_max_target;
395 : uint32_t thread_count;
396 : } pngx_options_t;
397 :
398 : typedef struct {
399 : uint8_t *data;
400 : size_t size;
401 : size_t capacity;
402 : } png_memory_buffer_t;
403 :
404 : typedef struct {
405 : uint8_t *rgba;
406 : png_uint_32 width;
407 : png_uint_32 height;
408 : size_t pixel_count;
409 : } pngx_rgba_image_t;
410 :
411 : typedef struct {
412 : float gradient_mean;
413 : float gradient_max;
414 : float saturation_mean;
415 : float opaque_ratio;
416 : float translucent_ratio;
417 : float vibrant_ratio;
418 : } pngx_image_stats_t;
419 :
420 : typedef struct {
421 : uint8_t *importance_map;
422 : size_t importance_map_len;
423 : cpres_rgba_color_t *derived_colors;
424 : size_t derived_colors_len;
425 : cpres_rgba_color_t *combined_fixed_colors;
426 : size_t combined_fixed_len;
427 : uint8_t *bit_hint_map;
428 : size_t bit_hint_len;
429 : } pngx_quant_support_t;
430 :
431 30 : PNGX_DEFINE_CLAMP(int32_t)
432 30 : PNGX_DEFINE_CLAMP(uint32_t)
433 44 : PNGX_DEFINE_CLAMP(uint16_t)
434 192 : PNGX_DEFINE_CLAMP(uint8_t)
435 563 : PNGX_DEFINE_CLAMP(float)
436 :
437 : /* from pngx_bridge rust library */
438 : extern pngx_bridge_result_t
439 : pngx_bridge_optimize_lossless(const uint8_t *input_data, size_t input_size, uint8_t **output_data,
440 : size_t *output_size, const pngx_bridge_lossless_options_t *options);
441 : extern pngx_bridge_quant_status_t pngx_bridge_quantize(const cpres_rgba_color_t *pixels,
442 : size_t pixel_count, uint32_t width,
443 : uint32_t height,
444 : const pngx_bridge_quant_params_t *params,
445 : pngx_bridge_quant_output_t *output);
446 : extern void pngx_bridge_free(uint8_t *ptr);
447 : extern uint32_t pngx_bridge_oxipng_version(void);
448 : extern uint32_t pngx_bridge_libimagequant_version(void);
449 : extern const char *pngx_bridge_rust_version_string(void);
450 : extern bool pngx_bridge_init_threads(int num_threads);
451 :
452 : extern bool pngx_quantize_palette256(const uint8_t *png_data, size_t png_size,
453 : const pngx_options_t *opts, uint8_t **out_data,
454 : size_t *out_size, int *quant_quality);
455 : extern bool pngx_palette256_prepare(const uint8_t *png_data, size_t png_size,
456 : const pngx_options_t *opts, uint8_t **out_rgba,
457 : uint32_t *out_width, uint32_t *out_height,
458 : uint8_t **out_importance_map, size_t *out_importance_map_len,
459 : int32_t *out_speed, uint8_t *out_quality_min,
460 : uint8_t *out_quality_max, uint32_t *out_max_colors,
461 : float *out_dither_level, uint8_t **out_fixed_colors,
462 : size_t *out_fixed_colors_len);
463 : extern bool pngx_palette256_finalize(const uint8_t *indices, size_t indices_len,
464 : const cpres_rgba_color_t *palette, size_t palette_len,
465 : uint8_t **out_data, size_t *out_size);
466 : extern void pngx_palette256_cleanup(void);
467 : extern bool pngx_create_palette_png(const uint8_t *indices, size_t indices_len,
468 : const cpres_rgba_color_t *palette, size_t palette_len,
469 : uint32_t width, uint32_t height, uint8_t **out_data,
470 : size_t *out_size);
471 : extern bool create_rgba_png(const uint8_t *rgba, size_t pixel_count, uint32_t width,
472 : uint32_t height, uint8_t **out_data, size_t *out_size);
473 : extern bool pngx_quantize_limited4444(const uint8_t *png_data, size_t png_size,
474 : const pngx_options_t *opts, uint8_t **out_data,
475 : size_t *out_size);
476 : extern bool pngx_quantize_reduced_rgba32(const uint8_t *png_data, size_t png_size,
477 : const pngx_options_t *opts, uint32_t *resolved_target,
478 : uint32_t *applied_colors, uint8_t **out_data,
479 : size_t *out_size);
480 : extern void pngx_fill_pngx_options(pngx_options_t *opts, const cpres_config_t *config);
481 : extern bool pngx_run_quantization(const uint8_t *png_data, size_t png_size,
482 : const pngx_options_t *opts, uint8_t **out_data, size_t *out_size,
483 : int *quant_quality);
484 : extern bool pngx_run_lossless_optimization(const uint8_t *png_data, size_t png_size,
485 : const pngx_options_t *opts, uint8_t **out_data,
486 : size_t *out_size);
487 : extern bool pngx_should_attempt_quantization(const pngx_options_t *opts);
488 : extern bool pngx_quantization_better(size_t baseline_size, size_t candidate_size);
489 :
490 : extern int pngx_get_last_error(void);
491 : extern void pngx_set_last_error(int error_code);
492 :
493 : #ifdef __cplusplus
494 : }
495 : #endif
496 :
497 : #endif /* COLOPRESSO_INTERNAL_PNGX_H */
|