gpt4 book ai didi

c - 如何使用 libpng 将 PNG 编码为缓冲?

转载 作者:太空狗 更新时间:2023-10-29 16:24:54 24 4
gpt4 key购买 nike

我目前正在使用以下方法将 PNG 写入文件:

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

/* Pixels in this bitmap structure are stored as BGR. */
typedef struct _RGBPixel {
uint8_t blue;
uint8_t green;
uint8_t red;
} RGBPixel;

/* Structure for containing decompressed bitmaps. */
typedef struct _RGBBitmap {
RGBPixel *pixels;
size_t width;
size_t height;
size_t bytewidth;
uint8_t bytes_per_pixel;
} RGBBitmap;

/* Returns pixel of bitmap at given point. */
#define RGBPixelAtPoint(image, x, y) \
*(((image)->pixels) + (((image)->bytewidth * (y)) \
+ ((x) * (image)->bytes_per_pixel)))

/* Attempts to save PNG to file; returns 0 on success, non-zero on error. */
int save_png_to_file(RGBBitmap *bitmap, const char *path)
{
FILE *fp = fopen(path, "wb");
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
png_uint_32 bytes_per_row;
png_byte **row_pointers = NULL;

if (fp == NULL) return -1;

/* Initialize the write struct. */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp);
return -1;
}

/* Initialize the info struct. */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, NULL);
fclose(fp);
return -1;
}

/* Set up error handling. */
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
return -1;
}

/* Set image attributes. */
png_set_IHDR(png_ptr,
info_ptr,
bitmap->width,
bitmap->height,
8,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);

/* Initialize rows of PNG. */
bytes_per_row = bitmap->width * bitmap->bytes_per_pixel;
row_pointers = png_malloc(png_ptr, bitmap->height * sizeof(png_byte *));
for (y = 0; y < bitmap->height; ++y) {
uint8_t *row = png_malloc(png_ptr, sizeof(uint8_t) * bitmap->bytes_per_pixel);
row_pointers[y] = (png_byte *)row;
for (x = 0; x < bitmap->width; ++x) {
RGBPixel color = RGBPixelAtPoint(bitmap, x, y);
*row++ = color.red;
*row++ = color.green;
*row++ = color.blue;
}
}

/* Actually write the image data. */
png_init_io(png_ptr, fp);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

/* Cleanup. */
for (y = 0; y < bitmap->height; y++) {
png_free(png_ptr, row_pointers[y]);
}
png_free(png_ptr, row_pointers);

/* Finish writing. */
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
return 0;
}

我如何编写类似的函数(用 C 语言)将 PNG 编码到内存缓冲区?

原型(prototype)看起来像这样:

uint8_t *encode_png_to_buffer(RGBBitmap *source);

看来我可能需要使用 png_set_write_fn()

但除此之外,我不确定如何处理这个问题。有没有这样做的例子?当然,我不是第一个需要此功能的人。

最佳答案

是的,使用 png_set_write_fn 这样的东西 - 未经测试:

已更新,根据评论进行了修改

/* structure to store PNG image bytes */
struct mem_encode
{
char *buffer;
size_t size;
}


void
my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
/* with libpng15 next line causes pointer deference error; use libpng12 */
struct mem_encode* p=(struct mem_encode*)png_get_io_ptr(png_ptr); /* was png_ptr->io_ptr */
size_t nsize = p->size + length;

/* allocate or grow buffer */
if(p->buffer)
p->buffer = realloc(p->buffer, nsize);
else
p->buffer = malloc(nsize);

if(!p->buffer)
png_error(png_ptr, "Write Error");

/* copy new bytes to end of buffer */
memcpy(p->buffer + p->size, data, length);
p->size += length;
}

/* This is optional but included to show how png_set_write_fn() is called */
void
my_png_flush(png_structp png_ptr)
{
}



int save_png_to_file(RGBBitmap *bitmap, const char *path)
{
...
/* static */
struct mem_encode state;

/* initialise - put this before png_write_png() call */
state.buffer = NULL;
state.size = 0;

/* if my_png_flush() is not needed, change the arg to NULL */
png_set_write_fn(png_ptr, &state, my_png_write_data, my_png_flush);

... call png_write_png() ...

/* now state.buffer contains the PNG image of size s.size bytes */

/* cleanup */
if(state.buffer)
free(state.buffer);

关于c - 如何使用 libpng 将 PNG 编码为缓冲?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1821806/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com