如何连接code PNG缓冲的libpng使用? [英] How to encode PNG to buffer using libpng?

查看:110
本文介绍了如何连接code PNG缓冲的libpng使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前使用下面写一个PNG到一个文件:

I'm currently using the following to write a PNG to a file:

#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语言)为en code一个PNG到内存缓冲区?

How can I write a similar function (in C) to encode a PNG to an in-memory buffer?

原型将是这个样子:

uint8_t *encode_png_to_buffer(RGBBitmap *source);

和看来我可能需要做一些使用 png_set_write_fn的()

And it seems that I would probably need to make some use of png_set_write_fn().

但除此之外我不知道如何处理这一点。是否有正在做的任何的例子?当然我不是第一个需要这个功能。

But apart from that I'm not sure how to approach this. Are there any examples of this being done? Surely I'm not the first to need this functionality.

推荐答案

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

Yes, using png_set_write_fn something like this - untested:

更新与评论编辑

/* 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);

这篇关于如何连接code PNG缓冲的libpng使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