2

この質問は以前に尋ねられたことを知っています。元のスレッドは、16 ビット RGB フレーム バッファを表示可能な形式に変換する方法です。しかし、私は自分の欲望の出力を得ていません。

現在、私はフレームバッファを扱っています。正確な図は、(「adb」シェルを介して) Android 携帯のフレーム バッファー (/dev/graphics/fb0) にアクセスしていることです。フレームバッファを取得するために「dd」を使用しました。

cd /dev/graphics

dd if=fb0 of=/sdcard/fb0.raw bs=1 count=width*height*3 //this width and height are based on mobile screen specification. And 3 is for RGB888

私はこのコードを使用しました -

#include <stdio.h>
#include <stdlib.h>
#include <bmpfile.h>

int main(int argc, char **argv)
{
bmpfile_t *bmp;
int i, j;
char* infilename;
FILE* infile;
char* outfile;
int width;
int height;
int depth;
unsigned char red, green, blue; // 8-bits each
unsigned short pixel; // 16-bits per pixel
//rgb_pixel_t bpixel = {128, 64, 0, 0};
//make && ./raw565tobmp fb.rgb565 720 480 32 fb.bmp && gnome-open fb.bmp

if (argc < 6) {
printf("Usage: %s infile width height depth outfile.\n", argv[0]);
exit(EXIT_FAILURE);
}

infilename = argv[1];
outfile = argv[5];

infile = fopen(infilename, "rb");
if (NULL == infile) {
perror("Couldn't read infile");
exit(EXIT_FAILURE);
}

width = atoi(argv[2]);
height = atoi(argv[3]);
depth = atoi(argv[4]);

// should be depth/8 at 16-bit depth, but 32-bit depth works better
short buffer[height*width*(depth/16)];
printf("depth: %d", depth);
if (fread(&buffer, 1, height*width*(depth/16), infile) != height*width*(depth/16)) {
 fputs("infile dimensions don't match the size you supplied\n", stderr);
}
printf("depth: %d", depth);

if ((bmp = bmp_create(width, height, depth)) == NULL) {
printf("Invalid depth value: '%d'. Try 1, 4, 8, 16, 24, or 32.\n", depth);
exit(EXIT_FAILURE);
}

for (i = 0; i < width; ++i) { // 720
 for (j = 0; j < height; ++j ) { // 480
  pixel = buffer[width*j+i];

  red = (unsigned short)((pixel & 0xFF0000) >> 16);  // 8
  green = (unsigned short)((pixel & 0x00FF00) >> 8); // 8
  blue = (unsigned short)(pixel & 0x0000FF);         // 8

  rgb_pixel_t bpixel = {blue, green, red, 0};
  bmp_set_pixel(bmp, i, j, bpixel);
  }
}

bmp_save(bmp, outfile);
bmp_destroy(bmp);

return 0;
}

このプログラムの入力 - ./a.out fb0.raw 480 854 24 /data/new.bmp

argv[1]=入力ファイル

argv[2]=幅

argv[3]=高さ

argv[4]=深さ

argv[5]=出力ファイル

元々、コードはここに示されています。16 ビット RGB フレーム バッファを表示可能な形式に変換する方法は?

ここで bmp ファイルを開いた後、すべてがBLACKになっています。これはなぜですか?

フレームバッファを表示する方法は?

4

4 に答える 4

2

