Android - не работает затенение изображения с помощью Renderscript - PullRequest
0 голосов
/ 28 мая 2019

Я написал следующий код, чтобы затенить изображение.В ранних проектах я имел опыт работы с JNI, а теперь я также хотел попробовать Renderscript.Итак, я пишу следующий код:

// MainActivity.java
public class MainActivity extends AppCompatActivity {

    private Bitmap mBitmapIn;
    private Bitmap mBitmapOut;

    private ImageView mImageView;

    private Allocation mInAllocation;
    private Allocation mOutAllocation;

    private Button mButton;

    private ScriptC_gray mScript;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mButton =(Button) findViewById(R.id.button);

        // Initialize UI
        mBitmapIn = loadBitmap(R.drawable.data);

        mBitmapOut =  Bitmap.createBitmap
                (
                        mBitmapIn.getWidth(),
                        mBitmapIn.getHeight(),
                        mBitmapIn.getConfig()
                );

        mImageView = (ImageView) findViewById(R.id.imageView);
        mImageView.setImageBitmap(mBitmapIn);

        // Create renderScript
        RenderScript rs = RenderScript.create(this);

        // Allocate buffers
        mInAllocation = Allocation.createFromBitmap(rs, mBitmapIn);
        mOutAllocation = Allocation.createFromBitmap(rs, mBitmapOut);

        mScript = new ScriptC_gray(rs); // Load script

        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Invoke renderScript kernel and update imageView
                mScript.forEach_gray(mInAllocation, mOutAllocation);

                // Copy to bitmap and invalidate image view
                mOutAllocation.copyTo(mBitmapOut);

                mImageView.setImageBitmap(mBitmapOut);
            }
        });
    }

    /**
     * Helper to load Bitmap from resource
     */
    private Bitmap loadBitmap(int resource) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeResource(getResources(), resource, options);
    }
}

Как вы можете видеть, я загружаю изображение, готовлю весь материал отрисовки, создавая распределения IN / OUT, применяя функцию ядра и помещая результат вэкран.

Файл gray.rs выглядит следующим образом:

// gray.rs
#pragma version(1)
#pragma rs java_package_name(com.celik.abdullah.grayscale)
#pragma rs_fp_relaxed

const float4 weight = {0.299f, 0.587f, 0.114f, 0.0f};   // for grayscale

/*
 * RenderScript kernel that performs grayscale manipulation
 */
uchar4 __attribute__((kernel)) gray(uchar4 in)
{
     float4 inF = rsUnpackColor8888(in);
     float4 outF = (float4){ dot(inF, weight) };
     return rsPackColorTo8888(outF);
}

Когда я запускаю проект, происходит следующее:

Результат:

enter image description here

Итак, ImageView становится пустым после того, как я нажимаю кнопку, и начинается процесс серого цвета.Зачем ?Я не мог найти свою ошибку.Я следовал инструкциям в официальной документации, но, может быть, мне чего-то не хватает

Ответы [ 2 ]

0 голосов
/ 21 июля 2019

Другой вариант - использовать 1.f в вашем весовом векторе, иначе ваша альфа обнуляется, делая полностью прозрачное изображение.

0 голосов
/ 16 июля 2019

Изменить файл rs, как показано ниже, работает для меня:

// gray.rs
#pragma version(1)
#pragma rs java_package_name(com.colibri.sample)
#pragma rs_fp_imprecise//rs_fp_relaxed//rs_fp_full//rs_fp_relaxed

const float3 gMonoMult = {0.299f, 0.587f, 0.114f};
/*
 * RenderScript kernel that performs grayscale manipulation
 */
uchar4 __attribute__((kernel)) gray(uchar4 in)
{
    // Transform the input pixel with a value range of [0, 255] to
    // a float4 vector with a range of [0.0f, 1.0f]
    float4 inF = rsUnpackColor8888(in);
    // Calculate the dot product of the rgb channels and the global constant we defined and
    // assign the result to each element in a float3 vector
    float3 outF = dot(inF.rgb, gMonoMult);
    // Transform the resulting color back to a uchar4 vector.
    // Since the input color is just a float3 instead of a float4 the alpha value will
    // be set to 255 or fully opaque.
    return rsPackColorTo8888(outF);
}
...