Image scaling

BlitzMax Forums/BlitzMax Beginners Area/Image scaling

AltanilConard(Posted 2008) [#1]
I'm trying to write a method that scales an image file. As SetScale gives a bit of a blurry and anti-aliased effect and the images I'm trying to scale have very few pixels I think it would be better to write a custom method. What I want is that every pixel in the image gets multiplied by a given amount; so when you're scaling an image by the factor 4, every pixel in the image will turn into a 4x4 rectangle.
I hope this does not sound to confusing. I think the function I have works, but that I'm doing something wrong with the reading/writing/creating of pixmaps/images. I don't have much experience with the modification of pixmaps, so could someone please have a glance at my method and look what is wrong?
	Method scaleImage(_im:TImage, _sx:Int, _sy:Int)
		Local im:TImage, pm:TPixmap, pm2:TPixmap, w:Int, h:Int
		Local x:Int, y:Int, x2:Int, y2:Int, pix:Int
		
		w = _im.width
		h = _im.height
		im = TImage.Create(w, h, 1, 0, 0, 0, 0)
		pm2 = CreatePixmap(w * _sx, h * _sy, PF_RGB888)
		
		DrawImage(_im, 0, 0)
		pm = GrabPixmap(0, 0, w, h);Cls
		
		For x = 0 Until w
			For y = 0 Until h
				For x2 = 0 Until _sx
					For y2 = 0 Until _sy
						WritePixel(pm2, pm.ReadPixel(x,y), x * _sx + x2, y * _sy + y2)
					Next
				Next
			Next
		Next
				
		im.pixmaps[0] = pm2
		DrawImage(im,0,0);Flip;WaitKey()
	End Method

I'm getting the error: "Unhandled exception: Pixmap coordinates out of bounds" (highlighting the WritePixel line).


GfK(Posted 2008) [#2]
You need For x = 0 To w - 1, and For y = 0 to h - 1.


AltanilConard(Posted 2008) [#3]
Isn't that the same as For x = 0 Until w?
It didn't work, I think there is something wrong with the pixmaps but I really can't figure out what. When I change "WritePixel(pm2, pm.ReadPixel(x,y), x * _sx + x2, y * _sy + y2)" to "WritePixel(pm2, pm.ReadPixel(1,1), 1, 1)" I'm getting the same error.
When I draw pm after grabbing it from screen it draws the image correct, so there's probably something wrong with pm2.
Thanks for the help Gfk, any idea what else it can be?


SebHoll(Posted 2008) [#4]
You need For x = 0 To w - 1, and For y = 0 to h - 1.

There is nothing wrong with the Until Conard has used - it does the same thing.

You are going to kick yourself, but I think the actual problem you have is simply from you writing the parameters in the wrong order for WritePixel (from the docs): ;-)

WritePixel( pixmap:TPixmap,x,y,argb )

You have put the pixel before the coordinates in your line, therefore, it should be changed to:

WritePixel(pm2, x * _sx + x2, y * _sy + y2, pm.ReadPixel(x,y))



AltanilConard(Posted 2008) [#5]
Thanks a lot, it works perfectly now! Yes, I do feel stupid ^^.


AltanilConard(Posted 2008) [#6]
I've got some more problems. In my code I'm turning the original image into a Pixmap by drawing the image and then using GrabPixmap. For this however, I will have to clear the screen so all the things that are allready there won't come on the image. This means I will lose what ever there was on the screen before the scale... Ofcourse I could save the entire screen in an image and then draw it again at the end of the method; but is it also possible to turn an image directly into a pixmap?
Also, the scaled image doesn't get 'maskblended' anymore, it has a black background when I draw it (blend is set to MASKBLEND, image flag also contains MASKEDIMAGE, maskcolor is set to (0, 0, 0)). Anyone know what the problem might be?


Vilu(Posted 2008) [#7]
As SetScale gives a bit of a blurry and anti-aliased effect and the images I'm trying to scale have very few pixels I think it would be better to write a custom method.


I believe AutoImageFlags defaults to "MASKEDIMAGE | FILTEREDIMAGE | MIPMAPPEDIMAGE". Take out the FILTEREDIMAGE and I see if it gets rid of the anti-aliasing.

AutoImageFlags MASKEDIMAGE | MIPMAPPEDIMAGE



QuickSilva(Posted 2008) [#8]
Conard, correct me if I am wrong but try using the command AutoImageFlags 0 at the beginning of your program and then try scaling your image up. It will then retain its full pixel quality.

If this s not what you are aiming for then please ignore me ;)

Jason.


GfK(Posted 2008) [#9]
Guys. If an image is 100 pixels wide, then you read the pixels from 0-99 - not 0-100. That's what I was getting at - you clearly just didn't read it properly. Whether you use To or Until is personal preference.


Gabriel(Posted 2008) [#10]
Nope, Until runs 1 less than To.


AltanilConard(Posted 2008) [#11]
@Vilu and QuickSilva: Editing the image flags indeed does the job :).

Just out of curiosity, is it possible to turn an image into a pixmap?

Thanks for the help all.


Jesse(Posted 2008) [#12]
not directly but you can get the pixmap from the image with lockimage. note that whatever you do to the pixmap will affect the image.


ImaginaryHuman(Posted 2008) [#13]
See the thread here: http://www.blitzbasic.com/Community/posts.php?topic=73042#816959

See the post(s) by me, I submitted code for doing simultaneous zooming and rotating of an image. It doesn't do any kind of filtering/smoothing but you can zoom in or out properly and rotate at the same time.