車輪の再発明を避けるために、既存のツールを再利用しようとしました。

  1. フレーム バッファを取得します。

    adb pull /dev/graphics/fb0 androidFB
    
  2. フレームバッファファイルで使用されている形式を見つけてください。私はその目的のためにユーティリティ avconv を使用します (ただし、ffmpeg を使用することもできます)。自家製のスクリプトに関連付けられています。

    #!/bin/bash
    
    #Change FB_RESOLUTION value by the android device's resolution
    FB_RESOLUTION=240x320
    OUTPUT_DIR=fbresult
    
    #format come from: avconv -pix_fmts| cut -f 2 -d " "
    format=(yuv420p yuyv422 rgb24 bgr24 yuv422p yuv444p yuv410p yuv411p gray monow monob pal8 yuvj420p yuvj422p yuvj444p xvmcmc xvmcidct uyvy422 uyyvyy411 bgr8 bgr4 bgr4_byte rgb8 rgb4 rgb4_byte nv12 nv21 argb rgba abgr bgra gray16be gray16le yuv440p yuvj440p yuva420p vdpau_h264 vdpau_mpeg1 vdpau_mpeg2 vdpau_wmv3 vdpau_vc1 rgb48be rgb48le rgb565be rgb565le rgb555be rgb555le bgr565be bgr565le bgr555be bgr555le vaapi_moco vaapi_idct vaapi_vld yuv420p16le yuv420p16be yuv422p16le yuv422p16be yuv444p16le yuv444p16be vdpau_mpeg4 dxva2_vld rgb444le rgb444be bgr444le bgr444be y400a bgr48be bgr48le yuv420p9be yuv420p9le yuv420p10be yuv420p10le yuv422p10be yuv422p10le yuv444p9be yuv444p9le yuv444p10be yuv444p10le yuv422p9be yuv422p9le vda_vld gbrp gbrp9be gbrp9le gbrp10be gbrp10le gbrp16be gbrp16le)
    
    
    mkdir $OUTPUT_DIR
    
    for item in ${format[*]}
    do
        #Loop through operation   
        avconv -vframes 1 -f rawvideo -pix_fmt $item -s $FB_RESOLUTION -i androidFB $OUTPUT_DIR/$item.png
    done
    
  3. OUTPUT_DIR ディレクトリを参照して、適切な外観の画像を見つけます。ファイルの名前は使用する形式です: XXXX.png 使用する形式は XXXX になります

  4. 以下のコマンドを使用して、PNG のフレームバッファを変換できるようになりました (解像度 FB_RESOLUTION を置き換え、XXXX を正しい値でフォーマットすることを忘れないでください)。

    avconv -vframes 1 -f rawvideo -pix_fmt XXXX -s FB_RESOLUTION -i androidFB androidFB.png
    
于 2013-06-05T09:40:59.030 に答える
2

Android 2.3.4 のモバイル画面イメージをキャプチャしようとしましたが、同じ問題がありました。最初はいくつかのツールを試していましたが、すべてが複雑でした。

ジョーはパディングについての手がかりをくれたので、ファイル内の生のフレームバッファを読み込んでGIMPでロードしようとしました(現時点では、そのためのソフトウェアを作成することに興味はありません。おそらく後で)。

GIMP の raw インポート パラメータをいじってみたところ、パディングを使用すると、240x320 の画面の幅は実際には 256x320 で、右側に透明なパディングがあることがわかりました。また、RGB ではなく「RGB アルファ」生タイプでした。

私が取り組んでいるのはマニュアルであるため、古い Android バージョンでこれを動作させるには、以下と GIMP を併用するだけで十分でした。

adb shell "cat /dev/graphics/fb0 > /mnt/sdcard/documents/devimages/$1.data"
adb pull /mnt/sdcard/documents/devimages/$1.data
adb shell "rm /mnt/sdcard/documents/devimages/$1.data"

これが誰かに役立つことを願っています:-)

于 2014-09-02T03:59:44.767 に答える
1

多くの利便性と機能性を得るために、Android 用の OpenCV ポートを使用できます。それは最も単純なことの1つです。プロジェクトでnaticeコードを使用しているので、それほど問題になるとは思いません。

私の記憶が正しければ、関数の名前imwrite()と場所は HighGui.hpp です。

ここで OpenCV の Android ポートを見つけることができます: http://opencv.org/downloads.html

関連する「黒さ」の問題: pgm イメージで作業しているときに、この問題に直面しました。PGM ヘッダーは、画像の「最大」深度を指定する必要があります。EG 255、8 ビット。8 ビットのデータがあり、16 ビットの最大解像度、65565 値で作業しているとします。すべての値が非常に低いため、画像は「黒」になります。私が何を意味するか知っていることを願っています。

于 2012-09-17T13:19:42.760 に答える
0
  rgb_pixel_t bpixel = {blue, green, red, 0};

アルファ値を0に設定している可能性があり、アルファは透明度の値です。代わりに255を試して、結果が得られるかどうかを確認してください。ピクセル方程式が間違っている場合は、少なくとも何かを取得する必要があります。

画像に関するもう1つの「落とし穴」は、データがRGBRGBRGBとして保存されない場合があることですが、Microsoft /IBMDIBのようにBGRBGRBGRです。画像を取得できるので簡単に確認できますが、LSDを使用しているように見えます。

height*width*(depth/16)

また見る必要があります。また、メンテナンスしやすいように、これを一度変数に入れることをお勧めします。

また、RAW DIBについて注意すべき点が1つあります。それは、行ごとにパディングが設定されている場合があることです。MS / IBM DIBでは、各スキャンラインを4バイト単位で格納する必要があります。したがって、出力が一方向に大きくシフトする場合は、それが原因である可能性があります。場合によっては、画像が上下逆に保存されます

于 2012-09-17T13:07:31.567 に答える