LCOV - code coverage report
Current view: top level - src - pngx.c (source / functions) Coverage Total Hit
Test: colopresso Coverage Report Lines: 91.4 % 210 192
Test Date: 2025-12-13 15:41:21 Functions: 100.0 % 7 7
Legend: Lines: hit not hit

            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 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              : #include <colopresso.h>
      13              : 
      14              : #include <stdbool.h>
      15              : #include <stddef.h>
      16              : #include <stdint.h>
      17              : #include <string.h>
      18              : 
      19              : #include "internal/log.h"
      20              : #include "internal/pngx_common.h"
      21              : 
      22              : static int g_pngx_last_error = 0;
      23              : 
      24            1 : int pngx_get_last_error(void) { return g_pngx_last_error; }
      25              : 
      26           81 : void pngx_set_last_error(int error_code) { g_pngx_last_error = error_code; }
      27              : 
      28           31 : 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) {
      29              :   const char *label;
      30           31 :   uint32_t resolved_colors = 0;
      31           31 :   uint32_t applied_colors = 0;
      32              :   bool success;
      33              : 
      34           31 :   if (!png_data || png_size == 0 || !opts || !out_data || !out_size) {
      35            0 :     return false;
      36              :   }
      37              : 
      38           31 :   *out_data = NULL;
      39           31 :   *out_size = 0;
      40           31 :   if (quant_quality) {
      41           31 :     *quant_quality = -1;
      42              :   }
      43              : 
      44           31 :   if (opts->lossy_type == PNGX_LOSSY_TYPE_REDUCED_RGBA32) {
      45            5 :     success = pngx_quantize_reduced_rgba32(png_data, png_size, opts, &resolved_colors, &applied_colors, out_data, out_size);
      46            5 :     if (success) {
      47            5 :       label = lossy_type_label(opts->lossy_type);
      48            5 :       cpres_log(CPRES_LOG_LEVEL_DEBUG, "PNGX: %s target %u colors -> %u unique", label, resolved_colors, applied_colors);
      49              :     }
      50            5 :     return success;
      51              :   }
      52              : 
      53           26 :   if (opts->lossy_type == PNGX_LOSSY_TYPE_LIMITED_RGBA4444) {
      54            3 :     return pngx_quantize_limited4444(png_data, png_size, opts, out_data, out_size);
      55              :   }
      56              : 
      57           23 :   return pngx_quantize_palette256(png_data, png_size, opts, out_data, out_size, quant_quality);
      58              : }
      59              : 
      60           37 : void pngx_fill_pngx_options(pngx_options_t *opts, const cpres_config_t *config) {
      61           37 :   uint16_t lossy_max_colors = COLOPRESSO_PNGX_DEFAULT_LOSSY_MAX_COLORS, palette256_alpha_bleed_max_distance = COLOPRESSO_PNGX_DEFAULT_PALETTE256_ALPHA_BLEED_MAX_DISTANCE;
      62           37 :   uint8_t level = COLOPRESSO_PNGX_DEFAULT_LEVEL, lossy_quality_min = COLOPRESSO_PNGX_DEFAULT_LOSSY_QUALITY_MIN, lossy_quality_max = COLOPRESSO_PNGX_DEFAULT_LOSSY_QUALITY_MAX,
      63           37 :           lossy_speed = COLOPRESSO_PNGX_DEFAULT_LOSSY_SPEED, lossy_type = COLOPRESSO_PNGX_DEFAULT_LOSSY_TYPE, lossy_reduced_bits_rgb = COLOPRESSO_PNGX_DEFAULT_REDUCED_BITS_RGB,
      64           37 :           lossy_reduced_bits_alpha = COLOPRESSO_PNGX_DEFAULT_REDUCED_ALPHA_BITS, tmp, palette256_alpha_bleed_opaque_threshold = COLOPRESSO_PNGX_DEFAULT_PALETTE256_ALPHA_BLEED_OPAQUE_THRESHOLD,
      65           37 :           palette256_alpha_bleed_soft_limit = COLOPRESSO_PNGX_DEFAULT_PALETTE256_ALPHA_BLEED_SOFT_LIMIT;
      66           37 :   int32_t lossy_reduced_colors = COLOPRESSO_PNGX_DEFAULT_REDUCED_COLORS, clamped;
      67           37 :   int16_t palette256_tune_speed_max = PNGX_PALETTE256_TUNE_SPEED_MAX, palette256_tune_quality_min_floor = PNGX_PALETTE256_TUNE_QUALITY_MIN_FLOOR,
      68           37 :           palette256_tune_quality_max_target = PNGX_PALETTE256_TUNE_QUALITY_MAX_TARGET;
      69           37 :   bool strip_safe = COLOPRESSO_PNGX_DEFAULT_STRIP_SAFE, optimize_alpha = COLOPRESSO_PNGX_DEFAULT_OPTIMIZE_ALPHA, lossy_enable = COLOPRESSO_PNGX_DEFAULT_LOSSY_ENABLE, lossy_dither_auto = false,
      70           37 :        saliency_map_enable = COLOPRESSO_PNGX_DEFAULT_SALIENCY_MAP_ENABLE, chroma_anchor_enable = COLOPRESSO_PNGX_DEFAULT_CHROMA_ANCHOR_ENABLE,
      71           37 :        adaptive_dither_enable = COLOPRESSO_PNGX_DEFAULT_ADAPTIVE_DITHER_ENABLE, gradient_boost_enable = COLOPRESSO_PNGX_DEFAULT_GRADIENT_BOOST_ENABLE,
      72           37 :        chroma_weight_enable = COLOPRESSO_PNGX_DEFAULT_CHROMA_WEIGHT_ENABLE, postprocess_smooth_enable = COLOPRESSO_PNGX_DEFAULT_POSTPROCESS_SMOOTH_ENABLE,
      73           37 :        palette256_gradient_profile_enable = COLOPRESSO_PNGX_DEFAULT_PALETTE256_GRADIENT_PROFILE_ENABLE, palette256_alpha_bleed_enable = COLOPRESSO_PNGX_DEFAULT_PALETTE256_ALPHA_BLEED_ENABLE;
      74           37 :   float lossy_dither_level = COLOPRESSO_PNGX_DEFAULT_LOSSY_DITHER_LEVEL, postprocess_smooth_importance_cutoff = COLOPRESSO_PNGX_DEFAULT_POSTPROCESS_SMOOTH_IMPORTANCE_CUTOFF,
      75           37 :         palette256_gradient_profile_dither_floor = PNGX_PALETTE256_GRADIENT_PROFILE_DITHER_FLOOR, palette256_profile_opaque_ratio_threshold = PNGX_PALETTE256_GRADIENT_PROFILE_OPAQUE_RATIO_THRESHOLD,
      76           37 :         palette256_profile_gradient_mean_max = PNGX_PALETTE256_GRADIENT_PROFILE_GRADIENT_MEAN_MAX, palette256_profile_saturation_mean_max = PNGX_PALETTE256_GRADIENT_PROFILE_SATURATION_MEAN_MAX,
      77           37 :         palette256_tune_opaque_ratio_threshold = PNGX_PALETTE256_TUNE_OPAQUE_RATIO_THRESHOLD, palette256_tune_gradient_mean_max = PNGX_PALETTE256_TUNE_GRADIENT_MEAN_MAX,
      78           37 :         palette256_tune_saturation_mean_max = PNGX_PALETTE256_TUNE_SATURATION_MEAN_MAX;
      79              : 
      80           37 :   if (!opts) {
      81            0 :     return;
      82              :   }
      83              : 
      84           37 :   if (config) {
      85           37 :     if (config->pngx_level >= 0 && config->pngx_level <= 6) {
      86           37 :       level = (uint8_t)config->pngx_level;
      87              :     }
      88           37 :     strip_safe = config->pngx_strip_safe;
      89           37 :     optimize_alpha = config->pngx_optimize_alpha;
      90           37 :     lossy_enable = config->pngx_lossy_enable;
      91           37 :     if (config->pngx_lossy_type >= CPRES_PNGX_LOSSY_TYPE_PALETTE256 && config->pngx_lossy_type <= CPRES_PNGX_LOSSY_TYPE_REDUCED_RGBA32) {
      92           37 :       lossy_type = (uint8_t)config->pngx_lossy_type;
      93              :     }
      94              : 
      95           37 :     if (config->pngx_lossy_max_colors > 0 && config->pngx_lossy_max_colors <= 256) {
      96           36 :       lossy_max_colors = (uint16_t)config->pngx_lossy_max_colors;
      97              :     }
      98           37 :     if (config->pngx_lossy_reduced_colors == COLOPRESSO_PNGX_DEFAULT_REDUCED_COLORS) {
      99           32 :       lossy_reduced_colors = COLOPRESSO_PNGX_DEFAULT_REDUCED_COLORS;
     100            5 :     } else if (config->pngx_lossy_reduced_colors >= (int32_t)COLOPRESSO_PNGX_REDUCED_COLORS_MIN) {
     101            2 :       clamped = config->pngx_lossy_reduced_colors;
     102            2 :       if (clamped > (int32_t)COLOPRESSO_PNGX_REDUCED_COLORS_MAX) {
     103            0 :         clamped = (int32_t)COLOPRESSO_PNGX_REDUCED_COLORS_MAX;
     104              :       }
     105              : 
     106            2 :       lossy_reduced_colors = clamped;
     107              :     }
     108           37 :     if (config->pngx_lossy_reduced_bits_rgb >= COLOPRESSO_PNGX_REDUCED_BITS_MIN && config->pngx_lossy_reduced_bits_rgb <= COLOPRESSO_PNGX_REDUCED_BITS_MAX) {
     109           37 :       lossy_reduced_bits_rgb = (uint8_t)config->pngx_lossy_reduced_bits_rgb;
     110              :     }
     111           37 :     if (config->pngx_lossy_reduced_alpha_bits >= COLOPRESSO_PNGX_REDUCED_BITS_MIN && config->pngx_lossy_reduced_alpha_bits <= COLOPRESSO_PNGX_REDUCED_BITS_MAX) {
     112           37 :       lossy_reduced_bits_alpha = (uint8_t)config->pngx_lossy_reduced_alpha_bits;
     113              :     }
     114           37 :     if (config->pngx_lossy_quality_min >= 0 && config->pngx_lossy_quality_min <= 100) {
     115           36 :       lossy_quality_min = (uint8_t)config->pngx_lossy_quality_min;
     116              :     }
     117           37 :     if (config->pngx_lossy_quality_max >= 0 && config->pngx_lossy_quality_max <= 100) {
     118           36 :       lossy_quality_max = (uint8_t)config->pngx_lossy_quality_max;
     119              :     }
     120           37 :     if (lossy_quality_max < lossy_quality_min) {
     121            1 :       tmp = lossy_quality_min;
     122            1 :       lossy_quality_min = lossy_quality_max;
     123            1 :       lossy_quality_max = tmp;
     124              :     }
     125           37 :     if (config->pngx_lossy_speed >= 1 && config->pngx_lossy_speed <= 10) {
     126           36 :       lossy_speed = (uint8_t)config->pngx_lossy_speed;
     127              :     }
     128           37 :     if (config->pngx_lossy_dither_level < 0.0f) {
     129            1 :       lossy_dither_auto = true;
     130           36 :     } else if (config->pngx_lossy_dither_level <= 1.0f) {
     131           35 :       lossy_dither_level = config->pngx_lossy_dither_level;
     132              :     }
     133           37 :     if (config->pngx_protected_colors && config->pngx_protected_colors_count > 0) {
     134            2 :       opts->protected_colors = config->pngx_protected_colors;
     135            2 :       opts->protected_colors_count = config->pngx_protected_colors_count;
     136              :     } else {
     137           35 :       opts->protected_colors = NULL;
     138           35 :       opts->protected_colors_count = 0;
     139              :     }
     140              : 
     141           37 :     saliency_map_enable = config->pngx_saliency_map_enable;
     142           37 :     chroma_anchor_enable = config->pngx_chroma_anchor_enable;
     143           37 :     adaptive_dither_enable = config->pngx_adaptive_dither_enable;
     144           37 :     gradient_boost_enable = config->pngx_gradient_boost_enable;
     145           37 :     chroma_weight_enable = config->pngx_chroma_weight_enable;
     146           37 :     postprocess_smooth_enable = config->pngx_postprocess_smooth_enable;
     147           37 :     postprocess_smooth_importance_cutoff = config->pngx_postprocess_smooth_importance_cutoff;
     148              : 
     149           37 :     palette256_gradient_profile_enable = config->pngx_palette256_gradient_profile_enable;
     150           37 :     if (config->pngx_palette256_gradient_dither_floor >= 0.0f && config->pngx_palette256_gradient_dither_floor <= 1.0f) {
     151           37 :       palette256_gradient_profile_dither_floor = config->pngx_palette256_gradient_dither_floor;
     152              :     }
     153           37 :     palette256_alpha_bleed_enable = config->pngx_palette256_alpha_bleed_enable;
     154              : 
     155           37 :     if (config->pngx_palette256_alpha_bleed_max_distance >= 0 && config->pngx_palette256_alpha_bleed_max_distance <= 65535) {
     156           37 :       palette256_alpha_bleed_max_distance = (uint16_t)config->pngx_palette256_alpha_bleed_max_distance;
     157              :     }
     158           37 :     if (config->pngx_palette256_alpha_bleed_opaque_threshold >= 0 && config->pngx_palette256_alpha_bleed_opaque_threshold <= 255) {
     159           37 :       palette256_alpha_bleed_opaque_threshold = (uint8_t)config->pngx_palette256_alpha_bleed_opaque_threshold;
     160              :     }
     161           37 :     if (config->pngx_palette256_alpha_bleed_soft_limit >= 0 && config->pngx_palette256_alpha_bleed_soft_limit <= 255) {
     162           37 :       palette256_alpha_bleed_soft_limit = (uint8_t)config->pngx_palette256_alpha_bleed_soft_limit;
     163              :     }
     164              : 
     165           37 :     if (config->pngx_palette256_profile_opaque_ratio_threshold >= 0.0f && config->pngx_palette256_profile_opaque_ratio_threshold <= 1.0f) {
     166           36 :       palette256_profile_opaque_ratio_threshold = config->pngx_palette256_profile_opaque_ratio_threshold;
     167              :     }
     168           37 :     if (config->pngx_palette256_profile_gradient_mean_max >= 0.0f && config->pngx_palette256_profile_gradient_mean_max <= 1.0f) {
     169           36 :       palette256_profile_gradient_mean_max = config->pngx_palette256_profile_gradient_mean_max;
     170              :     }
     171           37 :     if (config->pngx_palette256_profile_saturation_mean_max >= 0.0f && config->pngx_palette256_profile_saturation_mean_max <= 1.0f) {
     172           36 :       palette256_profile_saturation_mean_max = config->pngx_palette256_profile_saturation_mean_max;
     173              :     }
     174              : 
     175           37 :     if (config->pngx_palette256_tune_opaque_ratio_threshold >= 0.0f && config->pngx_palette256_tune_opaque_ratio_threshold <= 1.0f) {
     176           37 :       palette256_tune_opaque_ratio_threshold = config->pngx_palette256_tune_opaque_ratio_threshold;
     177              :     }
     178           37 :     if (config->pngx_palette256_tune_gradient_mean_max >= 0.0f && config->pngx_palette256_tune_gradient_mean_max <= 1.0f) {
     179           37 :       palette256_tune_gradient_mean_max = config->pngx_palette256_tune_gradient_mean_max;
     180              :     }
     181           37 :     if (config->pngx_palette256_tune_saturation_mean_max >= 0.0f && config->pngx_palette256_tune_saturation_mean_max <= 1.0f) {
     182           37 :       palette256_tune_saturation_mean_max = config->pngx_palette256_tune_saturation_mean_max;
     183              :     }
     184              : 
     185           37 :     if (config->pngx_palette256_tune_speed_max >= 1 && config->pngx_palette256_tune_speed_max <= 10) {
     186           37 :       palette256_tune_speed_max = (int16_t)config->pngx_palette256_tune_speed_max;
     187              :     }
     188           37 :     if (config->pngx_palette256_tune_quality_min_floor >= 0 && config->pngx_palette256_tune_quality_min_floor <= 100) {
     189           37 :       palette256_tune_quality_min_floor = (int16_t)config->pngx_palette256_tune_quality_min_floor;
     190              :     }
     191           37 :     if (config->pngx_palette256_tune_quality_max_target >= 0 && config->pngx_palette256_tune_quality_max_target <= 100) {
     192           37 :       palette256_tune_quality_max_target = (int16_t)config->pngx_palette256_tune_quality_max_target;
     193              :     }
     194              :   } else {
     195            0 :     opts->protected_colors = NULL;
     196            0 :     opts->protected_colors_count = 0;
     197              :   }
     198              : 
     199           37 :   lossy_quality_min = clamp_uint8_t(lossy_quality_min, 0, 100);
     200           37 :   lossy_quality_max = clamp_uint8_t(lossy_quality_max, lossy_quality_min, 100);
     201           37 :   lossy_speed = clamp_uint8_t(lossy_speed, 1, 10);
     202           37 :   lossy_max_colors = clamp_uint16_t(lossy_max_colors, 2, 256);
     203           37 :   lossy_dither_level = clamp_float(lossy_dither_level, 0.0f, 1.0f);
     204           37 :   lossy_reduced_bits_rgb = clamp_reduced_bits(lossy_reduced_bits_rgb);
     205           37 :   lossy_reduced_bits_alpha = clamp_reduced_bits(lossy_reduced_bits_alpha);
     206           37 :   if (postprocess_smooth_importance_cutoff < 0.0f) {
     207            1 :     postprocess_smooth_importance_cutoff = -1.0f;
     208              :   } else {
     209           36 :     postprocess_smooth_importance_cutoff = clamp_float(postprocess_smooth_importance_cutoff, 0.0f, 1.0f);
     210              :   }
     211              : 
     212           37 :   if (palette256_gradient_profile_dither_floor < 0.0f) {
     213            0 :     palette256_gradient_profile_dither_floor = -1.0f;
     214              :   } else {
     215           37 :     palette256_gradient_profile_dither_floor = clamp_float(palette256_gradient_profile_dither_floor, 0.0f, 1.0f);
     216              :   }
     217              : 
     218           37 :   if (palette256_profile_opaque_ratio_threshold < 0.0f) {
     219            0 :     palette256_profile_opaque_ratio_threshold = -1.0f;
     220              :   } else {
     221           37 :     palette256_profile_opaque_ratio_threshold = clamp_float(palette256_profile_opaque_ratio_threshold, 0.0f, 1.0f);
     222              :   }
     223           37 :   if (palette256_profile_gradient_mean_max < 0.0f) {
     224            0 :     palette256_profile_gradient_mean_max = -1.0f;
     225              :   } else {
     226           37 :     palette256_profile_gradient_mean_max = clamp_float(palette256_profile_gradient_mean_max, 0.0f, 1.0f);
     227              :   }
     228           37 :   if (palette256_profile_saturation_mean_max < 0.0f) {
     229            0 :     palette256_profile_saturation_mean_max = -1.0f;
     230              :   } else {
     231           37 :     palette256_profile_saturation_mean_max = clamp_float(palette256_profile_saturation_mean_max, 0.0f, 1.0f);
     232              :   }
     233              : 
     234           37 :   if (palette256_tune_opaque_ratio_threshold < 0.0f) {
     235            0 :     palette256_tune_opaque_ratio_threshold = -1.0f;
     236              :   } else {
     237           37 :     palette256_tune_opaque_ratio_threshold = clamp_float(palette256_tune_opaque_ratio_threshold, 0.0f, 1.0f);
     238              :   }
     239           37 :   if (palette256_tune_gradient_mean_max < 0.0f) {
     240            0 :     palette256_tune_gradient_mean_max = -1.0f;
     241              :   } else {
     242           37 :     palette256_tune_gradient_mean_max = clamp_float(palette256_tune_gradient_mean_max, 0.0f, 1.0f);
     243              :   }
     244           37 :   if (palette256_tune_saturation_mean_max < 0.0f) {
     245            0 :     palette256_tune_saturation_mean_max = -1.0f;
     246              :   } else {
     247           37 :     palette256_tune_saturation_mean_max = clamp_float(palette256_tune_saturation_mean_max, 0.0f, 1.0f);
     248              :   }
     249              : 
     250           37 :   if (palette256_tune_speed_max < -1) {
     251            0 :     palette256_tune_speed_max = -1;
     252              :   }
     253           37 :   if (palette256_tune_quality_min_floor < -1) {
     254            0 :     palette256_tune_quality_min_floor = -1;
     255              :   }
     256           37 :   if (palette256_tune_quality_max_target < -1) {
     257            0 :     palette256_tune_quality_max_target = -1;
     258              :   }
     259              : 
     260           37 :   opts->bridge.optimization_level = level;
     261           37 :   opts->bridge.strip_safe = strip_safe;
     262           37 :   opts->bridge.optimize_alpha = optimize_alpha;
     263           37 :   opts->lossy_enable = lossy_enable;
     264           37 :   opts->lossy_type = lossy_type;
     265           37 :   opts->lossy_max_colors = lossy_max_colors;
     266           37 :   opts->lossy_reduced_colors = lossy_reduced_colors;
     267           37 :   opts->lossy_reduced_bits_rgb = lossy_reduced_bits_rgb;
     268           37 :   opts->lossy_reduced_alpha_bits = lossy_reduced_bits_alpha;
     269           37 :   opts->lossy_quality_min = lossy_quality_min;
     270           37 :   opts->lossy_quality_max = lossy_quality_max;
     271           37 :   opts->lossy_speed = lossy_speed;
     272           37 :   opts->lossy_dither_level = lossy_dither_level;
     273           37 :   opts->lossy_dither_auto = lossy_dither_auto;
     274           37 :   opts->saliency_map_enable = saliency_map_enable;
     275           37 :   opts->chroma_anchor_enable = chroma_anchor_enable;
     276           37 :   opts->adaptive_dither_enable = adaptive_dither_enable;
     277           37 :   opts->gradient_boost_enable = gradient_boost_enable;
     278           37 :   opts->chroma_weight_enable = chroma_weight_enable;
     279           37 :   opts->postprocess_smooth_enable = postprocess_smooth_enable;
     280           37 :   opts->postprocess_smooth_importance_cutoff = postprocess_smooth_importance_cutoff;
     281           37 :   opts->palette256_gradient_profile_enable = palette256_gradient_profile_enable;
     282           37 :   opts->palette256_gradient_profile_dither_floor = palette256_gradient_profile_dither_floor;
     283           37 :   opts->palette256_alpha_bleed_enable = palette256_alpha_bleed_enable;
     284           37 :   opts->palette256_alpha_bleed_max_distance = palette256_alpha_bleed_max_distance;
     285           37 :   opts->palette256_alpha_bleed_opaque_threshold = palette256_alpha_bleed_opaque_threshold;
     286           37 :   opts->palette256_alpha_bleed_soft_limit = palette256_alpha_bleed_soft_limit;
     287           37 :   opts->palette256_profile_opaque_ratio_threshold = palette256_profile_opaque_ratio_threshold;
     288           37 :   opts->palette256_profile_gradient_mean_max = palette256_profile_gradient_mean_max;
     289           37 :   opts->palette256_profile_saturation_mean_max = palette256_profile_saturation_mean_max;
     290           37 :   opts->palette256_tune_opaque_ratio_threshold = palette256_tune_opaque_ratio_threshold;
     291           37 :   opts->palette256_tune_gradient_mean_max = palette256_tune_gradient_mean_max;
     292           37 :   opts->palette256_tune_saturation_mean_max = palette256_tune_saturation_mean_max;
     293           37 :   opts->palette256_tune_speed_max = palette256_tune_speed_max;
     294           37 :   opts->palette256_tune_quality_min_floor = palette256_tune_quality_min_floor;
     295           37 :   opts->palette256_tune_quality_max_target = palette256_tune_quality_max_target;
     296              : }
     297              : 
     298           54 : 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) {
     299              :   PngxBridgeLosslessOptions lossless;
     300              :   PngxBridgeResult result;
     301              : 
     302           54 :   if (!png_data || png_size == 0 || !opts || !out_data || !out_size) {
     303            0 :     return false;
     304              :   }
     305              : 
     306           54 :   *out_data = NULL;
     307           54 :   *out_size = 0;
     308              : 
     309           54 :   memset(&lossless, 0, sizeof(lossless));
     310           54 :   lossless.optimization_level = opts->bridge.optimization_level;
     311           54 :   lossless.strip_safe = opts->bridge.strip_safe;
     312           54 :   lossless.optimize_alpha = opts->bridge.optimize_alpha;
     313           54 :   result = pngx_bridge_optimize_lossless(png_data, png_size, out_data, out_size, &lossless);
     314           54 :   pngx_set_last_error((int)result);
     315              : 
     316           54 :   if (result != PNGX_BRIDGE_RESULT_SUCCESS) {
     317            0 :     return false;
     318              :   }
     319              : 
     320           54 :   return true;
     321              : }
     322              : 
     323           31 : bool pngx_should_attempt_quantization(const pngx_options_t *opts) {
     324           31 :   if (!opts) {
     325            0 :     return false;
     326              :   }
     327              : 
     328           31 :   return opts->lossy_enable;
     329              : }
     330              : 
     331           23 : bool pngx_quantization_better(size_t baseline_size, size_t candidate_size) { return candidate_size == 0 ? false : (baseline_size == 0 ? true : candidate_size < baseline_size); }
        

Generated by: LCOV version 2.0-1