How can I let a picture (.png) rotate?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
-DaRealXecon-
Posts: 31
Joined: Wed Jul 09, 2008 7:50 am

How can I let a picture (.png) rotate?

Post by -DaRealXecon- »

Hi,

How can I let a picture (.png) rotate?
If there is a possibility this without GU, OSLib etc. makes were I very gratefully. :D

Thanks in advance! ;)
User avatar
jean
Posts: 489
Joined: Sat Jan 05, 2008 2:44 am

Image processing for dummies

Post by jean »

There are two ways depending on your needs:
[1]
First of all you need your image to be decoded: use libpng or whatever you like to decode your image into a linear buffer containing the ordered list of all pixels in your image, being each pixel (for instance) a 32bit value 0xAABBGGRR that means 8bit per channel, 4 channels. Notice that this way, if p(x,y) is a generic pixel in image, p(0,1) is stored immediately after p(width,0) so a generic point can be accessed linearly through buffer[x+y*width].
Create a new image (i.e. malloc the required space e.g. 10x15 ABGR needs 10*15*4 bytes) and for each pixel of the new image being created, pick up the right inversely rotated pixel of the original image. This can be done applying a 2d rototraslation through a 2x2 matrix as seen on http://en.wikipedia.org/wiki/Rotation_matrix.
Notice that this involves resampling: the result of the rototraslation of each pixel's coordinates leads to non integer coordinate values, so you can decide to simply round that values to the nearest integer or to apply some interpolation algorythm.
[2]
refer to GU examples to learn how to setup GU, and how to render a quadrilateral polygon textured with your image; then you only need to apply rotation transformation just before you draw (take a look at

Code: Select all

void sceGumRotateX(float angle);
). Notice that image needs to be decoded and aligned due to GU speedup requirements. In other words, once you have used libpng to decode your image in buffer like that mentioned before, you have to create a new image whose width (only width) is the nearest higher 2 power. If your image is 480, then the new image will be 512. Copy the original image in the newly created one aligning to the upper left angle i.e. referring to the previous example, copy each 480*4 bytes line in the matching line. Something like:

Code: Select all

m = 0;
n = 0;
for &#40;i = 0; i < 272; i++&#41; // 272 = image height
&#123;
	memcpy&#40;&aligned&#91;n&#93;,&original&#91;m&#93;,1920&#41;; // 1920=480*4= original line size
	m += 480; // 480 = original line size = original image width
	n += 512; // 512 = aligned line size
&#125;
Please, don't confuse alignment with 128 bits in-memory alignment (that's another thing you should care about...just take a look to

Code: Select all

__attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41;
and to

Code: Select all

void *	memalign&#40;size_t align, size_t size&#41;;
for the same purpose in a dynamic context)

Method [1] is used in image processing when high quality is required and time is not an issue (it could be quite slow depending on implementation and image sizes) while [2] is the way to go for realtime, if resulting rotated images are not to be stored again (well, you could render to texture and then save it again but...): it's fast because CPU delegates pixel operation to GU and leaves CPU time to be used for something else.

If it's not clear, then i hope i at least gave you all the buzzwords for you to search and learn.

jean
ooPo
Site Admin
Posts: 2023
Joined: Sat Jan 17, 2004 9:56 am
Location: Canada
Contact:

Post by ooPo »

If you want an easy way to do it, use SDL_image to load the file, then use the rotozoomer in SDL_gfx to rotate it. Both libraries are available in the psplibraries package.

It'll probably be fast enough for a single image, otherwise you'll want to get the graphics hardware to do it for you.
-DaRealXecon-
Posts: 31
Joined: Wed Jul 09, 2008 7:50 am

Post by -DaRealXecon- »

Thank you a lot! :)
Post Reply