質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.76%

  • Java

    13174questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    6252questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

VirtualDisplay ImageReaderからBitmapを取得する際のサイズについて

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 136

u-ta

score 51

 前提・実現したいこと

Androidアプリを作成しています。
"MediaProjection"を使って、スクリーンをBitmapを取得するアプリを作成しています。
acquireLatestImageからImage.Planeを取得しています。

 発生している問題・エラーメッセージ

Bitmapのサイズの指定が理解できておらず、
ImageReaderからBitmapにするさいに、サイズの指定がうまくいかない状態です。

他の方を参考にbitmap.copyPixelsFromBufferを使ったのですが
画像の左右に黒いPaddingの領域ができてしまいます。

ご存知の方お願いします。

 該当のソースコード

private static VirtualDisplay display;
private static ImageReader imageRender;
private int displayWidth, displayHeight;

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data ) {

final MediaProjection projection = mediaProjectionManager.getMediaProjection(resultCode, data);
final DisplayMetrics metrics = getResources().getDisplayMetrics();

displayWidth      = metrics.widthPixels;
displayHeight     = metrics.heightPixels;

imageRender = ImageReader.newInstance( displayWidth , displayHeight, PixelFormat.RGBA_8888, 1);
imageRender.setOnImageAvailableListener(this, null);

display = projection.createVirtualDisplay("Preview",displayWidth, displayHeight,
metrics.densityDpi,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
imageRender.getSurface(),null, null);




@Override
protected void onCreate( Bundle savedInstanceState ) {

final DisplayMetrics metrics = getResources().getDisplayMetrics();
if( DEBUG ) Log.i( TAG, "widthPixels:" + metrics.widthPixels ); // widthPixels:1080
if( DEBUG ) Log.i( TAG, "heightPixels:" + metrics.heightPixels ); //heightPixels:1776
if( DEBUG ) Log.i( TAG, "scaledDensity:" + metrics.scaledDensity );// scaledDensity:2.5500002

 試したこと

bitmapのgetWidthがDisplayMetricsと一致していない。
画面の左右に黒いPaddingができてしまう。

Image.Plane plane    = image.getPlanes()[0];
ByteBuffer  buffer    = plane.getBuffer();
int pixelStride    = plane.getPixelStride();
int rowStride    = plane.getRowStride();
int rowPadding    = rowStride - pixelStride * displayWidth;

if( DEBUG ) Log.i( TAG, "getPixelStride:" + ( pixelStride ) ); // 4
if( DEBUG ) Log.i( TAG, "getRowStride:" + ( rowStride ) );     // 4608
if( DEBUG ) Log.i( TAG, "rowPadding:" + ( rowPadding ) );    // 288
if( DEBUG ) Log.i( TAG, "width:" + ( displayWidth + rowPadding / pixelStride ) ); // 1152
if( DEBUG ) Log.i( TAG, "Height:" + ( displayHeight ) ); // 1776


bitmap = Bitmap.createBitmap(
                    displayWidth + rowPadding / pixelStride, displayHeight ,
                    Bitmap.Config.ARGB_8888 );
            bitmap.copyPixelsFromBuffer( buffer );
            image.close();
if( DEBUG ) Log.i( TAG, "bitmap:" + bitmap.getWidth() ); // bitmap:1152
if( DEBUG ) Log.i( TAG, "bitmap:" + bitmap.getHeight() ); // bitmap:1776

bitmapのgetWidth、getHeightはDisplayMetricsと一致しているが
左右のPaddingはないが、細かい横線がたくさん表示されモザイクのような状態になる。

Image.Plane plane            = img.getPlanes()[0];
final Buffer rewBuffer    = plane.getBuffer().rewind();
bitmap = Bitmap.createBitmap(displayWidth, displayHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer( rewBuffer );
img.close();
if( DEBUG ) Log.i( TAG, "bitmap:" + bitmap.getWidth() ); // bitmap:1080
if( DEBUG ) Log.i( TAG, "bitmap:" + bitmap.getHeight() ); // bitmap:1776
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

失礼しました、閉じ忘れていました。

対象をViewに表示しながらテストしたところ、bitmapからjpgへの変換時に黒枠ができていたようです。
試行錯誤していたので、bitmapの部分と思い込んでいました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

imageRender.setOnImageAvailableListener(this, null);

これは必要なのでしょうか?
使うのであればその部分に関連するコード、メソッドが必要だと思いますが
リンク内容

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/03 13:38

    すべて記載できておらずすみません。
    @Override onImageAvailableは実装しており
    ImageReaderから画像が取得できるようになると呼ばれています。

    キャンセル

  • 2018/05/03 15:12

    >すべて記載できておらず
    記述していないところで問題が発生していないでしょうか

    scaledDensity:2.5500002
    ちょっと変わったdensityですが
    これ以外の端末、PIXELあたりではどうなんでしょう

    キャンセル

  • 2018/05/04 00:18

    ちょっと古いですが、nexus5でも同様になりました。

    Image.Planeからbitmap生成の方法はどんな処理がただしいのでしょうか?
    上記2とおりと、全ピクセルをpaddingなどを計算しながらループするサンプルをみたことがあるのですが

    そもそもrowPaddingなどが理解できていなくて、どちらの処理がベストなんでしょうか?

    キャンセル

  • 2018/05/04 07:15

    >どちらの処理がベスト
    Googleのサンプルを参考にするとか、ちょっと面倒ですが
    https://github.com/googlesamples/android-ScreenCapture/blob/master/Application/src/main/java/com/example/android/screencapture/ScreenCaptureFragment.java

    こちらのやり方は
    https://techbooster.org/android/application/17026/
    先にリンクを出したこちらとほぼ同じように
    スクショが撮れます(フォーマットを修正しないといけませんが)
    https://akira-watson.com/android/screenshot.html


    更にu-taさんのコードも
    setOnImageAvailableListenerを簡単に設定して試してもできます

    問題の可能性はsetOnImageAvailableListenerに関連して、コードを出していないところに起因するかもしれません
    実際に簡略化したものを別に作って試せば分かると思います

    それから、これは実際の画像ファイルとして
    確認しておかしいという話でしょうか
    それとも画面に表示させたのでしょうか

    >rowPaddingなどが理解できていなくて
    これは、rawデータの中で画像に関係しない部分と理解するのがざっくりですが適当では
    細かくはフォーマット次第ですし、ネット情報から探してください

    >nexus5でも同様になりました
    nexus5だと
    rowPadding:0
    なのでpaddingが関係しないのでわかりやすいのでは
    emulatorではとくに問題はないような気がします

    キャンセル

  • 2018/05/04 16:35

    いま手元にないのですが
    Nexus5だとdisplay関連のあたいは異なりますが
    結果として、imageViewまた、それをサーバーにPostしたBitmapを確認すると、黒いpadding領域ができている、もしくは細かい横線がたくさん表示されモザイクのような状態になる、という状態です。


    Bitmapの生成についてはもう少し調べてみますが
    いただいたリンクの方々も含めてほとんどの方が
    rowPaddingを使った実装なので
    一旦他の方の実装を参照して簡略化したものでもう少し調べてみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    13174questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    6252questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。