InverterLayer (and other effects) for Pebble Time

Inverter EffectMirror Effect
InverterLayer is a pretty cool feature of Pebble smartwath SDK, its simple purpose to invert colors of everything it’s placed over (black becomes white and vice versa).

Unfortunately it no longer works in SDK 3 (Basalt, Pebble Time) and will be depreciated. Fortunately it’s pretty straightforward to create your own InverterLayer.

The idea is to create a basic Layer and in the layer’s callback function (called when layer needs to redraw) capture screen framebuffer and invert colors at layer’s coordinates.

Here’s a stub for callback handler:

static void effect_layer_update_proc(Layer *me, GContext* ctx) {
  GRect layer_frame = layer_get_frame(me);  
  
  GBitmap *fb = graphics_capture_frame_buffer_format(ctx, GBitmapFormat8Bit);
  GRect window_dim = gbitmap_get_bounds(fb);
  uint8_t *fb_data = gbitmap_get_data(fb);
  
  effect_invert(fb_data,  layer_frame.origin.x,  layer_frame.origin.y, layer_frame.size.h, layer_frame.size.w, window_dim.size.w);
    
  graphics_release_frame_buffer(ctx, fb);
  
}

Here Line 2 gets layer position (x,y) and dimensions (h,w), Lines 4-6 capture current screen as a bitmap, get dimensions of the bitmap (basically window size) and get bitmap as raw data. Then Line 8 calls function to apply inverter effect and Line 10 releases the framebuffer.

Function effect_invert is pretty straightforward too:

void effect_invert(uint8_t *fb_data, int x, int y, int h, int w, int window_w) {
  
  int j = y * window_w + x; 
  
  for (int i=0; i < h * w ; i++) {
    
    fb_data[j] = ~fb_data[j];
    
    if (i !=0 && i % w  == 0) {
       j += window_w - w + 1;
    } else {
       j++;
    }
     
  }  
  
}

Here Line 3 calculates position of first pixel of our layer in framebuffer array (based on Y coordinates, width of the window and X coordinate). Then begin looping thru layer (Line 5), inverting every pixel in framebuffer data (Line 7). Lines 9-13 determine if whether we need to jump to the next line on the screen or simple advance to the next pixel.

Effect of such “InverterLayer” is shown on the left screenshot above. But this approach lets you add more pluggable effects. Just create a new function and call it in layer callback. EffectLayer library is based on this approach and at the time of this writing has one more effect – “Mirror”, showing on the left screenshot above.

Useful Links:

Leave a Reply

Your email address will not be published. Required fields are marked *