mirror of
https://github.com/google/pebble.git
synced 2025-07-04 22:00:38 -04:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
153
tools/pebble_image_routines.py
Normal file
153
tools/pebble_image_routines.py
Normal file
|
@ -0,0 +1,153 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2024 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.
|
||||
|
||||
|
||||
import math
|
||||
|
||||
# This module contains common image and color routines used to convert images
|
||||
# for use with Pebble.
|
||||
#
|
||||
# pebble64 refers to the color palette that is available in color products,
|
||||
# pebble2 refers to the palette available in b&w products
|
||||
|
||||
TRUNCATE = "truncate"
|
||||
NEAREST = "nearest"
|
||||
|
||||
# Create pebble 64 colors-table (r, g, b - 2 bits per channel)
|
||||
def _get_pebble64_palette():
|
||||
pebble_palette = []
|
||||
for i in xrange(0, 64):
|
||||
pebble_palette.append((
|
||||
((i >> 4) & 0x3) * 85, # R
|
||||
((i >> 2) & 0x3) * 85, # G
|
||||
((i ) & 0x3) * 85)) # B
|
||||
return pebble_palette
|
||||
|
||||
|
||||
def nearest_color_to_pebble64_palette(r, g, b, a):
|
||||
"""
|
||||
match each rgba32 pixel to the nearest color in the 8 bit pebble palette
|
||||
returns closest rgba32 color triplet (r, g, b, a)
|
||||
"""
|
||||
|
||||
a = ((a + 42) / 85) * 85 # fast nearest alpha for 2bit color range
|
||||
# clear transparent pixels (makes image more compress-able)
|
||||
# and required for greyscale tests
|
||||
if a == 0:
|
||||
r, g, b = (0, 0, 0)
|
||||
else:
|
||||
r = ((r + 42) / 85) * 85 # nearest for 2bit color range
|
||||
g = ((g + 42) / 85) * 85 # nearest for 2bit color range
|
||||
b = ((b + 42) / 85) * 85 # nearest for 2bit color range
|
||||
|
||||
return r, g, b, a
|
||||
|
||||
|
||||
def nearest_color_to_pebble2_palette(r, g, b, a):
|
||||
"""
|
||||
match each rgba32 pixel to the nearest color in 2 bit pebble palette
|
||||
returns closest rgba32 color triplet (r, g, b, a)
|
||||
"""
|
||||
|
||||
# these constants come from ITU-R recommendation BT.709
|
||||
luma = (r * 0.2126 + g * 0.7152 + b * 0.11)
|
||||
|
||||
def round_to_1_bit(value):
|
||||
""" Round a [0-255] value to either 0 or 255 """
|
||||
if value > (255 / 2):
|
||||
return 255
|
||||
return 0
|
||||
|
||||
rounded_luma = round_to_1_bit(luma)
|
||||
return (rounded_luma, rounded_luma, rounded_luma, round_to_1_bit(a))
|
||||
|
||||
|
||||
def truncate_color_to_pebble64_palette(r, g, b, a):
|
||||
"""
|
||||
converts each rgba32 pixel to the next lower matching color (truncate method)
|
||||
in the pebble palette
|
||||
returns the truncated color as a rgba32 color triplet (r, g, b, a)
|
||||
"""
|
||||
|
||||
a = (a / 85) * 85 # truncate alpha for 2bit color range
|
||||
# clear transparent pixels (makes image more compress-able)
|
||||
# and required for greyscale tests
|
||||
if a == 0:
|
||||
r, g, b = (0, 0, 0)
|
||||
else:
|
||||
r = (r / 85) * 85 # truncate for 2bit color range
|
||||
g = (g / 85) * 85 # truncate for 2bit color range
|
||||
b = (b / 85) * 85 # truncate for 2bit color range
|
||||
|
||||
return r, g, b, a
|
||||
|
||||
|
||||
def truncate_color_to_pebble2_palette(r, g, b, a):
|
||||
"""
|
||||
converts each rgba32 pixel to the next lower matching color (truncate method)
|
||||
returns closest rgba32 color triplet (r, g, b, a)
|
||||
"""
|
||||
|
||||
if a != 255:
|
||||
a = 0
|
||||
|
||||
if r == 255 and g == 255 and b == 255:
|
||||
return r, g, b, a
|
||||
else:
|
||||
return 0, 0, 0, a
|
||||
|
||||
|
||||
def rgba32_triplet_to_argb8(r, g, b, a):
|
||||
"""
|
||||
converts a 32-bit RGBA color by channel to an ARGB8 (1 byte containing all 4 channels)
|
||||
"""
|
||||
a, r, g, b = (a >> 6, r >> 6, g >> 6, b >> 6)
|
||||
argb8 = (a << 6) | (r << 4) | (g << 2) | b
|
||||
return argb8
|
||||
|
||||
|
||||
# convert 32-bit color (r, g, b, a) to 32-bit RGBA word
|
||||
def rgba32_triplet_to_rgba32(r, g, b, a):
|
||||
return (((r & 0xFF) << 24) | ((g & 0xFF) << 16) | ((b & 0xFF) << 8) | (a & 0xFF))
|
||||
|
||||
|
||||
# takes number of colors and outputs PNG & PBI compatible bit depths for paletted images
|
||||
def num_colors_to_bitdepth(num_colors):
|
||||
bitdepth = int(math.ceil(math.log(num_colors, 2)))
|
||||
|
||||
# only bitdepth 1,2,4 and 8 supported by PBI and PNG
|
||||
if bitdepth == 0:
|
||||
# caused when palette has only 1 color
|
||||
bitdepth = 1
|
||||
elif bitdepth == 3:
|
||||
bitdepth = 4
|
||||
elif bitdepth > 4:
|
||||
bitdepth = 8
|
||||
|
||||
return bitdepth
|
||||
|
||||
|
||||
def get_reduction_func(palette_name, color_reduction_method):
|
||||
reduction_funcs = {
|
||||
'pebble64': {
|
||||
NEAREST: nearest_color_to_pebble64_palette,
|
||||
TRUNCATE: truncate_color_to_pebble64_palette
|
||||
},
|
||||
'pebble2': {
|
||||
NEAREST: nearest_color_to_pebble2_palette,
|
||||
TRUNCATE: truncate_color_to_pebble2_palette
|
||||
}
|
||||
}
|
||||
return reduction_funcs[palette_name][color_reduction_method]
|
Loading…
Add table
Add a link
Reference in a new issue