C++ 将字符串转换为图像\u T

C++ 将字符串转换为图像\u T,c++,c,image,C++,C,Image,我正在使用raspberry dispmanx开发一个简单的图形应用程序。 我的目标是通过stdin(从一个RGBA数组,格式化为字符串,从一个python应用程序)获取一个png文件,将其转换为dispmanx期望的图像格式以显示它 现在,我只有一个可以从文件中获取PNG的函数,但将图像写入磁盘、将事件写入tmpfs需要太多时间 如何重写此函数以使用字符串作为输入? 我会独自管理这个,但我不知道如何从一个变量模拟一个文件来提供png_ptr和info_ptr #include <png.

我正在使用raspberry dispmanx开发一个简单的图形应用程序。 我的目标是通过stdin(从一个RGBA数组,格式化为字符串,从一个python应用程序)获取一个png文件,将其转换为dispmanx期望的图像格式以显示它

现在,我只有一个可以从文件中获取PNG的函数,但将图像写入磁盘、将事件写入tmpfs需要太多时间

如何重写此函数以使用字符串作为输入? 我会独自管理这个,但我不知道如何从一个变量模拟一个文件来提供png_ptr和info_ptr

#include <png.h>
#include <stdlib.h>
#include "bcm_host.h"
#include "loadpng.h"
//-------------------------------------------------------------------------

#ifndef ALIGN_TO_16
#define ALIGN_TO_16(x) ((x + 15) & ~15)
#endif

//-------------------------------------------------------------------------

bool
loadPngData(
    IMAGE_T* image,
    const char *file)
{
    FILE* fpin = fopen(file, "rb");

    if (fpin == NULL)
    {
        fprintf(stderr, "loadpng: can't open file for reading\n");
        return false;
    }

    //---------------------------------------------------------------------

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                 NULL,
                                                 NULL,
                                                 NULL);

    if (png_ptr == NULL)
    {
        fclose(fpin);
        return false;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);

    if (info_ptr == NULL)
    {
        png_destroy_read_struct(&png_ptr, 0, 0);
        fclose(fpin);
        return false;
    }

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, 0);
        fclose(fpin);
        return false;
    }

    //---------------------------------------------------------------------

    png_init_io(png_ptr, imgdata);

    png_read_info(png_ptr, info_ptr);

    //---------------------------------------------------------------------

    png_byte colour_type = png_get_color_type(png_ptr, info_ptr);
    png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    VC_IMAGE_TYPE_T type = VC_IMAGE_RGB888;

    if (colour_type & PNG_COLOR_MASK_ALPHA)
    {
        type = VC_IMAGE_RGBA32;
    }

    initImage(image,
              type,
              png_get_image_width(png_ptr, info_ptr),
              png_get_image_height(png_ptr, info_ptr),
              false);

    //---------------------------------------------------------------------

    double gamma = 0.0;

    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
    {
        png_set_gamma(png_ptr, 2.2, gamma);
    }

    //---------------------------------------------------------------------

    if (colour_type == PNG_COLOR_TYPE_PALETTE) 
    {
        png_set_palette_to_rgb(png_ptr);
    }

    if ((colour_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8))
    {
        png_set_expand_gray_1_2_4_to_8(png_ptr);
    }

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    {
        png_set_tRNS_to_alpha(png_ptr);
    }

    if (bit_depth == 16)
    {
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
        png_set_scale_16(png_ptr);
#else
        png_set_strip_16(png_ptr);
#endif
    }

    if (colour_type == PNG_COLOR_TYPE_GRAY ||
        colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
        png_set_gray_to_rgb(png_ptr);
    }

    //---------------------------------------------------------------------

    png_read_update_info(png_ptr, info_ptr);

    //---------------------------------------------------------------------

    png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep));

    png_uint_32 j = 0;
    for (j = 0 ; j < image->height ; ++j)
    {
        row_pointers[j] = image->buffer + (j * image->pitch);
    }

    //---------------------------------------------------------------------

    png_read_image(png_ptr, row_pointers);

    //---------------------------------------------------------------------

    fclose(fpin);

    free(row_pointers);

    png_destroy_read_struct(&png_ptr, &info_ptr, 0);

    return true;
}
#包括
#包括
#包括“bcm_host.h”
#包括“loadpng.h”
//-------------------------------------------------------------------------
#ifndef对齐\u至\u 16
#定义对齐到16(x)((x+15)和~15)
#恩迪夫
//-------------------------------------------------------------------------
布尔
载荷Pngdata(
图像_T*图像,
常量字符*文件)
{
文件*fpin=fopen(文件“rb”);
如果(fpin==NULL)
{
fprintf(stderr,“loadpng:无法打开文件进行读取\n”);
返回false;
}
//---------------------------------------------------------------------
png_structp png_ptr=png_create_read_struct(png_LIBPNG_VER_STRING,
无效的
无效的
无效);
如果(png_ptr==NULL)
{
fclose(fpin);
返回false;
}
png_infop info_ptr=png_create_info_struct(png_ptr);
if(info_ptr==NULL)
{
png_destroy_read_struct(&png_ptr,0,0);
fclose(fpin);
返回false;
}
if(setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr,&info_ptr,0);
fclose(fpin);
返回false;
}
//---------------------------------------------------------------------
png_init_io(png_ptr,imgdata);
png_read_info(png_ptr,info_ptr);
//---------------------------------------------------------------------
png_byte color_type=png_get_color_type(png_ptr,info_ptr);
png_字节位深度=png_获取位深度(png_ptr,info_ptr);
VC_IMAGE_TYPE_T TYPE=VC_IMAGE_RGB888;
if(颜色类型和PNG颜色遮罩ALPHA)
{
类型=VC_图像_RGBA32;
}
初始化图像(图像,
类型,
png_获取图像_宽度(png_ptr,info_ptr),
png_获取图像_高度(png_ptr,info_ptr),
假);
//---------------------------------------------------------------------
双伽马=0.0;
if(png_get_gAMA(png_ptr、info_ptr和gamma))
{
png_集_伽马(png_ptr,2.2,伽马);
}
//---------------------------------------------------------------------
if(颜色类型==PNG颜色类型调色板)
{
png_设置_调色板_至_rgb(png_ptr);
}
如果((颜色类型==PNG颜色类型灰色)&&(位深度<8))
{
png_设置_展开_灰色_1_2_4_至_8(png_ptr);
}
如果(png_获取_有效(png_ptr,info_ptr,png_info_tRNS))
{
png_设置_tRNS_至_alpha(png_ptr);
}
如果(位深度==16)
{
#ifdef PNG_READ_SCALE_16_至_8_受支持
png设置比例16(png ptr);
#否则
png_集_带_16(png_ptr);
#恩迪夫
}
如果(颜色类型==PNG颜色类型=灰色||
颜色类型==PNG颜色类型灰色ALPHA)
{
png_设置_灰度_至_rgb(png_ptr);
}
//---------------------------------------------------------------------
png_读取_更新_信息(png_ptr,info_ptr);
//---------------------------------------------------------------------
png_bytepp row_pointers=malloc(图像->高度*sizeof(png_bytep));
png_uint_32 j=0;
对于(j=0;jheight;++j)
{
行指针[j]=image->buffer+(j*image->pitch);
}
//---------------------------------------------------------------------
png_读取_图像(png_ptr,行指针);
//---------------------------------------------------------------------
fclose(fpin);
自由(行指针);
png_destroy_read_struct(&png_ptr,&info_ptr,0);
返回true;
}
编辑:可以从python以原始RGBA格式或png格式(作为带有标题和块的字符串)提供图像。我想原始RGBA会更快(跳过png格式),但使用png字符串修改此函数可能更简单。。。
欢迎提供任何线索

如果可以获取原始RGBA数据,则不需要此函数。此函数用于将压缩的png格式解码为原始RGBA。您可能还需要提供的唯一内容是宽度和高度

现在唯一的问题是什么更有效——将原始的、未压缩的数据发送到C程序或用Python将其编码为PNG,发送编码数据并用C程序解码

这里最大的问题是
png_init_io(png_ptr,fpin)
(我在函数调用中将
imgData
更改为
fpin
,但您可能希望传递数组而不是
文件
句柄)。在中的
libpng
文档中,有一个描述如何为输入/输出提供自己的函数。您必须用自己的函数代替
png\u init\u io
,而不是
FILE*
。这里有一个关于png初始化io的部分:

libpng中的输入/输出是通过png_read()和png_write()完成的,它们目前只调用fread()和fwrite()。文件*存储在png_struct中,并通过png_init_io()初始化。如果希望更改I/O方法,则库提供回调,您可以在运行时通过函数png_set_read_fn()和png_set_write_fn()设置回调,而不是调用png_init_io()函数。这些函数还提供可以通过函数png_get_io_ptr()检索的空指针。例如:

png_set_read_fn(png_structp read_ptr,
    voidp read_io_ptr, png_rw_ptr read_data_fn)

png_set_write_fn(png_structp write_ptr,
    voidp write_io_ptr, png_rw_ptr write_data_fn,
    png_flush_ptr output_flush_fn);

voidp read_io_ptr = png_get_io_ptr(read_ptr);
voidp write_io_ptr = png_get_io_ptr(write_ptr);
替换I/O功能必须具有以下原型:

void user_read_data(png_structp png_ptr,
   png_bytep data, png_size_t length);
void user_write_data(png_structp png_ptr,
    png_bytep data, png_size_t length);
void user_flush_data(png_structp png_ptr);
我从不操纵别人