LCOV - code coverage report
Current view: top level - src - webp.c (source / functions) Coverage Total Hit
Test: colopresso Coverage Report Lines: 81.8 % 77 63
Test Date: 2026-11-09 10:50:48 Functions: 100.0 % 4 4
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-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              : #include <errno.h>
      13              : #include <math.h>
      14              : #include <stdbool.h>
      15              : #include <stdint.h>
      16              : #include <stdio.h>
      17              : #include <stdlib.h>
      18              : #include <string.h>
      19              : 
      20              : #include <webp/encode.h>
      21              : 
      22              : #include <colopresso.h>
      23              : 
      24              : #include "internal/log.h"
      25              : #include "internal/webp.h"
      26              : 
      27              : static int g_last_webp_error = 0;
      28              : 
      29           27 : static void apply_webp_config(WebPConfig *webp_config, const cpres_config_t *config)
      30              : {
      31           27 :     webp_config->quality = config->webp_quality;
      32           27 :     webp_config->target_size = config->webp_target_size;
      33           27 :     webp_config->target_PSNR = config->webp_target_psnr;
      34           27 :     webp_config->method = config->webp_method;
      35           27 :     webp_config->segments = config->webp_segments;
      36           27 :     webp_config->sns_strength = config->webp_sns_strength;
      37           27 :     webp_config->filter_strength = config->webp_filter_strength;
      38           27 :     webp_config->filter_sharpness = config->webp_filter_sharpness;
      39           27 :     webp_config->filter_type = config->webp_filter_type;
      40           27 :     webp_config->autofilter = config->webp_autofilter;
      41           27 :     webp_config->alpha_compression = config->webp_alpha_compression;
      42           27 :     webp_config->alpha_filtering = config->webp_alpha_filtering;
      43           27 :     webp_config->alpha_quality = config->webp_alpha_quality;
      44           27 :     webp_config->pass = config->webp_pass;
      45           27 :     webp_config->preprocessing = config->webp_preprocessing;
      46           27 :     webp_config->partitions = config->webp_partitions;
      47           27 :     webp_config->partition_limit = config->webp_partition_limit;
      48           27 :     webp_config->emulate_jpeg_size = config->webp_emulate_jpeg_size;
      49           27 :     webp_config->thread_level = (config->webp_thread_level > 0) ? 1 : 0;
      50           27 :     webp_config->low_memory = config->webp_low_memory;
      51           27 :     webp_config->near_lossless = config->webp_near_lossless;
      52           27 :     webp_config->exact = config->webp_exact;
      53           27 :     webp_config->use_delta_palette = config->webp_use_delta_palette;
      54           27 :     webp_config->use_sharp_yuv = config->webp_use_sharp_yuv;
      55           27 :     webp_config->lossless = config->webp_lossless;
      56           27 : }
      57              : 
      58            1 : extern int webp_get_last_error(void)
      59              : {
      60            1 :     return g_last_webp_error;
      61              : }
      62              : 
      63           28 : extern void webp_set_last_error(int error_code)
      64              : {
      65           28 :     g_last_webp_error = error_code;
      66           28 : }
      67              : 
      68           30 : extern cpres_error_t webp_encode_rgba_to_memory(uint8_t *rgba_data, uint32_t width, uint32_t height,
      69              :                                                 uint8_t **webp_data, size_t *webp_size,
      70              :                                                 const cpres_config_t *config)
      71              : {
      72              :     WebPConfig webp_config;
      73              :     WebPPicture picture;
      74              :     WebPMemoryWriter writer;
      75              : 
      76           30 :     if (!rgba_data || !webp_data || !webp_size || !config) {
      77            0 :         return CPRES_ERROR_INVALID_PARAMETER;
      78              :     }
      79              : 
      80           30 :     if (!isfinite(config->webp_quality) || !isfinite(config->webp_target_psnr)) {
      81            2 :         return CPRES_ERROR_INVALID_PARAMETER;
      82              :     }
      83              : 
      84           28 :     memset(&webp_config, 0, sizeof(webp_config));
      85           28 :     memset(&picture, 0, sizeof(picture));
      86           28 :     memset(&writer, 0, sizeof(writer));
      87              : 
      88           28 :     colopresso_log(CPRES_LOG_LEVEL_DEBUG, "Starting WebP encoding to memory - %dx%d pixels", width,
      89              :                    height);
      90              : 
      91           28 :     if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, config->webp_quality)) {
      92            1 :         return CPRES_ERROR_INVALID_PARAMETER;
      93              :     }
      94              : 
      95           27 :     apply_webp_config(&webp_config, config);
      96              : 
      97           27 :     if (!WebPValidateConfig(&webp_config)) {
      98            0 :         return CPRES_ERROR_INVALID_PARAMETER;
      99              :     }
     100              : 
     101           27 :     if (!WebPPictureInit(&picture)) {
     102            0 :         return CPRES_ERROR_OUT_OF_MEMORY;
     103              :     }
     104              : 
     105           27 :     picture.width = (int)width;
     106           27 :     picture.height = (int)height;
     107           27 :     picture.use_argb = 1;
     108              : 
     109           27 :     if (!WebPPictureImportRGBA(&picture, rgba_data, width * 4)) {
     110            0 :         WebPPictureFree(&picture);
     111              : 
     112            0 :         return CPRES_ERROR_ENCODE_FAILED;
     113              :     }
     114              : 
     115           27 :     WebPMemoryWriterInit(&writer);
     116           27 :     picture.writer = WebPMemoryWrite;
     117           27 :     picture.custom_ptr = &writer;
     118              : 
     119           27 :     colopresso_log(CPRES_LOG_LEVEL_DEBUG, "Starting WebP encoding (memory)...");
     120              : 
     121           27 :     if (!WebPEncode(&webp_config, &picture)) {
     122            0 :         webp_set_last_error(picture.error_code);
     123            0 :         colopresso_log(CPRES_LOG_LEVEL_ERROR, "WebP encoding failed - error code: %d",
     124            0 :                        picture.error_code);
     125            0 :         WebPMemoryWriterClear(&writer);
     126            0 :         WebPPictureFree(&picture);
     127              : 
     128            0 :         return CPRES_ERROR_ENCODE_FAILED;
     129              :     }
     130              : 
     131           27 :     webp_set_last_error(0);
     132              : 
     133           27 :     colopresso_log(CPRES_LOG_LEVEL_DEBUG, "WebP encoding successful - size: %zu bytes",
     134              :                    writer.size);
     135              : 
     136           27 :     *webp_data = (uint8_t *)malloc(writer.size);
     137           27 :     if (!*webp_data) {
     138            0 :         WebPMemoryWriterClear(&writer);
     139            0 :         WebPPictureFree(&picture);
     140              : 
     141            0 :         return CPRES_ERROR_OUT_OF_MEMORY;
     142              :     }
     143              : 
     144           27 :     memcpy(*webp_data, writer.mem, writer.size);
     145           27 :     *webp_size = writer.size;
     146              : 
     147           27 :     WebPMemoryWriterClear(&writer);
     148           27 :     WebPPictureFree(&picture);
     149              : 
     150           27 :     return CPRES_OK;
     151              : }
        

Generated by: LCOV version 2.0-1