mirror of
https://github.com/google/pebble.git
synced 2025-06-04 09:13:12 +00:00
76 lines
4 KiB
C
76 lines
4 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
|
|
//! This function extracts a value for a specific bit per pixel depth from an image buffer
|
|
//! at a specific x y position.
|
|
//! @note inlined to support performance requirements of iterating over every pixel in an image
|
|
//! @param buffer pointer to a buffer containing pixel image data
|
|
//! @param x the x coordinates for the pixel to retrieve
|
|
//! @param y the y coordinates for the pixel to retrieve
|
|
//! @param width provides the image width
|
|
//! @param row_stride_bytes the byte-aligned width in bytes
|
|
//! @param bitdepth bits per pixel for the image (1,2,4 or 8 supported)
|
|
//! @return The value from the image buffer at the specified coordinates
|
|
static ALWAYS_INLINE uint8_t raw_image_get_value_for_bitdepth(const uint8_t *raw_image_buffer,
|
|
uint32_t x, uint32_t y, uint16_t row_stride_bytes, uint8_t bitdepth) {
|
|
// Retrieve the byte from the image buffer containing the requested pixel
|
|
uint32_t pixel_in_byte = raw_image_buffer[y * row_stride_bytes + (x * bitdepth / 8)];
|
|
// Find the index of the pixel in terms of coordinates and aligned_width
|
|
uint32_t pixel_index = y * (row_stride_bytes * 8 / bitdepth) + x;
|
|
// Shift and mask the requested pixel data from the byte containing it and return
|
|
return (uint8_t)((pixel_in_byte >> ((((8 / bitdepth) - 1) - (pixel_index % (8 / bitdepth)))
|
|
* bitdepth)) & ~(~0 << bitdepth));
|
|
}
|
|
|
|
//! This function sets a pixel value for a specific bits-per-pixel depth in an image buffer
|
|
//! at a specific (x, y) coordinate.
|
|
//! @note inlined to support performance requirements of iterating over every pixel in an image
|
|
//! @param raw_image_buffer Pointer to a buffer containing image pixel data
|
|
//! @param x The x coordinate for the pixel to retrieve
|
|
//! @param y The y coordinate for the pixel to retrieve
|
|
//! @param row_stride_bytes The byte-aligned width of each row in bytes
|
|
//! @param bitdepth The bits-per-pixel for the image (Only 1, 2, 4 or 8 bitdepths are supported)
|
|
//! @param value The pixel value to set in the image buffer at the specified (x, y) coordinates
|
|
static ALWAYS_INLINE void raw_image_set_value_for_bitdepth(uint8_t *raw_image_buffer,
|
|
uint32_t x, uint32_t y,
|
|
uint16_t row_stride_bytes,
|
|
uint8_t bitdepth, uint8_t value) {
|
|
const uint8_t pixels_per_byte = (uint8_t)(8 / bitdepth);
|
|
|
|
// Retrieve the byte from the image buffer containing the requested pixel
|
|
const uint32_t byte_offset = y * row_stride_bytes + (x * bitdepth / 8);
|
|
const uint8_t pixel_in_byte = raw_image_buffer[byte_offset];
|
|
|
|
// Find the index of the pixel in terms of coordinates and aligned_width
|
|
const uint32_t pixel_index = (y * (row_stride_bytes * pixels_per_byte) + x) % pixels_per_byte;
|
|
|
|
// For example, bitdepth=1 -> bitdepth_mask=0b1, bitdepth=2 -> bitdepth_mask=0b11, etc.
|
|
const uint8_t bitdepth_mask = (uint8_t)~(~0 << bitdepth);
|
|
|
|
const uint32_t bits_to_shift = (pixels_per_byte - 1 - pixel_index) * bitdepth;
|
|
|
|
const uint8_t value_position_mask = ~(bitdepth_mask << bits_to_shift);
|
|
|
|
const uint8_t value_shifted_to_position = (value & bitdepth_mask) << bits_to_shift;
|
|
|
|
// Finally, update the byte where the pixel is located using the value_mask
|
|
const uint8_t new_byte_value = (pixel_in_byte & value_position_mask) | value_shifted_to_position;
|
|
raw_image_buffer[byte_offset] = new_byte_value;
|
|
}
|