1

I'm hoping someone can help me out. I'm making an image manipulation app, and I found I needed a better way to load in large images.

My plan, is to iterate through "hypothetical" pixels of an image (a "for loop" that covers width/height of the base image, so each iteration represents a pixel), scale/translate/rotate that pixels position relative to the view, then use this information to determine which pixels are being displayed in the view itself, then use a combination of BitmapRegionDecoder and BitmapFactory.Options to load in only the section of image that the output actually needs rather than a full (even if scaled) image.

So far I seem to have covered scale of the image and translation properly, but I can't seem to figure out how to calculate rotation. Since it's not a real Bitmap pixel I can't use Matrix.rotate =( Here is the image translations in the onDraw of the view, imgPosX and imgPosY hold the center point of the image:

m.setTranslate(-userImage.getWidth() / 2.0f, -userImage.getHeight() / 2.0f);
m.postScale(curScale, curScale);
m.postRotate(angle);
m.postTranslate(imgPosX, imgPosY);
mCanvas.drawBitmap(userImage.get(), m, paint);

and here is the math so far of how I'm trying to determine if an images pixel is on the screen:

for(int j = 0;j < imageHeight;j++) {
    for(int i = 0;i < imageWidth;i++) {

        //image starts completely center in view, assume image is original size for simplicity
        //this is the original starting position for each pixel
        int x = Math.round(((float) viewSizeWidth / 2.0f) - ((float) newImageWidth / 2.0f) + i);
        int y = Math.round(((float) viewSizeHeight / 2.0f) - ((float) newImageHeight / 2.0f) + j);

        //first we scale the pixel here, easy operation
        x = Math.round(x * imageScale);
        y = Math.round(y * imageScale);

        //now we translate, we do this by determining how many pixels
        //our images x/y coordinates have differed from it's original
        //starting point, imgPosX and imgPosY in the view start in center
        //of view

        x = x + Math.round((imgPosX - ((float) viewSizeWidth / 2.0f)));
        y = y + Math.round((imgPosY - ((float) viewSizeHeight / 2.0f)));

        //TODO need rotation here

    }
}

so, assuming my math up until rotation is correct (probably not but it appears to be working so far), how would I then calculate the rotation from that pixels position? I've tried other similar questions like:

Link 1

Link 2

Link 3

without using rotation the pixels I expect to actually be on the screen are represented (I made text file that outputs the results in 1's and 0's so I can have a visual representation of whats on the screen), but with the formula found in those questions the information isn't what is expected. (Scenario: I've rotated an image so only the top left corner is visible in the view. Using the info from Here to rotate the pixel, I should expect to see a triangular set of 1's in the upper left corner of the output file, but that's not the case)

So, how would I calculate a a pixels position after rotation without using the Android matrix? But still get the same results.

And if I've just messed it up entirely my apologies =( Any help would be appreciated, this project has gone on for so long and I want to finally be done lol

If you need any more information I will provide as much as I possibly can =) Thank you for your time

I realize this question is particularly difficult so I will be posting a bounty as soon as SO allows.

Community
  • 1
  • 1
codingNewb
  • 470
  • 1
  • 8
  • 23

1 Answers1

2

You do not need to create your own Matrix, use the existing one. http://developer.android.com/reference/android/graphics/Matrix.html

You can map bitmap coordinates to screen coordinates by using

float[] coords = {x, y};
m.mapPoints(coords);
float sx = coords[0];
float sy = coords[1];

If you want to map screen to bitmap coordinates, you can create the inverse matrix

Matrix inverse = new Matrix(m);
inverse.inverse();
inverse.mapPoints(...)

I think your overall approach is going to be slow, as doing the pixel manipulation on the CU from Java has a lot of overhead. When drawing bitmaps normally, the pixel manipulation is done on the GPU.

yoah
  • 7,180
  • 2
  • 30
  • 30
  • I will give this a shot ASAP tomorrow ^_^ Thank you for your time. I know it's going to be slow but the application is just for an ideally single pass with output alone, a single time through is all I require so in terms of speed vs. mem I need to go for best mem usage =) – codingNewb Jul 05 '14 at 08:03