1

I am making a procedural animation in Android that is supposed to just take a 720x720 image, convert in into a 2d array of colors and then draw every pixel individually. The problem with my code is that it takes only the top left quadrant and displays it as if it were the whole image and I can't figure out how to fix it.
The code, source image and result here:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new DrawPixels(this, 720, 720));

    }
} 


public class DrawPixels extends View {
    public int[][] image_array;
    Bitmap frame;
    Bitmap photo;
    Canvas frameDrawer;
    Rect bounds;
    Paint lp;
    int width , height;
    int x = 0;
    int y = 0;
    int radius = 3;

    public DrawPixels(Context context , int width, int height) {
        super(context);
        photo = BitmapFactory.decodeResource(context.getResources(), R.drawable.marilyn2);
        image_array = imageTo2dArray(photo);

        this.width = width;
        this.height = height;

        frame = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
        frameDrawer = new Canvas(frame);
        bounds = new Rect(0 , 0, width,height);

        lp = new Paint();
        lp.setStyle(Paint.Style.FILL);

    }

    @Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);

        if (x < 720 && y < 720) {
            lp.setColor(image_array[x][y]);
            frameDrawer.drawCircle(x, y, radius, lp);
        }

        canvas.drawBitmap(frame, null, bounds , null);

        //sampling every 5th pixel
        if (x < 720){
            if(y < 720){
                y += 5;
            }else{
                y = 0;
                x += 5;
            }
            invalidate();
        }
    }


    public int[][] imageTo2dArray(Bitmap bm){
        int[][] arr = new int[720][720];
        int p, a, r, g, b, avg;
        for(int i = 0; i < 720; i++) {
            for (int j = 0; j < 720; j++) {
                arr[i][j] = bm.getPixel(i, j);
            }
        }
        return  arr;
    }
}


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="d.androidnewcomer.drawing.MainActivity">

</android.support.constraint.ConstraintLayout>

marilyn2.png: enter image description here

result: enter image description here

Zyx
  • 336
  • 4
  • 18
  • Why not use a `for` loop in `onDraw()` method? – Nark Apr 29 '18 at 10:52
  • `invalidate()` shoulnd't be used to draw your component in multiple parts. Your whole `View` should be painted in only one `invalidate()` or `repaint()` call, see https://stackoverflow.com/questions/9510125/difference-between-validate-revalidate-and-invalidate-in-swing-gui – Nark Apr 29 '18 at 11:07
  • Please post the layout where your View is called from – Nark Apr 29 '18 at 11:12
  • @Nofix thank you for the tips. I used invalidate(), because I want to draw the picture procedurally, a new pixel every frame. I now added the layout code. – Zyx Apr 29 '18 at 11:18

1 Answers1

1

The most likely reason is that BitmapFactory.decodeResource scales the bitmap so that it is no longer 720x720 but rather 1440x1440.

See: BitmapFactory.decodeResource Bitmap not original size in pixels

DHa
  • 659
  • 1
  • 6
  • 21
  • Since I was going to import pictures from sdcard, putting them into drawable-nodpi directory was not an option, but changing `arr[i][j] = bm.getPixel(i, j);` to `arr[i][j] = bm.getPixel(i*2, j*2);` seems to have worked. Thank you! – Zyx May 03 '18 at 12:16