Shallow Thoughts : tags : graphics
Akkana's Musings on Open Source Computing and Technology, Science, and Nature.
Tue, 23 Jul 2019
This is Part IV of a four-part article on ray tracing digital elevation
model (DEM) data.
The goal: render a ray-traced image of mountains from a digital
elevation model (DEM).
Except there are actually several more parts on the way, related to
using GRASS to make viewsheds. So maybe this is actually a five- or
six-parter. We'll see.
The Easy Solution
Skipping to the chase here ... I had a whole long article
written about how to make a sequence of images with povray, each
pointing in a different direction, and then stitch them together
with ImageMagick.
But a few days after I'd gotten it all working, I realized none of it
was needed for this project, because ... ta-DA —
povray accepts this argument inside its camera section:
angle 360
Duh! That makes it so easy.
You do need to change povray's projection to cylindrical;
the default is "perspective" which warps the images.
If you set your look_at to point due south --
the first and second coordinates are the same as your observer coordinate,
the third being zero so it's looking southward -- then povray will
create a lovely strip starting at 0 degrees bearing (due north), and
with south right in the middle.
The camera section I ended up with was:
camera {
cylinder 1
location <0.344444, 0.029620, 0.519048>
look_at <0.344444, 0.029620, 0>
angle 360
}
with the same
light_source and
height_field as in Part III.
There are still some more steps I'd like to do.
For instance, fitting names of peaks to that 360-degree pan.
The rest of this article discusses some of the techniques I would
have used, which might be useful in other circumstances.
A Script to Spin the Observer Around
Angles on a globe aren't as easy as just adding 45 degrees to the
bearing angle each time. You need some spherical trigonometry to
make the angles even, and it depends on the observer's coordinates.
Obviously, this wasn't something I wanted to calculate by hand, so
I wrote a script for it:
demproj.py.
Run it with the name of a DEM file and the observer's coordinates:
demproj.py demfile.png 35.827 -106.1803
It takes care of calculating the observer's elevation, normalizing
to the image size and all that. It generates eight files, named
outfileN.png,
outfileNE.png etc.
Stitching Panoramas with ImageMagick
To stitch those demproj images manually in ImageMagick, this should
work in theory:
convert -size 3600x600 xc:black \
outfile000.png -geometry +0+0 -composite \
outfile045.png -geometry +400+0 -composite \
outfile090.png -geometry +800+0 -composite \
outfile135.png -geometry +1200+0 -composite \
outfile180.png -geometry +1600+0 -composite \
outfile225.png -geometry +2000+0 -composite \
outfile270.png -geometry +2400+0 -composite \
outfile315.png -geometry +2800+0 -composite \
out-composite.png
or simply
convert outfile*.png +smush -400 out-smush.png
Adjusting Panoramas in GIMP
But in practice, some of the images have a few-pixel offset,
and I never did figure out why; maybe it's a rounding error
in my angle calculations.
I opened the images as layers in GIMP, and used my GIMP script
Pandora/
to lay them out as a panorama. The cylindrical projection should
make the edges match perfectly, so you can turn off the layer masking.
Then use the Move tool to adjust for the slight errors
(tip: when the Move tool is active, the arrow keys will move
the current layer by a single pixel).
If you get the offsets perfect and want to know what they are
so you can use them in ImageMagick or another program, use
GIMP's Filters->Python-Fu->Console.
This assumes the panorama image is the only one loaded in GIMP,
otherwise you'll have to inspect gimp.image_list() to see where
in the list your image is.
>>> img = gimp.image_list()[0]
>>> for layer in img.layers:
... print layer.name, layer.offsets
Tags: GIS, mapping, graphics, gimp, ImageMagick
[
15:28 Jul 23, 2019
More mapping |
permalink to this entry |
]
Sun, 24 Dec 2017
Dave and I will be giving a planetarium talk in February
on the analemma and related matters.
Our planetarium, which runs a fiddly and rather limited program called
Nightshade, has no way of showing the analemma. Or at least, after
trying for nearly a week once, I couldn't find a way. But it can
show images, and since I once wrote a
Python
program to plot the analemma, I figured I could use my program
to generate the analemmas I wanted to show and then project them
as images onto the planetarium dome.
But naturally, I wanted to project just the analemma and
associated labels; I didn't want the blue background to
cover up the stars the planetarium shows. So I couldn't just use
a simple screenshot; I needed a way to get my GTK app to create a
transparent image such as a PNG.
That turns out to be hard. GTK can't do it (either GTK2 or GTK3),
and people wanting to do anything with transparency are nudged toward
the Cairo library. As a first step, I updated my analemma program to
use Cairo and GTK3 via gi.repository. Then I dove into Cairo.
I found one C solution for
converting
an existing Cairo surface to a PNG, but I didn't have much luck
with it. But I did find a
Python
program that draws to a PNG without bothering to create a GUI.
I could use that.
The important part of that program is where it creates a new Cairo
"surface", and then creates a "context" for that surface:
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *imagesize)
cr = cairo.Context(surface)
A Cairo surface is like a canvas to draw on, and it knows how to
save itself to a PNG image.
A context is the equivalent of a GC in X11 programming:
it knows about the current color, font and so forth.
So the trick is to create a new surface, create a context,
then draw everything all over again with the new context and surface.
A Cairo widget will already have a function to draw everything
(in my case, the analemma and all its labels), with this signature:
def draw(self, widget, ctx):
It already allows passing the context in, so passing in a different
context is no problem. I added an argument specifying the background
color and transparency, so I could use a blue background in the user
interface but a transparent background for the PNG image:
def draw(self, widget, ctx, background=None):
I also had a minor hitch: in draw(), I was saving the context as
self.ctx rather than passing it around to every draw routine.
That means calling it with the saved image's context would overwrite
the one used for the GUI window. So I save it first.
Here's the final image saving code:
def save_image(self, outfile):
dst_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
self.width, self.height)
dst_ctx = cairo.Context(dst_surface)
# draw() will overwrite self.ctx, so save it first:
save_ctx = self.ctx
# Draw everything again to the new context,
# with a transparent instead of an opaque background:
self.draw(None, dst_ctx, (0, 0, 1, 0)) # transparent blue
# Restore the GUI context:
self.ctx = save_ctx
dst_surface.write_to_png("example.png")
print("Saved to", outfile)
Tags: programming, python, gtk, gtk3, graphics, analemma
[
19:39 Dec 24, 2017
More programming |
permalink to this entry |
]
Sat, 12 Jan 2013
I discussed Emacs's
artist-mode
a few days ago as a simple, but incomplete, solution to the problem of
sketching graphs while taking notes during a math class. But I've found
a much better way, one that allows for including any images --
drawings, photos, or screenshots.
It took a little work and some custom .emacs code, but I love the result.
Iimage mode
The key is iimage-mode, which displays inline images.
In this mode, you put a line in your
buffer with a reference to your image file, something like this:
file://myimage.jpg
and Emacs will replace it with the contents of that image. Marvellous!
You can use other patterns for filenames as well, but I'm fine
with using URLs. Note there are only two slashes in file:// -- it's a
local file in the same directory as the text file being edited.
It's a little tricky to enable it.
The docs are not entirely clear on the differences between
iimage-mode
, turn-on-iimage-mode
and iimage-mode-buffer
.
I found I could get a file that already had existing images to display
them with:
(turn-on-iimage-mode)
(iimage-mode-buffer t)
Very cool! But too much to type every time. And to use it for
note-taking, I needed a way to say, "Create a new image here, let me
edit it, then display the image I just edited inline."
Enabling iimage-mode automatically
First, I wanted iimage mode displayed automatically on files in my
note-taking directories. I normally use text-mode for these files,
with spell checking and line wrapping turned on (auto-fill mode).
So I defined a new minor mode based on text-mode:
(define-derived-mode text-img-mode text-mode "Image display mode"
(auto-fill-mode)
(turn-on-iimage-mode)
(iimage-mode-buffer t)
)
Then I wanted this mode to be called whenever I'm editing a file
in my classes directory. So I added it to my auto-mode-alist
:
(setq auto-mode-alist
...
(cons '("Docs/classes/" . text-img-mode)
...
auto-mode-alist) )
Inserting a new image
Next, I needed a way to insert an image URL into the buffer and
call up an image editor on it. I shouldn't have to type the filename
twice and keep track of it; that's what computers are for.
And I needed a drawing program. As a longtime GIMP geek, most
of my computer drawing has been in GIMP. But GIMP is overkill for
calling up a quick sketch window. I was tempted to use TuxPaint;
it's a good sketching app even if you're not five years old, and it's
fun and easy to use.
But by default, TuxPaint has some features that get in the way of
note-taking, like distracting sound effects. I'm sure it's possible
to turn those off, and I do plan to investigate that.
I saw a reference to pinta as a lightweight drawing app, but it required
a boatload of Mono libraries that I don't otherwise need, and Krita has
the same problem with KDE services. So I opted for MyPaint.
It works okay, though it's rather slow to start up and has some other
issues, so I'm still hoping to find a more lightweight sketching app.
In any case, I fiddled around with start-process
until
I figured out how to use it to start a program. Then I wrote a little
function that lets the user pick a filename, inserts a URL to that
filename into the buffer, then calls up mypaint on the file.
(defun img ()
"Prompt for a filename, then call up mypaint to create an image"
(interactive)
(let ((imgfile (read-string "Filename? " "xxx.jpg" 'my-history)))
(insert "\nfile://" imgfile "\n" )
(start-process "mypaint" nil "/usr/bin/mypaint" imgfile)
))
Worked fine! I can run M-x img
, be prompted for a filename,
and get a mypaint window where I can make my sketch.
Noticing that a new image has been added
But wait. I finish sketching, write the file and quit mypaint ...
and the buffer still shows something like
file://xxx.jpg
, even if it's showing other images
inline. I needed a way to tell it to refresh and load any new images.
(I considered having emacs wait for mypaint to exit, but decided I
might sometimes want to keep editing while mypaint was still up.)
M-x eval-expression (iimage-mode-buffer t)
will do that,
but that's a lot of typing to do. Obviously, I needed a key binding.
Strangely enough, C-c i wasn't taken for text buffers, so that seemed
like a natural. So I added a key binding to the end of the
text-img-mode
. iimage-mode-buffer
requires
that t argument -- it gives an error without it -- so the key binding
looks a little more complicated than one that just calls a simple function.
I added it to the end of my text-img-mode function.
(define-derived-mode text-img-mode text-mode "Image display mode"
...
(local-set-key "\C-ci"
(lambda () (interactive) (iimage-mode-buffer t)))
)
But after using it a bit, I discovered that this didn't reload images
if I edited them a second time. Fortunately,
vwood had
the answer:
(defun refresh-iimages ()
"Only way I've found to refresh iimages (without also recentering)"
(interactive)
(clear-image-cache nil)
(iimage-mode nil)
(iimage-mode t)
(message "Refreshed images")
)
I added the message
at the end, since otherwise the function
left a distracting
"Toggling iimage-mode off; better pass an explicit argument" error.
Then the key binding in my text-img-mode became
(local-set-key "\C-ci" 'refresh-iimages)
Inserting a screenshot
Wait -- one more thing. As I actually used text-img-mode to take notes,
I discovered that taking screenshots would actually be much more useful
than making my own drawings. Then I could copy small sections of the
slides and graphs into my notes at the appropriate place, without
needing to copy equations at all.
Why not write a function to allow that? The unpleasantly named
scrot program fills the bill nicely, and gives me a choice
of clicking in a window or dragging out an area of the screen.
(defun screenshot ()
"Prompt for a filename, then call up scrot to create an interactive screenshot"
(interactive)
(let ((imgfile (read-string "Filename? " "scr.jpg" 'my-history)))
(insert "\nfile://" imgfile "\n" )
(start-process "scrot" nil "/usr/bin/scrot" "-s" imgfile)
))
This turned out to be so useful that I added a key for it in text-img-mode:
(local-set-key "\C-cs" 'screenshot)
I'm so happy with the result! Iimage mode is working great, and having
text and images together is turning out to be perfect for note-taking.
My only problem now -- okay, I admit it -- is a tendency to get so
excited over inserting screenshots that I get distracted and forget to
actually listen to the lecture. I'm sure I'll get over that, but for
now, Thank goodness vlc is good at skipping back!
Tags: editors, emacs, graphics, education
[
13:42 Jan 12, 2013
More linux/editors |
permalink to this entry |
]
Thu, 10 Jan 2013
I found a cool package in Emacs the other day: Artist Mode.
It lets you draw ASCII graphics in your text file.
I was actually looking for the solution to a different problem:
taking notes in a math-intensive Coursera class. I've been taking
notes in Emacs, but a text editor is awkward for equations and even
more awkward for graphs.
What I really wanted was something like the old Claris Works (or so
I'm told; I never used it myself) -- something that's primarily a
text editor but lets you drawings, equations, and tables when you
need to. In theory, word processors like LibreOffice could do that,
but in practice they're not very good at switching modes, nor at
integrating several types of media into one document.
Texmacs is great for the equations and apparently it can do tables
too, but it can't do freehand drawing.
And none of these programs is very configurable -- I can't use my
fast, comfortable Emacs bindings while typing, and that's a
deal-breaker for me, because being able to make corrections quickly
makes a huge difference in my typing speed.
LibreOffice's key bindings are only
partially configurable, and after you've spent half a day chasing
down all the action names you need (the ones that are actually
available), you upgrade to a newer version and discover you have to
do it all over again because there's no way to migrate configuration files.
Even Texmacs, ironically, is no better: the documentation claims
it's possible to configure key bindings, but it doesn't appear anyone
has ever succeeded in figuring out how.
Anyway, ASCII graphics aren't the ultimate solution to note-taking.
And I've found a better solution for that, while I'll write about
separately. But for now, Artist Mode is just so cool I had to share it.
Enable it by running M-x artist-mode
.
You can immediately start drawing in your buffer with the mouse.
Whatever you draw gets turned into ASCII graphics.
For note-taking, it's fine for scribbling the rough shape of a
curve. It takes no time to mouse in a little sketch like
| .. 20
| ..
| ...
10 |. ..
|.. ...
| ... ...
| .. ....
| ..... .....
| ............
|..... .............
+-------------------------------------
It even has primitives (middleclick to get a.menu) for things like
lines, rectangles and circles, and for filling regions. When you're
done drawing, M-x artist-mode
goes back to whatever
mode you were using before.
I probably won't use it very much for note taking.
But there are times when I've wanted to draw ASCII graphics --
a laborious process in ordinary text modes --
and other times when it would just be fun to play around with my buffer.
I'm happy to know about Artist Mode.
I may not need it often, but it sure is fun to use now and then.
Tags: editors, emacs, graphics, education
[
20:02 Jan 10, 2013
More linux/editors |
permalink to this entry |
]
Thu, 09 Sep 2010
Part 2 in my Hugin series is out, in which I discuss how to rescue
difficult panoramas that confuse Hugin.
Hugin is an amazing program, but if you get outside the bounds of
the normal "Assistant" steps, the user interface can be a bit
confusing -- and sometimes it does things that are Just Plain Weird.
But with help from some folks on IRC, I found out that a newer
version of Hugin can fix those problems, and worked out how to do
it (as well as lots of ways that seemed like they should work, but
didn't).
Read the gory details in:
Hugin
part 2: Rescuing Difficult Panoramas.
There will be a Hugin Part 3, and possibly even a Part 4, discussing
things Hugin can do beyond panoramas.
Tags: writing, linux, graphics, panorama, hugin
[
14:58 Sep 09, 2010
More writing |
permalink to this entry |
]
Thu, 26 Aug 2010
A couple of weeks ago in my
Fotoxx
article I discussed using Fotoxx to create panoramas.
But for panoramas bigger than a couple of images, you're much better
off using the Linux panorama app: Hugin.
Hugin is very impressive, and much too capable to be summarized in a
single short article, so I'm planning three. This week's article is a
basic introduction:
Painless
Panorama Stitching with Hugin.
Tags: writing, linux, graphics, panorama, hugin
[
15:11 Aug 26, 2010
More writing |
permalink to this entry |
]
Thu, 12 Aug 2010
Dave stumbled on a neat little photo editor while tricking out his
old Vaio (P3/650 MHz, 192M RAM) and looking for lightweight apps.
It's called Fotoxx and it's quite impressive: easy to use and packed
with useful features.
So I wrote about it in this week's Linux Planet article:
Fotoxx,
the Greatest Little Linux Photo Editor You've Never Heard Of.
At first, I was most impressed by the Warp tool -- much easier to
use than GIMP's IWarp, though it's rather slow and not quite as
flexible as IWarp. But once I got to writing the article, I was
blown away by two additional features: it has an automatic panorama
stitcher and an HDR tool. GIMP doesn't have either of these
features, at all.
Now, panorama stitching used to be a big deal, but it isn't so much
any more now that Hugin has gotten much easier to use. (My article
in two weeks will be about Hugin.) Fotoxx isn't quite that flexible:
it can only stitch two images at a time, and can't handle images
with a lot of overlap. (But Hugin has some limitations too.)
But HDR -- wow! I've been meaning to learn more about making HDR
images in GIMP -- although it has no HDR tool, there are plug-ins to
make it a bit easier to assemble one, just like my Pandora plug-in
makes it a little easier to assemble panoramas. But now I don't need
to -- fotoxx handles it automatically.
I won't be switching from GIMP any time soon for regular photo
editing, of course -- GIMP is still much more flexible. But fotoxx
is definitely worth a look, and I'll be keeping it installed to make
HDR images, if nothing else.
Tags: writing, linux, graphics, panorama, HDR
[
15:44 Aug 12, 2010
More writing |
permalink to this entry |
]
Sat, 15 Nov 2008
Dave and I recently acquired a lovely trinket from a Mac-using friend:
an old 20-inch Apple Cinema Display.
I know what you're thinking (if you're not a Mac user): surely
Akkana's not lustful of Apple's vastly overpriced monitors when
brand-new monitors that size are selling for under $200!
Indeed, I thought that until fairly recently. But there actually
is a reason the Apple Cinema displays cost so much more than seemingly
equivalent monitors -- and it's not the color and shape of the bezel.
The difference is that Apple cinema displays are a technology called
S-IPS, while normal consumer LCD monitors -- those ones you
see at Fry's going for around $200 for a 22-inch 1680x1050 -- are
a technology called TN. (There's a third technology in between the
two called S-PVA, but it's rare.)
The main differences are color range and viewing angle.
The TN monitors can't display full color: they're only
6 bits per channel. They simulate colors outside that range
by cycling very rapidly between two similar colors
(this is called "dithering" but it's not the usual use of the term).
Modern TN monitors are
astoundingly fast, so they can do this dithering faster than
the eye can follow, but many people say they can still see the
color difference. S-IPS monitors show a true 8 bits per color channel.
The viewing angle difference is much easier to see. The published
numbers are similar, something like 160 degrees for TN monitors versus
180 degrees for S-IPS, but that doesn't begin to tell the story.
Align yourself in front of a TN monitor, so the colors look right.
Now stand up, if you're sitting down, or squat down if you're
standing. See how the image suddenly goes all inverse-video,
like a photographic negative only worse? Try that with an S-IPS monitor,
and no matter where you stand, all that happens is that the image
gets a little less bright.
(For those wanting more background, read
TN Film, MVA,
PVA and IPS – Which one's for you?, the articles on
TFT Central,
and the wikipedia
article on LCD technology.)
Now, the comparison isn't entirely one-sided. TN monitors have their
advantages too. They're outrageously inexpensive. They're blindingly
fast -- gamers like them because they don't leave "ghosts" behind
fast-moving images. And they're very power efficient (S-IPS monitors,
are only a little better than a CRT). But clearly, if you spend a lot
of time editing photos and an S-IPS monitor falls into your
possession, it's worth at least trying out.
But how? The old Apple Cinema display has a nonstandard connector,
called ADC, which provides video, power and USB1 all at once.
It turns out the only adaptor from a PC video card with DVI output
(forget about using an older card that supports only VGA) to an ADC
monitor is the $99 adaptor from the Apple store. It comes with a power
brick and USB plug.
Okay, that's a lot for an adaptor, but it's the only game in town,
so off I went to the Apple store, and a very short time later I had
the monitor plugged in to my machine and showing an image. (On Ubuntu
Hardy, simply removing xorg.conf was all I needed, and X automatically
detected the correct resolution. But eventually I put back one section
from my old xorg.conf, the keyboard section that specifies
"XkbOptions" to be "ctrl:nocaps".)
And oh, the image was beautiful. So sharp, clear, bright and colorful.
And I got it working so easily!
Of course, things weren't as good as they seemed (they never are, with
computers, are they?) Over the next few days I collected a list of
things that weren't working quite right:
- The Apple display had no brightness/contrast controls; I got
a pretty bad headache the first day sitting in front of that
full-brightness screen.
- Suspend didn't work. And here when I'd made so much progress
getting suspend to work on my desktop machine!
- While X worked great, the text console didn't.
The brightness problem was the easiest. A little web searching led me
to acdcontrol, a
commandline program to control brightness on Apple monitors.
It turns out that it works via the USB plug of the ADC connector,
which I initially hadn't connected (having not much use for another
USB 1.1 hub). Naturally, Ubuntu's udev/hal setup created the device
in a nonstandard place and with permissions that only worked for root,
so I had to figure out that I needed to edit
/etc/udev/rules.d/20-names.rules and change the hiddev line to read:
KERNEL=="hiddev[0-9]*", NAME="usb/%k", GROUP="video", MODE="0660"
That did the trick, and after that acdcontrol worked beautifully.
On the second problem, I never did figure out why suspending with
the Apple monitor always locked up the machine, either during suspend
or resume. I guess I could live without suspend on a desktop, though I
sure like having it.
The third problem was the killer. Big deal, who needs text consoles,
right? Well, I use them for debugging, but what was more important,
also broken were the grub screen (I could no longer choose
kernels or boot options) and the BIOS screen (not something
I need very often, but when you need it you really need it).
In fact, the text console itself wasn't a problem. It turns out the
problem is that the Apple display won't take a 640x480 signal.
I tried building a kernel with framebuffer enabled, and indeed,
that gave me back my boot messages and text consoles (at 1280x1024),
but still no grub or BIOS screens. It might be possible to hack a grub
that could display at 1280x1024. But never being able to change BIOS
parameters would be a drag.
The problems were mounting up. Some had solutions; some required
further hacking; some didn't have solutions at all. Was this monitor
worth the hassle? But the display was so beautiful ...
That was when Dave discovered TFT
Central's search page -- and we learned that the Dell 2005FPW
uses the exact same Philips tube as the
Apple, and there are lots of them for sale used,.
That sealed it -- Dave took the Apple monitor (he has a Mac, though
he'll need a solution for his Linux box too) and I bought a Dell.
Its image is just as beautiful as the Apple (and the bezel is nicer)
and it works with DVI or VGA, works at resolutions down to 640x480
and even has a powered speaker bar attached.
Maybe it's possible to make an old Apple Cinema display work on a Mac.
But it's way too much work. On a PC, the Dell is a much better bet.
Tags: linux, tech, photo, graphics, monitor, S-IPS, TN, ADC, DVI
[
21:57 Nov 15, 2008
More tech |
permalink to this entry |
]