使用Android处理1920x1280图像 - RenderScript

时间:2012-09-04 13:58:29

标签: android renderscript

我是RenderScript的新手并试图处理大小为1920x1280px的图像,这似乎每次都会在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)

如果我将图像调整为100x56px,则相同的代码可以工作: - (。

请查看下面的代码并建议我需要进行的任何更改,代码基于我在互联网上和其他地方找到的示例。

注意:以下代码并非真正的生产质量。

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

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

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

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 个答案:

答案 0 :(得分:3)

您的LogCat中没有异常或警告,但我可能知道这个问题。

首先,我甚至没有看你的RenderScript,因为你说它适用于小位图。

在android中,每个VM或进程都有自己的内存部分,这对于位图1920x1080来说基本上是不够的。所以你的logcat应该有一些你可能忽略的提示:

bitmap size exceeds VM budget

我不知道您的实现细节(获取位图表单服务器,本地文件等)。所以我会引导你去Android Bitmap Training

一般的想法是根据需要加载图像。通过这个:

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;

关键部分:

options.inJustDecodeBounds = true;

说嘿!不要解码和加载位图。我会对我的Bitmap进行一些设置。