Welcome to Arkanis Development

A simple one-file image gallery


First a small disclaimer: This stuff is only useful if you have some webspace lying around and don't want to use a cloud thing or if a full blown gallery is to annoying or complex for your needs.

For the last few years I used a small PHP image gallery to share images (primarily Kerbal Space Program screenshots). I uploaded images via SSH and the script would automatically show all images and create thumbnails when necessary. While this isn't useful for most people it worked quite well for me.

A few days ago I was bored and started to build a new image gallery. This time based on some browser APIs I wanted to tinker with for some time now: Drag & drop and AJAX file uploads. My goal was to drag & drop images directly into the gallery, encode them as JPEGs, create thumbnails and then upload the stuff.

  • Drag & drop because it's simple and it fits quite well with the way I chose which images I want to upload.
  • Because Elite: Dangerous creates screenshots as bitmaps I wanted to convert them to JPEGs before uploading them. This way the browser can also create the thumbnails. No need for any GD library (image processing) on the server side.
  • Finally I wanted to have an efficient upload: Just sending the raw data directly as the request body. No form encoding and without loading the entire file into memory. But this part of the experiment was actually for a different project (uploading large video files into an archive).

I pushed the result up to github. A simple image gallery that's just one PHP file. Drop it into a directory and that directory becomes the gallery (given the webserver has write permission for that directory to store new images there). It's not really production grade software: The browser might hang when you drop a large image and the thumbnails might look jagged with some images. But it's good enough for me at the moment.

Tinkering around with the drag & drop, binary upload and upload progress stuff was quite interesting. It seems to work more or less but I'm still confused about how progress events are triggered (files seem ok but array buffers are a different topic). I was quite glad that Chrome and Firefox could actually upload large files without completely loading them into memory. While useless for the image gallery that will come in handy for a different project.

On the down side I was somewhat annoyed by other aspects of the implementations. Reading a file as a data URL seems to block the browser (at least Firefox) as does rendering the image into a canvas to get the pixel values for the JPEG encoder. I would have liked to put that stuff into a webworker (another thread) but they can't use DOM stuff like image or canvas elements. So no solution there. For normal images it doesn't matter much but for larger images it's quite noticeable.

Sometimes it kind of strikes me that when working with browser I have to switch into "try to creatively abuse a scripted document viewer" mode. To solve a problem you have to gather together and combine components in sometimes funny ways. Usually I like that aspect of web development, it's almost like playing a puzzle game. But sometimes it just becomes smelly. For example to decode an image (get its pixel values) I had to convert it into a data URL (base64 encoded string), create an img element with that URL as its src attribute, draw that image element onto a canvas and finally get the pixel data from there.

There's a good reason browser are like this. After all they're for viewing websites, not offering a complete or sane programming environment. But even in plain C the above task is simple compared to the browser: You can go for a straight solution, just load the image with a library like stb_image. Done. Even resizing (stb_image_resize) and encoding (stb_image_write) is simple.

On the other hand GUI stuff and drag & drop probably isn't as simple in C as it is in browsers. And since it's all about an image gallery comparing it with C is kind of stupid. But a few times I was tempted to just compile this stuff into JavaScript so I can put it into a webworker and stop the browser from hanging. Funny like the old stuff makes me think straight and the new stuff think in puzzles.

Oh, that became quite a detour from the original topic. Shouldn't write blog posts when I'm way to tired… :P

Leave a new comment

Having thoughts on your mind about this stuff here? Want to tell me and the rest of the world your opinion? Write and post it right here. Be sure to check out the format help (focus the large text field) and give the preview button a try.

Format help

Please us the following stuff to spice up your comment.

An empty line starts a new paragraph. ---- print "---- lines start/end code" ---- * List items start with a * or -