Archive for the ‘bootsplash’ Category

USplash screen for ubuntu with “animated gif”

Today I needed to change the boot screen of my ubuntu machine. It’s a computer (actually a mac mini) that I’m setting up to be used as a info screen in stores and on a 9m^2 led screen. We want the logo of the company to be the main focus when booting, so I set to create a theme for usplash in ubuntu, since I had already finished customizing rEfid.

I started reading this: https://help.ubuntu.com/community/USplashCustomizationHowto, which helped me to understand the basics, and find the source code example.

The fact that the boot theme is coded in C, and that the functions is called 25 times a second, gave me an idea: I wanted a mac/flash like loader like the ones you see at http://ajaxload.info/. So I generated an animated gif from that page, with the colors that matched my theme.

Next I had to split the animated gif into a bunch of png images, and generate a palette for my main theme image, and then reuse the palette on all the image files.

Splitting the gif is easy with ImageMagick:

convert loading.gif loading.png


This makes loading-0.png through loading-11.png. In Photoshop it was easy to make a predefined “Action” that adds the palette, saves the file, closes it, and does the same to all the other pictures. (Also easy in Gimp of course)

This is important because we are restricted to use 1 palette, so all the images need to have the same one. A tip is to add all the objects you need into the background image, then convert the image to indexed(256color) and extract the palette. Now you remove the objects again, and use this palette for all the images.

Now, the only thing left was the code.

In the Makefile, I added loading_0.png.c.o through loading_12.png.c.o, so that make generates object files for the images. Next I went into the theme source file, and added an “extern struct usplash_pixmap” definition for all the images I needed.

First I needed to define the images in the code, so I could use the linked objects:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct usplash_pixmap *pixmap_loader[12];
 
extern struct usplash_pixmap pixmap_loader_bg;
extern struct usplash_pixmap pixmap_loader_0;
extern struct usplash_pixmap pixmap_loader_1;
extern struct usplash_pixmap pixmap_loader_2;
extern struct usplash_pixmap pixmap_loader_3;
extern struct usplash_pixmap pixmap_loader_4;
extern struct usplash_pixmap pixmap_loader_5;
extern struct usplash_pixmap pixmap_loader_6;
extern struct usplash_pixmap pixmap_loader_7;
extern struct usplash_pixmap pixmap_loader_8;
extern struct usplash_pixmap pixmap_loader_9;
extern struct usplash_pixmap pixmap_loader_10;
extern struct usplash_pixmap pixmap_loader_11;

And added this code to the init section, to be able to reach the loading image from an array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void t_init(struct usplash_theme *theme) {
    int x, y;
    usplash_getdimensions(&x, &y);
    theme->progressbar_x = (x - theme->pixmap->width)/2 + theme->progressbar_x;
    theme->progressbar_y = (y - theme->pixmap->height)/2 + theme->progressbar_y;
    pixmap_loader[0] = &pixmap_loader_0;
    pixmap_loader[1] = &pixmap_loader_1;
    pixmap_loader[2] = &pixmap_loader_2;
    pixmap_loader[3] = &pixmap_loader_3;
    pixmap_loader[4] = &pixmap_loader_4;
    pixmap_loader[5] = &pixmap_loader_5;
    pixmap_loader[6] = &pixmap_loader_6;
    pixmap_loader[7] = &pixmap_loader_7;
    pixmap_loader[8] = &pixmap_loader_8;
    pixmap_loader[9] = &pixmap_loader_9;
    pixmap_loader[10] = &pixmap_loader_10;
    pixmap_loader[11] = &pixmap_loader_11;
}

I now replaced the example t_animate_step function with the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
void t_animate_step(struct usplash_theme* theme, int pulsating) {
 
    static int pulsate_step = 0;
    unsigned char step_num = 0;
    unsigned int position_x = theme->progressbar_x + (pixmap_throbber_back.width - pixmap_loader_bg.width) / 2;
 
    if (pulsating) {
        pulsate_step ++;
        step_num = (unsigned char)(pulsate_step/2) % 12;
        usplash_put(position_x, theme->progressbar_y, &pixmap_loader_bg);
        usplash_put_part(position_x, theme->progressbar_y, 32, 32, pixmap_loader[step_num], 0, 0);
    }
}

Whats happening here is that when the “pulsating” flag is active, it increases the pulsate_step counter, and for each 2nd step/frame, “step_num” increases, running from 0-11 and around again(using modulus). Then I draw first the background, and then the actual image.

I also had to add the following function t_draw_progressbar, so the “pulsating” loader, which is larger than the progressbar, doesn’t destroy the theme with remains of the “gif”.

1
2
   unsigned int position_x = theme->progressbar_x + (pixmap_throbber_back.width - pixmap_loader_bg.width) / 2;
   usplash_put(position_x, theme->progressbar_y, &pixmap_loader_bg);

Result:

Full source code with images and binary:
trippelm-usplash.tar.gz

Tip:
To add a usplash theme to your ubuntu, you could install the nifty startup configurator:

apt-get install startupmanager

This will make it easy to add/change the boot splash without using the console. Just add the .so file from your theme, and select it as the current boot splash.