mirror of
https://github.com/google/pebble.git
synced 2025-06-20 00:00:36 +00:00
Import the pebble dev site into devsite/
This commit is contained in:
parent
3b92768480
commit
527858cf4c
1359 changed files with 265431 additions and 0 deletions
145
devsite/source/_guides/app-resources/animated-images.md
Normal file
145
devsite/source/_guides/app-resources/animated-images.md
Normal file
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
title: Animated Images
|
||||
description: |
|
||||
How to add animated image resources to a project in the APNG format, and
|
||||
display them in your app.
|
||||
guide_group: app-resources
|
||||
order: 0
|
||||
platform_choice: true
|
||||
---
|
||||
|
||||
The Pebble SDK allows animated images to be played inside an app using the
|
||||
``GBitmapSequence`` API, which takes [APNG](https://en.wikipedia.org/wiki/APNG)
|
||||
images as input files. APNG files are similar to well-known `.gif` files, which
|
||||
are not supported directly but can be converted to APNG.
|
||||
|
||||
A similar effect can be achieved with multiple image resources, a
|
||||
``BitmapLayer`` and an ``AppTimer``, but would require a lot more code. The
|
||||
``GBitmapSequence`` API handles the reading, decompression, and frame
|
||||
duration/count automatically.
|
||||
|
||||
|
||||
## Converting GIF to APNG
|
||||
|
||||
A `.gif` file can be converted to the APNG `.png` format with
|
||||
[gif2apng](http://gif2apng.sourceforge.net/) and the `-z0` flag:
|
||||
|
||||
```text
|
||||
./gif2apng -z0 animation.gif
|
||||
```
|
||||
|
||||
> Note: The file extension must be `.png`, **not** `.apng`.
|
||||
|
||||
|
||||
## Adding an APNG
|
||||
|
||||
{% platform local %}
|
||||
Include the APNG file in the `resources` array in `package.json` as a `raw`
|
||||
resource:
|
||||
|
||||
```js
|
||||
"resources": {
|
||||
"media": [
|
||||
{
|
||||
"type":"raw",
|
||||
"name":"ANIMATION",
|
||||
"file":"images/animation.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
{% endplatform %}
|
||||
|
||||
{% platform cloudpebble %}
|
||||
To add the APNG file as a raw resource, click 'Add New' in the Resources section
|
||||
of the sidebar, and set the 'Resource Type' as 'raw binary blob'.
|
||||
{% endplatform %}
|
||||
|
||||
## Displaying APNG Frames
|
||||
|
||||
The ``GBitmapSequence`` will use a ``GBitmap`` as a container and update its
|
||||
contents each time a new frame is read from the APNG file. This means that the
|
||||
first step is to create a blank ``GBitmap`` to be this container.
|
||||
|
||||
Declare file-scope variables to hold the data:
|
||||
|
||||
```c
|
||||
static GBitmapSequence *s_sequence;
|
||||
static GBitmap *s_bitmap;
|
||||
```
|
||||
|
||||
Load the APNG from resources into the ``GBitmapSequence`` variable, and use the
|
||||
frame size to create the blank ``GBitmap`` frame container:
|
||||
|
||||
|
||||
```c
|
||||
// Create sequence
|
||||
s_sequence = gbitmap_sequence_create_with_resource(RESOURCE_ID_ANIMATION);
|
||||
|
||||
// Create blank GBitmap using APNG frame size
|
||||
GSize frame_size = gbitmap_sequence_get_bitmap_size(s_sequence);
|
||||
s_bitmap = gbitmap_create_blank(frame_size, GBitmapFormat8Bit);
|
||||
```
|
||||
|
||||
Once the app is ready to begin playing the animated image, advance each frame
|
||||
using an ``AppTimer`` until the end of the sequence is reached. Loading the next
|
||||
APNG frame is handled for you and written to the container ``GBitmap``.
|
||||
|
||||
Declare a ``BitmapLayer`` variable to display the current frame, and set it up
|
||||
as described under
|
||||
{% guide_link app-resources/images#displaying-an-image "Displaying An Image" %}.
|
||||
|
||||
```c
|
||||
static BitmapLayer *s_bitmap_layer;
|
||||
```
|
||||
|
||||
Create the callback to be used when the ``AppTimer`` has elapsed, and the next
|
||||
frame should be displayed. This will occur in a loop until there are no more
|
||||
frames, and ``gbitmap_sequence_update_bitmap_next_frame()`` returns `false`:
|
||||
|
||||
```c
|
||||
static void timer_handler(void *context) {
|
||||
uint32_t next_delay;
|
||||
|
||||
// Advance to the next APNG frame, and get the delay for this frame
|
||||
if(gbitmap_sequence_update_bitmap_next_frame(s_sequence, s_bitmap, &next_delay)) {
|
||||
// Set the new frame into the BitmapLayer
|
||||
bitmap_layer_set_bitmap(s_bitmap_layer, s_bitmap);
|
||||
layer_mark_dirty(bitmap_layer_get_layer(s_bitmap_layer));
|
||||
|
||||
// Timer for that frame's delay
|
||||
app_timer_register(next_delay, timer_handler, NULL);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When appropriate, schedule the first frame advance with an ``AppTimer``:
|
||||
|
||||
```c
|
||||
uint32_t first_delay_ms = 10;
|
||||
|
||||
// Schedule a timer to advance the first frame
|
||||
app_timer_register(first_delay_ms, timer_handler, NULL);
|
||||
```
|
||||
|
||||
When the app exits or the resource is no longer required, destroy the
|
||||
``GBitmapSequence`` and the container ``GBitmap``:
|
||||
|
||||
```c
|
||||
gbitmap_sequence_destroy(s_sequence);
|
||||
gbitmap_destroy(s_bitmap);
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue