Tuesday, November 17, 2015

Display image in opposite color to Trick your brain


This example inspired by the BBC video "Trick your brain: black and white photo turns to colour! - Colour: The Spectrum of Science".

Load your photo, touch the ImageView to display the image of opposite color, look on the blue dot concentratedly for a moment, then release touch to display the black and white image. MAY BE you will be tricked with a color image. try it:)

APK can be download on bottom of this post.


MainActivity.java
package com.blogspot.android_er.androidimage;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import java.io.FileNotFoundException;

public class MainActivity extends AppCompatActivity {

    private static final int RQS_OPEN = 1;

    LinearLayout panel;
    Button buttonOpen;
    ImageView imageView;
    BlueDot blueDot;

    Bitmap bmNormal, bmGrayScale, bmOpposite;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        panel = (LinearLayout)findViewById(R.id.panel);
        buttonOpen = (Button) findViewById(R.id.opendocument);
        buttonOpen.setOnClickListener(buttonOpenOnClickListener);

        imageView = (ImageView)findViewById(R.id.image);
        imageView.setOnTouchListener(imageViewOnTouchListener);

        blueDot = (BlueDot)findViewById(R.id.bluedot);
    }

    View.OnTouchListener imageViewOnTouchListener = new View.OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            if(event.getAction() == MotionEvent.ACTION_DOWN){
                //user touch on ImageView
                if(bmOpposite != null){
                    imageView.setImageBitmap(bmOpposite);
                    blueDot.setVisibility(View.VISIBLE);
                }
            }else if(event.getAction() == MotionEvent.ACTION_UP){
                //user release touch on ImageView
                if(bmGrayScale != null){
                    imageView.setImageBitmap(bmGrayScale);
                    blueDot.setVisibility(View.INVISIBLE);
                }
            }
            return true;
        }
    };

    View.OnClickListener buttonOpenOnClickListener =
            new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
                    intent.addCategory(Intent.CATEGORY_OPENABLE);
                    intent.setType("image/*");
                    startActivityForResult(intent, RQS_OPEN);
                }
            };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && requestCode == RQS_OPEN) {
            Uri dataUri = data.getData();
            int w = imageView.getWidth();
            int h = imageView.getHeight();

            try {
                bmNormal = bmGrayScale = bmOpposite = null;
                bmNormal = loadScaledBitmap(dataUri, w, h);
                bmGrayScale = getGrayscale(bmNormal);
                bmOpposite = getOpposite(bmNormal);
                imageView.setImageBitmap(bmGrayScale);

                //hide ui control and action bar to make more space for the picture
                panel.setVisibility(View.GONE);
                getSupportActionBar().hide();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }
    }

    private Bitmap getGrayscale(Bitmap src){

        //Custom color matrix to convert to GrayScale
        float[] matrix = new float[]{
                0.3f, 0.59f, 0.11f, 0, 0,
                0.3f, 0.59f, 0.11f, 0, 0,
                0.3f, 0.59f, 0.11f, 0, 0,
                0, 0, 0, 1, 0,};

        Bitmap dest = Bitmap.createBitmap(
                src.getWidth(),
                src.getHeight(),
                src.getConfig());

        Canvas canvas = new Canvas(dest);
        Paint paint = new Paint();
        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
        paint.setColorFilter(filter);
        canvas.drawBitmap(src, 0, 0, paint);

        return dest;
    }

    private Bitmap getOpposite(Bitmap src){

        int w = src.getWidth();
        int h = src.getHeight();

        Bitmap dest = Bitmap.createBitmap(w, h, src.getConfig());

        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                int pixel = src.getPixel(x, y);
                int oppPixel = Color.argb(
                        Color.alpha(pixel),
                        255-Color.red(pixel),
                        255-Color.green(pixel),
                        255-Color.blue(pixel));
                dest.setPixel(x, y, oppPixel);
            }
        }

        return dest;
    }

    /*
    reference:
    Load scaled bitmap
    http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
     */
    private Bitmap loadScaledBitmap(Uri src, int req_w, int req_h) throws FileNotFoundException {

        Bitmap bm = null;

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(getBaseContext().getContentResolver().openInputStream(src),
                null, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, req_w, req_h);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bm = BitmapFactory.decodeStream(
                getBaseContext().getContentResolver().openInputStream(src), null, options);

        return bm;
    }

    public int calculateInSampleSize(BitmapFactory.Options options,
                                     int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height
                    / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

}


Custom view to display a blue dot on screen, BlueDot.java
package com.blogspot.android_er.androidimage;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class BlueDot extends View {

    Paint paint;

    public BlueDot(Context context) {
        super(context);
        init();
    }

    public BlueDot(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public BlueDot(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(5);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int w = canvas.getWidth();
        int h = canvas.getHeight();
        canvas.drawCircle(w/2, h/2, 25, paint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(
                MeasureSpec.getSize(widthMeasureSpec),
                MeasureSpec.getSize(heightMeasureSpec));
    }
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="5dp"
    android:background="@android:color/black"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/panel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_horizontal"
            android:autoLink="web"
            android:text="android-er.blogspot.com"
            android:textStyle="bold" />

        <Button
            android:id="@+id/opendocument"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Open" />

    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/image"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <com.blogspot.android_er.androidimage.BlueDot
            android:id="@+id/bluedot"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignTop="@id/image"
            android:layout_alignBottom="@id/image"
            android:layout_alignLeft="@id/image"
            android:layout_alignRight="@id/image"
            android:visibility="invisible"/>
    </RelativeLayout>

</LinearLayout>



download filesDownload APK to try.

No comments: