1
\$\begingroup\$

I am building a 2D game in Java in which I use trig operations for rotation. I know Java offers an excellent graphics library but I intend to make my own code just for learning purposes. Now the problem is, I do not understand image interpolation. I do know it tracks the unmapped pixels on rotation and there are various techniques to do it etc. But one thing that Im still confused about even after referring to several tutorials, is - how to find the pixels that are not mapped ?? Once I know it, I can easily implement it in code. Im using PixelGrabber to get pixels and then perform rotation. So could someone just explain how to find unmapped pixels in the array during the rotation operation please?

\$\endgroup\$
7
  • \$\begingroup\$ Can you describe what you mean by "unmapped pixels"? This sounds like it may be specific to the method you're using. \$\endgroup\$
    – DMGregory
    Apr 17, 2016 at 16:33
  • \$\begingroup\$ its a general term , not specific to my method. when i rotate my image it is left with many 'black holes' coz they are the color of the unmapped pixels. ok so let me explain. Before rotation I have an array from pixelgrabber. Then i find calculate the size of the array after rotation coz it will be different. This is done since this new array will let me create the rotated image It all works, except the black holes. \$\endgroup\$
    – Bloke
    Apr 17, 2016 at 17:01
  • \$\begingroup\$ This kind of description of your method belongs in an edit to the question, not in a comment. If I understand you correctly: you are walking through your source image's pixels, and for each one calculating its rotated position in the new image, then copying its colour to that position - is that right? In that case, this "unmapped pixels" problem absolutely is specific to your method. You should be walking the destination image and pulling in source pixels, not the reverse. Alternatively, you can rotate-by-shear. \$\endgroup\$
    – DMGregory
    Apr 17, 2016 at 17:24
  • \$\begingroup\$ Well, what I meant by saying it wasn't specific to me, was the fact that the term 'unmapped pixel' is quite a common one and is used frequently in any tutorial that explains image interpolation. So it is obviously a known problem to which different solutions exist. So I was surprised u didn't understand what I meant by that term the first time. For eg. lets say someone asks u how to handle a 'divide- by- zero' error in code - u are not going to ask him what he means by the term, are u ?? Coz its a common error. So is unmapped pixels. \$\endgroup\$
    – Bloke
    Apr 17, 2016 at 17:46
  • \$\begingroup\$ I don't think there's anything to gain by arguing semantics here. I didn't ask the question for entertainment purposes: from your original description I had a hard time determining what method you were using, what artifact you were encountering, and thus what kind of help you would need, so I asked. (Is my description of your method correct? I'm still not 100% certain because you haven't described your method or provided a code sample) If you want help, adding clarity will get you a lot further than getting defensive about word choice. :/ \$\endgroup\$
    – DMGregory
    Apr 17, 2016 at 17:52

1 Answer 1

2
\$\begingroup\$

What you call unmapped pixels are what appear as "holes" in the rotated image. In image computing (such as analysis, rendering, etc.) a rotation is a manipulation of an image A in order to obtain an image A' so that it is a rotated version of θ degrees (or radians). The simplest way to achieve this, and I guess this is the method you applied, is to consider a transform function f(P,θ) which takes point P and rotates it of an additional angle θ. From polar to cartesian coordinates, we get the system:

enter image description here

This way we can find out the final position of every pixel P(x,y) our image has. Here comes the problem you encountered. When we use this naive method we get the following results:

enter image description here

The presence of holes in the final image (I used a gray scaled one to keep it simple for my MatLab renderer) are due to the fact your image has a finite number of pixels, and when tranforming their position they are not likely to fit the final shape you're expecting, you must round the floating values you get using sin() and cos() to get integer coordinates (code not optimized):

function newimg= rotazione(img, an)
    anrad= (an/180)*pi;
    x= size (img, 1);
    y= size (img, 2);
    b= round (x*cos(anrad)+ y*sin(anrad));
    h= round (x*sin(anrad)+ y*cos(anrad));
    for i=1:x
        for j=1:y
            cx(i,j)= round (i*cos(anrad) - j*sin(anrad));
            cy(i,j)= round (i*sin(anrad) + j*cos(anrad));
        end
    end
    px= min (cx(:));        // Bounding box: get the minimum x coordinate among all
    py= min (cy(:));        // Bounding box: get the minimum x coordinate among all
    for i=1:x
        for j=1:y
            cx= round (i*cos(anrad) - j*sin(anrad));
            cy= round (i*sin(anrad) + j*cos(anrad));
            if (px < 0)
                cx= cx + abs (px) + 1;
            end
            if (py < 0)
                cy= cy + abs (py) + 1;
            end
            newimg (cx, cy)= img (i, j);
        end
    end
