Showing posts with label BASIC. Show all posts
Showing posts with label BASIC. Show all posts

Thursday, October 16, 2008

Pixels and image resizing

I came across this document about how pixels are not "little squares", and read it because I was under the impression that pixels were, in fact, little squares. I was wrong, and to summarize the document's point as I understand it: a pixel is more useful to us as a point sample of an image that exists independently of the resolution of the display. More on that in a second.

For me, the idea that pixels ARE little squares is an easy one to believe because of low-res video games where assets are visibly made up of little squares. Mario, for example, doesn't appear on the screen as a miniaturized (photographic) picture of a plumber, but is simply a relatively small number of squares of relatively few different colors arranged to sort of LOOK like a little plumber. The pixels are so big and each one constitutes such a large percentage of the entire image that they have to be considered blocks with which an image is made and not samples representative of a more complex image. If the size of Mario should increase (via zooming in, not via mushroom), then the pixels that form him should increase at the same rate, and not be blended or filtered in any way. Mario IS little square pixels and they should remain in tact.

Pixels in photographs, however, should be too small to consider individually, and should not increase in size as the size of the image increases. Instead the pixels should be spaced farther apart, and the resultant gaps should be filled with colors that would create a smooth transition from one sample to the next. This isn't a perfect solution, of course, and a higher resolution source will probably always look better than a low-res source upscaled to a higher-res, but the idea of resizing by treating the pixels as samples on a continuum of color values is far more useful visually than considering them picture elements which necessarily change in size along with the image.

Here are two examples of a four pixel matrix made up of four different gray scale values. The one on the left is magnified about 20x and each pixel is 20x bigger as well. The one on the right is also magnified 20x, but each pixel was treated as a sample and spaced to the corners of the final image while all the rest of the pixels were filled in using values derived from the four samples.

The derivation is achieved by essentially drawing a circle around the sample, the edge of which abuts the next sample. The center of the circle is the sample color, and the edge of the circle is the closest sample's color, and everything in between is a percentage of both based on a cosine curve. Real image editing software uses a Gaussian filter which uses a more complicated formula, but the shape of the curve is similar to a cosine, so I went with the COS, modified a bit so that COS(0) = 1 and COS(180) = 0. Of course, not every derived pixel will be based on only two samples, and there's a large field in the center of the box that is an average of all four samples. The algorithm I came up with to find each value is:

FOR i = 0 TO 19
FOR j = 0 TO 19
Dist1 = SQR((j - 0) ^ 2 + (i - 0) ^ 2)
Dist2 = SQR((19 - j) ^ 2 + (i - 0) ^ 2)
Dist3 = SQR((j - 0) ^ 2 + (19 - i) ^ 2)
Dist4 = SQR((19 - j) ^ 2 + (19 - i) ^ 2)
IF Dist1 <= 18 THEN
CurPixel = CurPixel + Pixel(0) * (1 + COS((Dist1 * 10 * PI) / 180))
Total = Total + 1
END IF
IF Dist2 <= 18 THEN
CurPixel = CurPixel + Pixel(1) * (1 + COS((Dist2 * 10 * PI) / 180))
Total = Total + 1
END IF
IF Dist3 <= 18 THEN
CurPixel = CurPixel + Pixel(2) * (1 + COS((Dist3 * 10 * PI) / 180))
Total = Total + 1
END IF
IF Dist4 <= 18 THEN
CurPixel = CurPixel + Pixel(3) * (1 + COS((Dist4 * 10 * PI) / 180))
Total = Total + 1
END IF
IF Total > 0 THEN
PSET (50 + j, i), CurPixel / 2
END IF
CurPixel = 0
Total = 0
NEXT j
NEXT i

And looking it over again, it's a little bloated, but it works by counting from 0 to 19 twenty times to consider each of the pixels on the final 20x20 image. For each iteration of this loop, the four distances between the current pixel to the four samples (the corners) is found. Then, if the distance to a corner is less than or equal to 18 (the edge of the circle drawn around each sample), then the color of that corner is considered in the current pixel's value, and that color is defined as a percentage of the original color determined by the cosine of the distance from the corner multiplied by 10. That way at a distance of 0, the color will be 1*Original (COS(0*10)*Original), and at a distance of 18, the color will be 0*Original (COS(18*10)*Original). Each of the applicable colors is added together and divided by 2 (to be honest, I'm not exactly sure why 2. It doesn't represent an average since every value is divided by 2 even in the places where there are 4 samples, but I like how it looks) and then drawn in that position.

And maybe everyone already knows this, and maybe I'm not writing any of this in a way that makes any sense, but I thought it was interesting how image resizing works, and I thought I'd take a stab at making it work on a small scale and then try to show it to somebody.

Full code on comments.

Friday, May 30, 2008

Makin' Prograaaams

Apparently some people noticed that I wasn't around much lately, so this seems like a good place to dump the things I've been working on.

First up is a project I started a couple of weeks ago to keep the old Japanese reading skill sharp (or, you know, sharpen it for the first time). As of right now, there are two modes, one is a review which provides a kanji, its reading(s) and a definition of sorts (all according to the Tuttle Kanji Cards). The second mode is a quiz, which right now just shows a definition and gives five options of which one is the correct answer. Please note that the screenshots in the links are cropped to eliminate the considerable black space that makes up most of the screen, and the "review" shot is actually three screens on top of each other to show the two different styles of romanization for readings, and that there is the option to have the readings displayed in Japanese.

You can try the review mode of this program by downloading this

The other thing I was working on, but not so much lately, is Lisa Green Teaches Texting.



This thing is designed to satisfy mankind's need to practice texting? If you're using DosBox to run this one, make sure your CPU cycles are set to MAX, or else this thing will take forever to load. Also, there are a couple of things that don't quite work right: the text input screen doesn't word wrap to match the prompt, the cursor acts a little funny, and there was at one time a results screen that would rate and comment on your performance, but the formula pretty much praised everyone, so the results screen just gives a few stats.

You can download the mostly functional version of this here

Enjoy!

Monday, December 10, 2007

Tom Nook is a Thieving Bastard: The Game

Last semester I picked up BASIC programming again and spent a couple of months learning how to do some of the things I was too stupid to do when I was a kid: things like drawing bitmaps, making rudimentary text parsers, and capturing keypresses in useful ways.

Jay and I started to do a game, which of course means that we had a lot of fun brainstorming, and then the concept died, whithered on the vine. But no matter, because here is a simple game I put together this March which allows the player to shoot Tom Nook in the head and take his damn bells (well, you can move a crosshairs over Nook's head and press SPACEBAR, and a bag of bells will appear as Nook disappears).




Special thanks for Animal Crossing for featuring the most child-slave-drivingest raccoon in the universe.

Source code on the comments page (if it'll work).