mirror of
https://github.com/google/pebble.git
synced 2025-06-05 17:53:11 +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
163
devsite/source/_posts/2015-12-02-Bitmap-Resources.md
Normal file
163
devsite/source/_posts/2015-12-02-Bitmap-Resources.md
Normal file
|
@ -0,0 +1,163 @@
|
|||
---
|
||||
# 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: Unifying bitmap resources
|
||||
author: katharine
|
||||
tags:
|
||||
- Freshly Baked
|
||||
---
|
||||
|
||||
With the upcoming release of firmware 3.8 on Pebble and Pebble Steel, and the
|
||||
associated SDK 3.8, we have decided to redesign how image resources work in
|
||||
Pebble apps.
|
||||
|
||||
|
||||
|
||||
|
||||
Why change?
|
||||
-----------
|
||||
|
||||
First, some history: when SDK 1 was originally released, and continuing up to
|
||||
SDK 2.9, there was a single image type, `png`. A `png` resource would take a PNG
|
||||
as input and spit out a custom, uncompressed, 1-bit-per-pixel image format we
|
||||
called "pbi". This was the only bitmap format Pebble supported, and life was
|
||||
simple.
|
||||
|
||||
With the release of SDK 3.0, we added firmware support for a new image format:
|
||||
PNG (with some restrictions). This enabled Pebble to directly read compressed
|
||||
images, and those images could be 1-bit, 2-bit, 4-bit or 8-bit palettised. The
|
||||
existing `png` resource type was changed to produce these images instead of the
|
||||
old PBI format, and everyone had smaller image resources.
|
||||
|
||||
Unfortunately, "png" isn't the best option for all cases. The old 1-bit format
|
||||
supported some [compositing operations](``GCompOp``) that other image formats
|
||||
do not support. We added the `pbi` format to achieve this legacy behavior.
|
||||
Additionally, PNG decompression isn't free: loading a PNG resource requires
|
||||
enough memory to hold the compressed image, the uncompressed image, and some
|
||||
scratch space. This was often offset by the benefits of palettised images with
|
||||
fewer bits per pixel, but sometimes it didn't fit. We added `pbi8`, which
|
||||
produced 8-bit-per-pixel PBI images. This still left it impossible to generate
|
||||
a palettized PBI, even though the format does exist.
|
||||
|
||||
As a further complication, since SDK 1 and continuing through the present day,
|
||||
`pbi` (and `pbi8`) images have cropped transparent borders around the outside.
|
||||
However, `png` images (as of SDK 3) do _not_ crop like this. The cropping
|
||||
behavior was originally a bug, and is generally undesirable, but must be
|
||||
maintained for backwards compatibility.
|
||||
|
||||
There is one additional exception to all of this: until SDK 3.8, the Aplite platform still
|
||||
interprets `png` to mean `pbi`. It also interprets `pbi8` to mean `pbi`. When
|
||||
we built the 3.8 SDK, we changed `png` to really mean `png` on Aplite.
|
||||
Unfortunately, the more limited memory of the Aplite platform meant that these
|
||||
PNGs sometimes did not have enough space to decompress. The only workaround was
|
||||
to duplicate resources and use `targetPlatforms` to specify a `pbi` resource for
|
||||
Aplite and a `png` resource for Basalt and Chalk.
|
||||
|
||||
The easiest answer was to keep `png` as an alias for `pbi` on Aplite—but then
|
||||
there's no way of generating a real PNG for Aplite. Furthermore, the `png`,
|
||||
`pbi` and `pbi8` trio was getting confusing, so we decided to do something else.
|
||||
|
||||
"bitmap" to the rescue
|
||||
----------------------
|
||||
|
||||
As of SDK 3.8, `png`, `pbi` and `pbi8` **are all deprecated**. We are instead
|
||||
introducing a new resource type, `bitmap`. This new resource type unifies all
|
||||
the existing types, allows the SDK to use its best judgement, increases the
|
||||
flexibility available to developers, and takes the guesswork out of advanced
|
||||
image manipulation. It also removes the generally undesirable forced cropping
|
||||
behavior.
|
||||
|
||||
The simplest option is to only specify that you want a `bitmap` resource, and
|
||||
by default the SDK will do the most reasonable thing:
|
||||
|
||||
```js
|
||||
{
|
||||
"type": "bitmap",
|
||||
"name": "IMAGE_BERRY_PUNCH",
|
||||
"file": "images/berry-punch.png"
|
||||
}
|
||||
```
|
||||
|
||||
This will create an image with the smallest possible in-memory representation,
|
||||
which will depend on the number of colors. On Aplite, where memory is tight,
|
||||
it will optimize for low memory consumption by creating a pbi. On all other
|
||||
platforms, where there is more memory to spare, it will create a png.
|
||||
|
||||
This behavior can be overridden using the following attributes:
|
||||
|
||||
* `memoryFormat`: This determines the `GBitmapFormat` that the resulting image
|
||||
will have. The default value is `Smallest`, which picks the value that will
|
||||
use the least memory. If you have specific requirements, you can specify:
|
||||
`SmallestPalette`, `1BitPalette`, `2BitPalette`, `4BitPalette`, `1Bit` or
|
||||
`8Bit`. If an image cannot be represented in the requested format, a build
|
||||
error will result. This, for instance, enables palette manipulation with
|
||||
static checking for confidence that you will have an appropriate palette to
|
||||
manipulate.
|
||||
* `spaceOptimization`: This determines whether we should optimize the image for
|
||||
resource space (`storage`) or memory (`memory`). The default depends on the
|
||||
memory available on the platform: Aplite defaults to `memory`, while other
|
||||
platforms default to `storage`.
|
||||
* `storageFormat`: This explicitly states whether an image should be stored on
|
||||
flash as a PNG or pbi image. In most cases you should not specify this, and
|
||||
instead depend on `spaceOptimization`. However, if you read resources
|
||||
directly, this option exists to force a value.
|
||||
|
||||
So if you want an image that will always have a 2-bit palette and use as little
|
||||
memory as possible, you can do this:
|
||||
|
||||
```js
|
||||
{
|
||||
"type": "bitmap",
|
||||
"name": "IMAGE_TIME_TURNER",
|
||||
"file": "images/time-turner.png",
|
||||
"memoryFormat": "2BitPalette",
|
||||
"spaceOptimization": "memory"
|
||||
}
|
||||
```
|
||||
|
||||
The resulting image will always have `GBitmapFormat2BitPalette`, even if it
|
||||
could have a 1-bit palette. If it has more than four colors, the build will
|
||||
fail.
|
||||
|
||||
In SDK 3.8-beta8, this would result in a 2-bit palettized pbi. However, this
|
||||
is not guaranteed: we can change the format in the future, as long as the result
|
||||
has ``GBitmapFormat2BitPalette`` and we prefer to optimise for memory
|
||||
consumption where possible.
|
||||
|
||||
Finally, note that some combinations are impossible: for instance, a `1Bit`
|
||||
image can never be stored as a PNG, so `"storageFormat": "png"` combined with
|
||||
`"memoryFormat": "1Bit"` will be a compile error.
|
||||
|
||||
Migration
|
||||
---------
|
||||
|
||||
If you have an existing app, how do you migrate it to use the new `bitmap` type?
|
||||
|
||||
If you were depending on the `pbi` cropping behavior, you will have to manually
|
||||
crop your image. Beyond that, this table gives the equivalences:
|
||||
|
||||
| SDK 3.7 type | `bitmap` specification |
|
||||
|--------------|----------------------------------------------|
|
||||
| `png` | `{"type": "bitmap"}` |
|
||||
| `pbi` | `{"type": "bitmap", "memoryFormat": "1Bit"}` |
|
||||
| `pbi8` | `{"type": "bitmap", "storageFormat": "pbi"}` |
|
||||
|
||||
`png-trans` has been left out of this entire exercise. Its behavior is unchanged:
|
||||
it will produce two pbis with `GBitmapFormat1Bit`. However, `png-trans` is also
|
||||
deprecated and discouraged. As of SDK 3.8, all platforms support transparency
|
||||
in images, and so should use `bitmap` instead.
|
||||
|
||||
If you have any questions, you can [find us on Discord]({{ site.links.discord_invite }})
|
||||
or [contact us](/contact/).
|
Loading…
Add table
Add a link
Reference in a new issue