Processing 1920x1280 image with Android - RenderScript

主宰稳场 提交于 2019-12-12 04:47:27

问题


I am newbie to RenderScript and trying to process image with size 1920x1280px, this seems to be crashing every time with following error on logcat

09-04 19:26:04.670: D/dalvikvm(30308): GC_FOR_ALLOC freed 73K, 3% free 6615K/6787K, paused 26ms
09-04 19:26:04.680: I/dalvikvm-heap(30308): Grow heap (frag case) to 14.404MB for 8294416-byte allocation
09-04 19:26:04.690: D/dalvikvm(30308): GC_CONCURRENT freed 2K, 2% free 14713K/14919K, paused 1ms+1ms
09-04 19:26:04.820: D/dalvikvm(30308): GC_FOR_ALLOC freed 0K, 2% free 14713K/14919K, paused 12ms
09-04 19:26:04.820: I/dalvikvm-heap(30308): Grow heap (frag case) to 17.917MB for 3686416-byte allocation
09-04 19:26:04.840: D/dalvikvm(30308): GC_FOR_ALLOC freed 0K, 2% free 18313K/18567K, paused 13ms
09-04 19:26:04.860: D/dalvikvm(30308): GC_CONCURRENT freed 0K, 2% free 18313K/18567K, paused 1ms+2ms
09-04 19:26:05.010: A/libc(30308): Fatal signal 11 (SIGSEGV) at 0x5c41f809 (code=1)
09-04 19:26:05.010: A/libc(30308): Fatal signal 11 (SIGSEGV) at 0x5c41e001 (code=1)

where as the same code works if I resize the image to 100x56px :-(.

Please review the code below and suggest me any changes that needs to be done, the code is based on the example I found elsewhere on internet and from sample.

NOTE: The code below is not really production quality.

content of VDRender.rs

#pragma version(1)
#pragma rs java_package_name(com.iangclifton.tutorials.renderscript);

#include "rs_graphics.rsh"

const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};

void root(const uchar4 *v_in, uchar4 *v_out) {

    //rsDebug("Called ROOT - ONE", rsUptimeMillis());

    float4 f4 = rsUnpackColor8888(*v_in);

    float3 mono = dot(f4.rgb, gMonoMult);
    *v_out = rsPackColorTo8888(mono);
}

content of RenderScript101.rs

#pragma version(1)
#pragma rs java_package_name(com.iangclifton.tutorials.renderscript);

#include "rs_graphics.rsh"

float4 gBgColor; // Background color as xyzw 4-part float
rs_allocation gBgImage; // Background image
rs_allocation gVDBgImage; // Background image

rs_sampler gLinearClamp; // Sampler used by the program fragment
rs_program_fragment gSingleTextureFragmentProgram; // fragment shader
rs_program_store gProgramStoreBlendNone; // blend none, depth none program store
rs_program_vertex gProgramVertex; // Default vertex shader

rs_script gVDScript;

static const float3 gBgVertices[4] = {
    { -1.0, -1.0, -1.0 },
    { 1.0, -1.0, -1.0 },
    { 1.0, 1.0, -1.0 },
    {-1.0, 1.0, -1.0 }
};

void drawInteger(int value, int x, int y) {

    char text[50] = "0";
    int index = 0;

    if(value != 0) {

    index = 49;
    text[index] = 0;

    while(value > 0) {

        index--;

        int digitValue = value % 10;

        text[index] = '0' + digitValue;

        value /= 10;
    }

    if(value < 0) {
        text[index--] = '-';
    }    
    }

    rsgDrawText(&text[index], x, y);
}

int64_t gTimeMS = 0;
int64_t updateFPS = 0;

int gFPS = 0;

static void drawBackground() {

    if (gBgImage.p != 0) {

        //rsgClearColor(gBgColor.x, gBgColor.y, gBgColor.z, gBgColor.w);

        rs_matrix4x4 projection, model;
        rsMatrixLoadOrtho(&projection, -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f);
        rsgProgramVertexLoadProjectionMatrix(&projection);

        rsMatrixLoadIdentity(&model);
        rsgProgramVertexLoadModelMatrix(&model);

        // ----
        if(1) 
        {
            rsForEach(gVDScript, gBgImage, gBgImage, NULL);
            rsgBindTexture(gSingleTextureFragmentProgram, 0, gBgImage);
        }
        else
        {
            rsgBindTexture(gSingleTextureFragmentProgram, 0, gBgImage);
        }
        //----

        rsgDrawQuad(
            gBgVertices[0].x, gBgVertices[0].y, gBgVertices[0].z,
            gBgVertices[1].x, gBgVertices[1].y, gBgVertices[0].z,
            gBgVertices[2].x, gBgVertices[2].y, gBgVertices[0].z,
            gBgVertices[3].x, gBgVertices[3].y, gBgVertices[0].z
        );

        int x = 250;
        int y = 150;
        int fps = 0;

        int64_t t = rsUptimeMillis();
        int diff = t - gTimeMS;
        fps = 1000 / diff; 
        gTimeMS = t;

        if((t - updateFPS) > 500)
        {   
            gFPS = fps;
            updateFPS = t;
        }

        rsgDrawText("FPS:", x, y);
        drawInteger(gFPS, 250+40, 150);
    }
}

void init() {
    gBgColor = (float4) { 0.0f, 1.0f, 0.0f, 1.0f };
    rsDebug("Called init", rsUptimeMillis());
}

int root() {
    rsgBindProgramVertex(gProgramVertex);
    rsgBindProgramFragment(gSingleTextureFragmentProgram);
    rsgBindProgramStore(gProgramStoreBlendNone);

    drawBackground();
    return 1;
}

content of RenderScript101RS.java

