ZBLOG

libimagequant + libpng 实现对png的压缩代码

下面是一个使用libimagequant和libpng进行PNG压缩的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <png.h>
#include <libimagequant.h>

void write_png_file(const char *filename, uint8_t *image_data, int width, int height) {
    FILE *fp = fopen(filename, "wb");
    if (!fp) {
        printf("Error: Failed to open PNG file for writing.\n");
        return;
    }

    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        fclose(fp);
        printf("Error: Failed to create PNG write structure.\n");
        return;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_write_struct(&png_ptr, NULL);
        fclose(fp);
        printf("Error: Failed to create PNG info structure.\n");
        return;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        printf("Error: Error during PNG writing.\n");
        return;
    }

    png_init_io(png_ptr, fp);

    // Set image information
    int color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    
    // Write header
    png_set_IHDR(png_ptr,
                 info_ptr,
                 width,
                 height,
                 8,
                 color_type,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);

     // Initialize rows
     uint8_t **row_pointers = (uint8_t**)malloc(sizeof(uint8_t*) * height);
     for (int y = 0; y < height; ++y) {
         row_pointers[y] = image_data + (width * 4 * y);
     }

     // Write image data
     png_set_rows(png_ptr, info_ptr, (png_bytepp)row_pointers);
     png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

     // Clean up
     png_destroy_write_struct(&png_ptr, &info_ptr);
     fclose(fp);
     free(row_pointers);

    printf("PNG file saved successfully.\n");
}

int main() {
    const char* input_filename = "input.png";
    const char* output_filename = "output.png";

    // Load input PNG image
    FILE *fp = fopen(input_filename, "rb");
    if (!fp) {
        printf("Error: Failed to open input PNG file.\n");
        return -1;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        fclose(fp);
        printf("Error: Failed to create PNG read structure.\n");
        return -1;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        fclose(fp);
        printf("Error: Failed to create PNG info structure.\n");
        return -1;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(fp);
        printf("Error: Error during PNG reading.\n");
        return -1;
    }

    png_init_io(png_ptr, fp);
    
    // Read header information
    int width = 0;
	int height = 0;
	int bit_depth = 0;
	int color_type = 0;
	png_read_info(png_ptr, info_ptr);
	width = png_get_image_width(png_ptr, info_ptr);
	height = png_get_image_height(png_ptr, info_ptr);
	bit_depth = png_get_bit_depth(png_ptr, info_ptr);
	color_type = png_get_color_type(png_ptr, info_ptr);

	// Ensure input image is RGBA (32-bit)
	if (color_type != PNG_COLOR_TYPE_RGBA) {
		printf("Error: Only RGBA input images are supported.\n");
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(fp);
		return -1;
	}

    // Read image data
    uint8_t *image_data = (uint8_t *)malloc(width * height * 4 * sizeof(uint8_t));
    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
    for (int y = 0; y < height; ++y) {
        memcpy(image_data + (width * 4 * y), row_pointers[y], width * 4 * sizeof(uint8_t));
    }

    // Clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);

    // Compress image using libimagequant
	LIQ_RGB* liq_image = liq_image_create_rgba(NULL, width, height, image_data, 0);

	liq_attr* liq_attribute = liq_attr_create();
	liq_result* liq_quantization_result;

	if (LIQ_OK != liq_set_quality(liq_attribute, 70 /* minimum quality */)) {
	    printf("Error: Failed to set quality level for libimagequant.\n");
	    return -1;
	}

	if (LIQ_OK != (liq_quantization_result=liq_quantize_image(liq_attribute,
										  			  liq_image))) {
	    printf("Error: Failed to quantize image with libimagequant.\n");
	    return -1;
	}

	liq_set_dithering_level(liq_quantization_result, 1.0);

	uint8_t *output_image_data = malloc(width * height * sizeof(uint8_t));
	liq_write_remapped_image(liq_quantization_result, liq_image,
							  output_image_data, width * height * sizeof(uint8_t));

	liq_attr_destroy(liq_attribute);
	liq_result_destroy(liq_quantization_result);
    liq_image_destroy(liq_image);
    free(image_data);

    // Write compressed image to output PNG file
    write_png_file(output_filename, output_image_data, width, height);

    free(output_image_data);

    return 0;
}

请注意,上述代码需要链接libimagequant和libpng库,并且您需要在编译时指定这些库的路径和名称。此外,还应该处理错误和内存管理等其他细节。这只是一个简单示例,用于演示如何使用libimagequant和libpng进行PNG压缩。实际应用中可能需要更多的逻辑和优化。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=2414

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?