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 (PNGX_CHROMA_BUCKET_DIM * PNGX_CHROMA_BUCKET_DIM * PNGX_CHROMA_BUCKET_DIM)
278 : #define PNGX_FULL_CHANNEL_BITS 8
279 : #define PNGX_IMPORTANCE_SCALE 65535.0f
280 : #define PNGX_MAX_DERIVED_COLORS 48
281 : #define PNGX_POSTPROCESS_DISABLE_DITHER_THRESHOLD 0.25f
282 : #define PNGX_POSTPROCESS_MAX_COLOR_DISTANCE_SQ 900
283 :
284 : #ifdef __cplusplus
285 : extern "C" {
286 : #endif
287 :
288 : typedef enum {
289 : PNGX_BRIDGE_RESULT_SUCCESS = 0,
290 : PNGX_BRIDGE_RESULT_INVALID_INPUT = 1,
291 : PNGX_BRIDGE_RESULT_OPTIMIZATION_FAILED = 2,
292 : PNGX_BRIDGE_RESULT_IO_ERROR = 3,
293 : } PngxBridgeResult;
294 :
295 : typedef enum {
296 : PNGX_BRIDGE_QUANT_STATUS_OK = 0,
297 : PNGX_BRIDGE_QUANT_STATUS_QUALITY_TOO_LOW = 1,
298 : PNGX_BRIDGE_QUANT_STATUS_ERROR = 2,
299 : } PngxBridgeQuantStatus;
300 :
301 : typedef enum {
302 : PNGX_LOSSY_TYPE_PALETTE256 = COLOPRESSO_PNGX_LOSSY_TYPE_PALETTE256,
303 : PNGX_LOSSY_TYPE_LIMITED_RGBA4444 = COLOPRESSO_PNGX_LOSSY_TYPE_LIMITED_RGBA4444,
304 : PNGX_LOSSY_TYPE_REDUCED_RGBA32 = COLOPRESSO_PNGX_LOSSY_TYPE_REDUCED_RGBA32,
305 : } pngx_lossy_type_t;
306 :
307 : typedef struct {
308 : uint8_t optimization_level;
309 : bool strip_safe;
310 : bool optimize_alpha;
311 : } PngxBridgeOptions;
312 :
313 : typedef struct {
314 : uint8_t optimization_level;
315 : bool strip_safe;
316 : bool optimize_alpha;
317 : } PngxBridgeLosslessOptions;
318 :
319 : typedef struct {
320 : int32_t speed;
321 : uint8_t quality_min;
322 : uint8_t quality_max;
323 : uint32_t max_colors;
324 : int32_t min_posterization;
325 : float dithering_level;
326 : const uint8_t *importance_map;
327 : size_t importance_map_len;
328 : const cpres_rgba_color_t *fixed_colors;
329 : size_t fixed_colors_len;
330 : bool remap;
331 : } PngxBridgeQuantParams;
332 :
333 : typedef struct {
334 : cpres_rgba_color_t *palette;
335 : size_t palette_len;
336 : uint8_t *indices;
337 : size_t indices_len;
338 : int32_t quality;
339 : } PngxBridgeQuantOutput;
340 :
341 : typedef struct {
342 : PngxBridgeOptions bridge;
343 : bool lossy_enable;
344 : uint8_t lossy_type;
345 : uint16_t lossy_max_colors;
346 : int32_t lossy_reduced_colors;
347 : uint8_t lossy_reduced_bits_rgb;
348 : uint8_t lossy_reduced_alpha_bits;
349 : uint8_t lossy_quality_min;
350 : uint8_t lossy_quality_max;
351 : uint8_t lossy_speed;
352 : float lossy_dither_level;
353 : bool lossy_dither_auto;
354 : const cpres_rgba_color_t *protected_colors;
355 : int32_t protected_colors_count;
356 : bool saliency_map_enable;
357 : bool chroma_anchor_enable;
358 : bool adaptive_dither_enable;
359 : bool gradient_boost_enable;
360 : bool chroma_weight_enable;
361 : bool postprocess_smooth_enable;
362 : float postprocess_smooth_importance_cutoff;
363 : bool palette256_gradient_profile_enable;
364 : float palette256_gradient_profile_dither_floor;
365 : bool palette256_alpha_bleed_enable;
366 : uint16_t palette256_alpha_bleed_max_distance;
367 : uint8_t palette256_alpha_bleed_opaque_threshold;
368 : uint8_t palette256_alpha_bleed_soft_limit;
369 : float palette256_profile_opaque_ratio_threshold;
370 : float palette256_profile_gradient_mean_max;
371 : float palette256_profile_saturation_mean_max;
372 : float palette256_tune_opaque_ratio_threshold;
373 : float palette256_tune_gradient_mean_max;
374 : float palette256_tune_saturation_mean_max;
375 : int16_t palette256_tune_speed_max;
376 : int16_t palette256_tune_quality_min_floor;
377 : int16_t palette256_tune_quality_max_target;
378 : uint32_t thread_count;
379 : } pngx_options_t;
380 :
381 : typedef struct {
382 : uint8_t *data;
383 : size_t size;
384 : size_t capacity;
385 : } png_memory_buffer_t;
386 :
387 : typedef struct {
388 : uint8_t *rgba;
389 : png_uint_32 width;
390 : png_uint_32 height;
391 : size_t pixel_count;
392 : } pngx_rgba_image_t;
393 :
394 : typedef struct {
395 : float gradient_mean;
396 : float gradient_max;
397 : float saturation_mean;
398 : float opaque_ratio;
399 : float translucent_ratio;
400 : float vibrant_ratio;
401 : } pngx_image_stats_t;
402 :
403 : typedef struct {
404 : uint8_t *importance_map;
405 : size_t importance_map_len;
406 : cpres_rgba_color_t *derived_colors;
407 : size_t derived_colors_len;
408 : cpres_rgba_color_t *combined_fixed_colors;
409 : size_t combined_fixed_len;
410 : uint8_t *bit_hint_map;
411 : size_t bit_hint_len;
412 : } pngx_quant_support_t;
413 :
414 : /* from pngx_bridge rust library */
415 : PngxBridgeResult pngx_bridge_optimize_lossless(const uint8_t *input_data, size_t input_size, uint8_t **output_data, size_t *output_size, const PngxBridgeLosslessOptions *options);
416 : PngxBridgeQuantStatus pngx_bridge_quantize(const cpres_rgba_color_t *pixels, size_t pixel_count, uint32_t width, uint32_t height, const PngxBridgeQuantParams *params, PngxBridgeQuantOutput *output);
417 : void pngx_bridge_free(uint8_t *ptr);
418 : uint32_t pngx_bridge_oxipng_version(void);
419 : uint32_t pngx_bridge_libimagequant_version(void);
420 : const char *pngx_bridge_rust_version_string(void);
421 : bool pngx_bridge_init_threads(int num_threads);
422 :
423 : #define PNGX_DEFINE_CLAMP(type) \
424 : static inline type clamp_##type(type value, type min_value, type max_value) { \
425 : assert(min_value <= max_value); \
426 : \
427 : if (value < min_value) { \
428 : return min_value; \
429 : } \
430 : \
431 : if (value > max_value) { \
432 : return max_value; \
433 : } \
434 : \
435 : return value; \
436 : }
437 :
438 24 : PNGX_DEFINE_CLAMP(int32_t);
439 24 : PNGX_DEFINE_CLAMP(uint32_t);
440 37 : PNGX_DEFINE_CLAMP(uint16_t);
441 159 : PNGX_DEFINE_CLAMP(uint8_t);
442 495 : PNGX_DEFINE_CLAMP(float);
443 :
444 : bool pngx_quantize_palette256(const uint8_t *png_data, size_t png_size, const pngx_options_t *opts, uint8_t **out_data, size_t *out_size, int *quant_quality);
445 : bool pngx_palette256_prepare(const uint8_t *png_data, size_t png_size, const pngx_options_t *opts, uint8_t **out_rgba, uint32_t *out_width, uint32_t *out_height, uint8_t **out_importance_map,
446 : size_t *out_importance_map_len, int32_t *out_speed, uint8_t *out_quality_min, uint8_t *out_quality_max, uint32_t *out_max_colors, float *out_dither_level,
447 : uint8_t **out_fixed_colors, size_t *out_fixed_colors_len);
448 : bool pngx_palette256_finalize(const uint8_t *indices, size_t indices_len, const cpres_rgba_color_t *palette, size_t palette_len, uint8_t **out_data, size_t *out_size);
449 : void pngx_palette256_cleanup(void);
450 : bool pngx_create_palette_png(const uint8_t *indices, size_t indices_len, const cpres_rgba_color_t *palette, size_t palette_len, uint32_t width, uint32_t height, uint8_t **out_data, size_t *out_size);
451 : bool create_rgba_png(const uint8_t *rgba, size_t pixel_count, uint32_t width, uint32_t height, uint8_t **out_data, size_t *out_size);
452 : bool pngx_quantize_limited4444(const uint8_t *png_data, size_t png_size, const pngx_options_t *opts, uint8_t **out_data, size_t *out_size);
453 : bool pngx_quantize_reduced_rgba32(const uint8_t *png_data, size_t png_size, const pngx_options_t *opts, uint32_t *resolved_target, uint32_t *applied_colors, uint8_t **out_data, size_t *out_size);
454 : void pngx_fill_pngx_options(pngx_options_t *opts, const cpres_config_t *config);
455 : bool pngx_run_quantization(const uint8_t *png_data, size_t png_size, const pngx_options_t *opts, uint8_t **out_data, size_t *out_size, int *quant_quality);
456 : bool pngx_run_lossless_optimization(const uint8_t *png_data, size_t png_size, const pngx_options_t *opts, uint8_t **out_data, size_t *out_size);
457 : bool pngx_should_attempt_quantization(const pngx_options_t *opts);
458 : bool pngx_quantization_better(size_t baseline_size, size_t candidate_size);
459 :
460 : int pngx_get_last_error(void);
461 : void pngx_set_last_error(int error_code);
462 :
463 : #ifdef __cplusplus
464 : }
465 : #endif
466 :
467 : #endif /* COLOPRESSO_INTERNAL_PNGX_H */
|