end

To answer your question, I tell you you don't need to find a way to get the unmapped pixels in the rotated image. First, you can't, because you mapped forward all available pixels the starting image has.

There's a simple way to find a solution to this problem. Instead of rotating forward the original image, you can just consider the area your rotated image is going to be drawn into (you have to calculate the final bounding box) and apply the inverse rotation. This way you are going to map back all the pixels you're supposed to see on the screen. This is achieved by considering any pixel P'(x',y') in the final rectangle and apply the inverse function for rotation:

enter image description here

When using sin() and cos() here, you are not forced to round these values, but you can even interpolate the value with nearby pixels to get different effects: no interpolation (nearest), linear interpolation, bi-linear, and so on:

function [ out ] = ruota_nearest_semplice( img , gradi)
    // Rotates the image applying a nearest-neighbour interpolation
    // but computing for every pixel inside the bounding box
    [x, y]=size(img);
    gradi=(gradi/180)*pi;
    kernel=[cos(-gradi) sin(-gradi);-sin(-gradi) cos(-gradi)];
    c1=[x y]./2;
    d=ceil([ abs(x*cos(gradi)) + y*abs(sin(gradi)) abs(x*sin(gradi)) + abs(y*cos(gradi))]);
    out=ones(d);
    c2= round(d./2);
    for i=1:d(1) %x
        for j=1:d(2) %y
            p=([i j]-c2);
            p1=round(p*kernel)+c1;
            if(p1(1)>0 && p1(2)>0 && p1(1)<=x && p1(2)<=y)
                out(i,j)=img(p1(1),p1(2)); 
            end
        end
    end
end

This is just some pseudo-code from MatLab, but I hope it can be useful for you to make your own script.

\$\endgroup\$
8
  • \$\begingroup\$ Oh boy o boy - I truly admire the interest u have taken in this. I'll definitely go through it but i got another question now. I am also into another game - Java again - in which I intend to draw a bike rider riding on a mountain. Now look Ive not had much practice or experience developing games so Im struggling with it - the struggle is only for the bits where Math or trig is involved. \$\endgroup\$
    – Bloke
    Apr 17, 2016 at 18:26
  • \$\begingroup\$ Now my question was - Ive seen some similar games involving a bike or cycle rider and I found that the games display all real like movements - like rotation of the wheels, the fluctuating suspension of the bike body on the wheel etc. What i would like to know is - if I am to make such a game, then as far as the bike goes, will I have to use different images for each wheel, body and handle etc to produce that effect ? Is that how u think its usually done ?? \$\endgroup\$
    – Bloke
    Apr 17, 2016 at 18:26
  • \$\begingroup\$ Usually you separate graphics from collision system, unless necessary. A rotating wheel doesn't change its shape, so you change its sprite image but keep the same mask for collision detection. In general, rotations are performed using an optimal algorithm similar to the last one above, but performed at low-level by GPUs. In fact, computing graphics via software is expensive in terms of CPU overload \$\endgroup\$
    – liggiorgio
    Apr 17, 2016 at 18:42
  • \$\begingroup\$ Thanks a lot Giorgio - Now u mentioned bounding box in the earlier comment which reminded me of yet another question - In the game I was discussing above for pixel mapping, I first create the new array based on the bounding box. Its my own code that I wrote after referring to some tutorials and learning the concept of rotations. So the only way I could do it is by calculating the rotated array dimensions for different quadrants. To give just a rough example, if angle > 0 and < 90 then bounding box height = topmost rotated point to bottom rightmost point \$\endgroup\$
    – Bloke
    Apr 17, 2016 at 18:51
  • \$\begingroup\$ I get the results all fine but is there a better way to do it ? \$\endgroup\$
    – Bloke
    Apr 17, 2016 at 18:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .