2017-04-10 4 views
0

私は、ラズベリーのdispmanxを使った簡単なグラフィックアプリケーションを開発中です。 私の目標は、stdin(RGBA配列から文字列としてフォーマットされたPythonアプリケーションから)からpngファイルを取得し、それを表示するためにdispmanxが期待するIMAGE_Tフォーマットに変換することです。文字列をIMAGE_Tに変換する

ここでは、ファイルから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; 
} 

編集:イメージは、生のRGBAでのpythonから提供することができますかpng形式で(ヘッダとチャンクを含む文字列として)。私は生のRGBAが速く(PNG形式をスキップする)、しかしこの機能を変更することは、PNG文字列でもっとシンプルになると思います... 手がかりは大歓迎です!

+0

pythonアプリケーションの文字列には、pngファイルまたはRGBAデータのみが含まれていますか?後者の場合は、新しいRGBAデータごとに 'png_infop'構造体を手作業で設定する必要がありますが、おそらく、そこに置くべき値が何であるかは分かりません。また、RGBAデータではなく、圧縮されたPNGデータ – Rogus

+0

問題のあいまいさに気付いたRogusに感謝します。 – technico

答えて

1

生のRGBAデータを取得できる場合は、この機能は必要ありません。この関数は、圧縮されたpng形式をraw RGBAにデコードするために使用されます。おそらく提供する必要があるのは幅と高さだけです。

唯一の問題は、生の圧縮されていないデータをCプログラムに送ること、またはPythonでPNGにコード化し、エンコードされたデータを送信し、Cプログラムでデコードすることです。

ここでの最大の問題はpng_init_io(png_ptr, fpin);です(私は関数呼び出しでfpinimgDataを変更しましたが、あなたはおそらく代わりにFILEハンドルの配列を渡したいです)。 section 5libpngのドキュメントには、自分自身の入出力機能を提供する方法が記載されています。 png_init_ioの代わりに、FILE*の代わりにconst char*と入力する必要があります。ここpng_init_ioの一部です:のlibpngで

入力/出力がpng_readを通じて、現在だけのfread()とfwriteの()を呼び出して()とpng_writeを()、行われます。 FILE *はpng_structに格納され、png_init_io()で初期化されます。 I/Oのメソッドを変更したい場合、ライブラリはpng_init_io()関数を呼び出すのではなく、実行時にpng_set_read_fn()とpng_set_write_fn()関数で設定できるコールバックを提供します。これらの関数は、png_get_io_ptr()関数で取り出すことができるvoidポインタも提供します。たとえば、次のように交換用のI/O機能は、プロトタイプを持っている必要があります

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

は:

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

を私はここであなたを助けることができないので、私はこれらの機能を操作したことがありませんが、それはそうです変更しなければならないのは、ファイルを読み飛ばすだけで、元の実装がファイルで行うのと同じ配列のデータを配列から読み込むことだけです。このセクションを読む必要があります。ソースコードをチェックして、何をすべきかを見て、すでにデコードされたデータを取得する可能性がある場合は、時間がかかると思うかもしれません。

+0

答えのすべての部分をありがとうございます。概要、ドキュメント、コード、アドバイス、これはすべて完璧だった=) – technico

+1

うれしい – Rogus

関連する問題