下面是一个使用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助手提供,问题来源于学员提问