22. October 2017

SDL2_image for iOS with JPEG image format

Adding SDL2_image with JPEG support for iOS is a little bit different than for Android. In case of Android, it was necessary to add JPEG library in C and build it. iOS has JPEG dependency hidden in another library which is already compiled in frameworks.

If you just add SDL2_image to your project for iOS, you will very likely end up with following linker error:

"_kUTTypeJPEG", referenced from ...
Linker command failed with exit code 1

To resolve this issue, it is sufficient to add two dependencies into your project.

Go to Project and select Build Phases.

In the section Linking add library: ImageIO.framework

Then add the second dependency: MobileCoreServices.framework

Then Clean and Build the project.

These steps should resolve the linker issue, and JPEG should work.

31. August 2017

SDL2_image for Android with JPEG image format

In the previous article, we were discussing how to add support for PNG image format to SDL2 application for Android. Let’s add another more common format. What about JPEG?

The first step is to enable JPEG in SDL2_image. Just add a proper definition to SDL2_image/build.gradle.

ndk {
...
CFlags.addAll([
    "-DLOAD_JPG"
    "-DLOAD_PNG",
    "-DLOAD_XPM"
])}

Then it is necessary to add C implementation of JPEG library. There is one big catch. Do not call it jpeg. The problem is that the name will collide with another library in Android system and function jpeg_create_decompress(&cinfo) will crash. Thanks to DevMultiTech for a hint about the solution.

Let’s call the jpeg library SDL2_jpeg.

Register modules in settings.gradle:

include ':SDL2_jpeg'

Build all libraries:

gradle distributeLib

Here is a sample code for loading and displaying JPEG image:

SDL_Surface *backgroundSurface = IMG_Load("brno-snow.jpg")
SDL_Texture *backgroundTexture = SDL_CreateTextureFromSurface(renderer, backgroundSurface);
SDL_RenderCopy(renderer, backgroundTexture, NULL, &dstrect);

Result looks like this:

You can find whole source code at https://github.com/georgik/sdl2-android-example.

You can find about SDL2 and libraries more under the topic SDL2.

28. December 2011

CGI server? Bash one-liner!

Author: Lordrat

By now you know, that when you need simple server to serve static pages just for you to play, you use Python’s SimpleHTTPServer.

But this time I wanted more: I wanted to to able to use serve images caught by my webcam. CGI server would be quick answer. While there is class in python doing that, I did not wanted to play with it. I needed something quick to do and maybe I was just little lazy to do so this day.

First thought: one window while cycle with cam-grabber, in the other window SimpleHTTPServer. Well, the solution lacked elegance, as it was not one-liner-styled enough. And then it occurred to me: why not use Netcat?

Building Blocks

 

At first, I needed to get data from camera. I had figured how to do that some time ago.

vgrabbj -i vga -d /dev/video0 -a -z 10 -q 100

Let’s just elaborate on that a little bit. vgrabbj takes `640×480` image from video4linux device `/dev/video0`, with enabled brightness adjustment, taking 10 images just to adjust, and using 100% quality of JPEG, and sending it to stdout.

Another building block is “server” to serve something that returned command. NetCat is our fiend. Little-bit of HTTP-fu is needed, but not much.

{ echo -ne 'HTTP/1.0 200 OK\r\nConnection: Close\r\n\r\n'; cat file; } | nc -l 1234

We will be serving JPEG, so we add appropriate HTTP header (unless you can see things in binary garbage).

Content-Type: image/jpeg

It may happen that file-size of image will cripple user’s comfort over slower network. What about speeding it up by sending response gzipped? We will need header

Content-Encoding: gzip

and we will have to use… you guessed it: gzip.

gzip -f

However, gzip will not reduce the size of JPEG much, as it already has entropy quite high. We can decrease quality of image i.g. by switch -q of vgrabbj, but in this case I would prefer ImageMagick for reasons that will become clear in a moment. Another possibility how to deal with this issue is scaling image down, which can be done here as well.

convert - -quality 75 -

It will also be nice to have a non-crippled copy of served file. Can do that: tee.

Serving repeatedly can be done by i.e. by while loop. Small functional enhancement: it will be nice to have so called “auto-refresh”. Adding one HTTP header will do that for us. Say every 5 seconds.

Refresh: 5

Some cooling enhancements? Server header:

Server: CoolServer!

Assembling

 

And now just put it all together.

while :; do { echo -ne 'HTTP/1.0 200 OK\r\nServer: Kwak!\r\nConnection: Close'\
'\r\nRefresh: 5\r\nContent-Type: image/jpeg\r\nContent-Encoding: gzip\r\n\r\n'\
; vgrabbj -i vga -d /dev/video0 -a -z 10 -q 100 | tee omg-`date +'%Y-%m-%d-%H'\
'%M%S'`.jpg | convert - -quality 75 - | gzip -f; } | nc -l 1234; done

Feel free to unwrap it ;-).
And a non-one-liner (little bit more readable) version:

#!/bin/bash
PORT=1234
QUALITY=75
REFRESH=5
HEADER='HTTP/1.0 200 OK\r\n'
HEADER=$HEADER'Server: CoolServer!\r\n'
HEADER=$HEADER"Refresh: $REFRESH\r\n"
HEADER=$HEADER'Connection: Close\r\n'
HEADER=$HEADER'Content-Type: image/jpeg\r\n'
HEADER=$HEADER'Content-Encoding: gzip\r\n'
HEADER=$HEADER'\r\n'
while :; do
    {
        echo -ne "$HEADER"
        vgrabbj -i vga -d /dev/video0 -a -z 10 -q 100 \
        | tee omg-`date +'%Y-%m-%d-%H%M%S'`.jpg \
        | convert - -quality "$QUALITY" - \
        | gzip -f
    } \
    | nc -l "$PORT"
done

Notes

 

  • Some versions of nc may need to be called more like `nc -l -p 1234`.
  • First photo will be served from time you started script, every other from time the last shoot was taken. (Exercise for patient reader: why it is so? ;-) ). This might not be issue, as it speeds up reading of photo on request.
  • Previous can be solved by creating script, that can be called by nc on connection. That way you can create even interactive “CGI” script, that will read (and parse) input from std in and write response to stdout. Not all versions of nc are able to do that.
  • Another exercise: Will you be able to secure your communication using stunnel.

Enjoy ;-)