Rotation and scaling tool: rotpixels

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Rotation and scaling tool: rotpixels
by on (#90106)
Out of the Sonic hacking community came RotSprite, a program for rotating and scaling pixel art without the blurring of bilinear filtering or the jaggedness of naive point sampling. But it was closed-source and Windows-only. So I decided to reimplement the algorithm in Python.

The result: Rotpixels.

I reimplemented the algorithm without some of the optional steps. I provided for rotation, scaling, and even pixel aspect ratio correction (so that your graphics drawn in the 1.143 PAR of NES can be correctly rotated within 1.143 PAR). It's very slow because Scale2x and edge detection are written in pure Python, and PIL's majority filtering is slow as well. But now that I have a working reference implementation as source code, I may rewrite it in C if there is interest.

by on (#90128)
This is my first time trying to run Python code... I have no idea if there's some kind of "standard" version of Python to use, but after failing with versions 3.2.1 and 2.7.2, I finally got it working on 2.6.1. Kinda. I got this error:

Python wrote:
File "rotpixels.py", line 347, in main
out.save(outfilename)
NameError: global name 'outfilename' is not defined


Not knowing enough Python to actually look for the error I simply hardcoded a string with the name of the output file, and I finally got to see the output of the program. What I'm I doing wrong?

BTW, I'm using portable versions of Python (and I'm really glad I made that choice, I'd be pretty pissed if I had installed 2 useless versions into my system).

Anyway, this program looks very similar to the one that inspired it. The possibility to mess with aspect ratios is very welcome, and should make a huge difference in the end. I'll have to play with this a bit more to see what it can really do!

by on (#90130)
It's because Python has to live up to its name: the serpent coil, or as I like to call it (and have for 5-6 years now), "The Coiler".

Not here to argue over languages, which sucks vs. which is better, blah blah, just sayin'... The Coiler is always coiled and ready to strike at any moment. You got bitten.

by on (#90132)
tokumaru wrote:
This is my first time trying to run Python code... I have no idea if there's some kind of "standard" version of Python to use, but after failing with versions 3.2.1 and 2.7.2, I finally got it working on 2.6.1. Kinda. I got this error:

Python wrote:
File "rotpixels.py", line 347, in main
out.save(outfilename)
NameError: global name 'outfilename' is not defined


Not knowing enough Python to actually look for the error I simply hardcoded a string with the name of the output file, and I finally got to see the output of the program. What I'm I doing wrong?

IDK how it could've possibly worked for tepples, you need to replace outfilename with opt.outfilename.

by on (#90137)
tokumaru wrote:
I have no idea if there's some kind of "standard" version of Python to use

A lot of native code libraries on which programs rely haven't been ported to Python 3.x. The latest in the 2.7 series is probably the best, along with the corresponding version of PIL.

Quote:
Kinda. I got this error:

Python wrote:
File "rotpixels.py", line 347, in main
out.save(outfilename)
NameError: global name 'outfilename' is not defined

NameError means the program is trying to use an uninitialized variable, which means the program has a bug. :oops: The solution reported by thefox is correct.

thefox wrote:
IDK how it could've possibly worked for tepples

Any Python program can import any other Python program as a module and use its functions. A program designed to run as a module will test whether it's being run stand-alone or as a module (the if __name__=='__main__' near the end). I try to make my programs usable as libraries, where the command-line tool just calls the library. In a last-minute refactoring toward this end, I forgot to test file output. I was relying on the fact that an output filename is optional; it'll appear in the system's registered image viewer (out.show()) if no filename is available. I've applied thefox's fix and reuploaded.

by on (#90147)
Thank the Gods! The Coiler has slithered away, soon to re-coil itself to strike the next passerby.

by on (#90148)
This may be the most useful tool ever for one of my ideas, thanks! Can't wait to try it out.

by on (#90149)
tepples wrote:
The latest in the 2.7 series is probably the best, along with the corresponding version of PIL.

Any idea why the program failed in version 2.7.2 (PIL 1.1.7) for me then? Here's what I get:

Quote:
File "D:\(long path)\App\lib\site-packages\PIL\
Image.py", line 1755, in new
return Image()._new(core.new(mode, size))
TypeError: integer argument expected, got float


I kinda like the idea of coding tools in Python, but I need to understand what's happening here before I can give it a try!

by on (#90152)
Thank you for your patience in helping me get various combinations of option flags to work.

On Python 2.7.2 and PIL 1.1.7, I managed to reproduce your problem: later versions don't like it when an image has a fractional size. But as before, my testing didn't have 100% coverage, as it goes away if I use the --pad option to explicitly set the output size. Try replacing this:
Code:
        outsize = (ow, oh)

with this:
Code:
        outsize = (int(round(ow)), int(round(oh)))

Keep in mind that Python is sensitive to the number of spaces before a line of code.

by on (#90158)
When I said I needed to understand what was happening I didn't mean the error itself, but rather the reason why it was happening. You said that "the latest in the 2.7 series is probably the best", so I assumed that was what you were using, so I really puzzled when it worked for you and not for me.

I have to admit that I'm a bit worried about using Python to code my own development tools because of these little incompatibilities... I mean, the thing appears to change a lot from version to version. But I guess that if stick to a certain version and tell other people what version this is when sharing programs, things will be OK.

by on (#90208)
I've uploaded what I hope is a fixed version with these two minor bugs taken care of. So is it working any better for you now?