package com.iangclifton.tutorials.renderscript;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Float4;
import android.renderscript.Matrix4f;
import android.renderscript.ProgramFragment;
import android.renderscript.ProgramFragmentFixedFunction;
import android.renderscript.ProgramStore;
import android.renderscript.ProgramVertex;
import android.renderscript.ProgramVertexFixedFunction;
import android.renderscript.RenderScriptGL;
import android.renderscript.Sampler;

/**
 * Custom RenderScript helper that simplifies interaction with the RenderScript.
 * 
 * @author Ian G. Clifton
 */
public class RenderScript101RS {

    private Sampler mLinearClamp;
    private ProgramStore mProgramStoreBlendNone;
    private ProgramVertex mProgramVertex;
    private RenderScriptGL mRS;
    private ScriptC_RenderScript101 mScript;
    private ScriptC_VDRender mVDScript;
    private ProgramFragment mSingleTextureFragmentProgram;

    /**
     * Constructs a new helper with RenderScriptGL and Resources references.
     * 
     * @param rs RenderScriptGL reference
     * @param res Resources reference
     * @param resId int ID of the RenderScript (e.g., R.raw.xyz)
     */
    public RenderScript101RS(RenderScriptGL rs, Resources res, int resId, int resId2) {
        mRS = rs;

        mScript = new ScriptC_RenderScript101(rs, res, resId);
        mVDScript = new ScriptC_VDRender(rs, res, resId2);

        mScript.set_gVDScript(mVDScript);

        initProgramStore();
        initSampler();
        initProgramFragment();
        initProgramVertex();
        mRS.bindRootScript(mScript);

    }

    /**
     * Sets a custom background Bitmap on the RenderScript view
     * 
     * @param bitmap Bitmap to use as the background
     */
    public void setBackgroundBitmap(Bitmap bitmap) {
        if (bitmap == null) {
            return;
        }
        final Allocation bitmapAllocation = Allocation.createFromBitmap(mRS, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);
        mScript.set_gBgImage(bitmapAllocation);

        //final Allocation bitmapVDAllocation = Allocation.createFromBitmap(mRS, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);
        //mScript.set_gVDBgImage(bitmapVDAllocation);
    }

    /**
     * Sets a custom background color on the RenderScript view
     * 
     * @param color Float4 color
     */
    public void setBackgroundColor(Float4 color) {
        mScript.set_gBgColor(color);
    }

    /**
     * Prepares the ProgramFragment (fragment shader)
     */
    private void initProgramFragment() {
        final ProgramFragmentFixedFunction.Builder pfBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
        pfBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
        mSingleTextureFragmentProgram = pfBuilder.create();
        mScript.set_gSingleTextureFragmentProgram(mSingleTextureFragmentProgram);
    }

    /**
     * Prepares the ProgramStore (controls use of framebuffer such as blending)
     */
    private void initProgramStore() {
        mProgramStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS);
        mScript.set_gProgramStoreBlendNone(mProgramStoreBlendNone);
    }

    /**
     * Prepares the ProgramVertex (vertex shader)
     */
    private void initProgramVertex() {
        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
        mProgramVertex = pvb.create();
        ProgramVertexFixedFunction.Constants pva = new ProgramVertexFixedFunction.Constants(mRS);
        ((ProgramVertexFixedFunction) mProgramVertex).bindConstants(pva);
        Matrix4f proj = new Matrix4f();
        proj.loadProjectionNormalized(1, 1);
        pva.setProjection(proj);
        mScript.set_gProgramVertex(mProgramVertex);
    }

    /**
     * Prepares the Sampler (controls how pixels are pulled from a texture)
     */
    private void initSampler() {
        mLinearClamp = Sampler.CLAMP_LINEAR(mRS);
        mScript.set_gLinearClamp(mLinearClamp);
    }
}

content of RenderScript101View

package com.iangclifton.tutorials.renderscript;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.renderscript.RSSurfaceView;
import android.renderscript.RenderScriptGL;
import android.view.MotionEvent;

/**
 * Custom RSSurfaceView that sets up the RenderScript and captures touch events.
 * 
 * @author Ian G. Clifton
 */
public class RenderScript101View extends RSSurfaceView {
    private Context mContext;
    private RenderScript101RS mRenderScript;
    private RenderScriptGL mRS;

    /**
     * {@inheritDoc}}
     */
    public RenderScript101View(Context context) {
        super(context);
        mContext = context;
        ensureRenderScript();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        if (mRenderScript == null) {
            return true;
        }

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            mRenderScript.setBackgroundBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.icon00072half));
        }

        return true;
    }

    /**
     * Ensures the RenderScriptGL reference has been established and our custom
     * RS helper has been created.
     */
    private void ensureRenderScript() {
        if (mRS == null) {
            final RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
            mRS = createRenderScriptGL(sc);
        }
        if (mRenderScript == null) {
            mRenderScript = new RenderScript101RS(mRS, mContext.getResources(), R.raw.renderscript101, R.raw.vdrender);
        }
    }
}

回答1:


There is no exception or warning in your LogCat but I may know the issue.

First off, I didn't even look at your RenderScript because you said it works fine for small bitmap.

In android each VM or process have its own portion of memory and this is mostly not enough for a bitmap 1920x1080. So your logcat should have prompt something like this that you may have neglected:

bitmap size exceeds VM budget

I don't know your implementation details (getting bitmap form server, local file etc.). So I will guide you to Android Bitmap Training.

The general idea is to load image as small as you need. By this:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

The crucial part:

options.inJustDecodeBounds = true;

Says hey! don't decode and load the bitmap yet. I will do some settings to my Bitmap.



来源:https://stackoverflow.com/questions/12265108/processing-1920x1280-image-with-android-renderscript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!