blob: a919adec06b511bad8067d24d2e5787ab4b3774e [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/camera/lib/image_utils/hsv_generator.h"
#include <lib/image-format/image_format.h>
#include <lib/syslog/cpp/macros.h>
#include "src/camera/lib/image_utils/color_source.h"
#include "src/camera/lib/image_utils/image_format_rgba.h"
namespace camera {
constexpr uint8_t kTwoByteShift = 16;
constexpr uint8_t kOneByteShift = 8;
// Set the alpha value to 100%:
constexpr uint8_t kAlphaValue = 0xff;
constexpr uint8_t kOneByteMask = 0xff;
constexpr uint64_t kTwoByteMask = 0xffff;
// Write an image plane whose pixels are 2^n bytes wide.
template <class PixelSize>
void WriteByteAligned(void* start, PixelSize value, uint32_t width, uint32_t height,
uint32_t stride) {
auto* pixels = reinterpret_cast<PixelSize*>(start);
for (uint32_t row = 0; row < height; ++row) {
for (uint32_t col = 0; col < width; ++col) {
pixels[row * stride / sizeof(value) + col] = value;
}
}
}
void WriteSingleColorImage(Rgba rgba, const fuchsia::sysmem::ImageFormat_2& format, void* buffer) {
// Check if valid format
uint32_t packed_value = RgbaPack(format.pixel_format.type, rgba);
uint32_t bytes_per_pixel =
ImageFormatBitsPerPixel(ConvertPixelFormatToWire(format.pixel_format)) / 8;
if (bytes_per_pixel == 4) {
WriteByteAligned(buffer, packed_value, format.coded_width, format.coded_height,
format.bytes_per_row);
}
// 24 bit formats need to be handles specially, because we don't have a uint24_t:
if (bytes_per_pixel == 3) {
auto* pixels = reinterpret_cast<uint8_t*>(buffer);
uint8_t color1 = packed_value >> kTwoByteShift & kOneByteMask;
uint8_t color2 = packed_value >> kOneByteShift & kOneByteMask;
uint8_t color3 = packed_value & kOneByteMask;
for (uint32_t row = 0; row < format.coded_height; ++row) {
for (uint32_t col = 0; col < format.coded_width; ++col) {
uint32_t start = row * format.bytes_per_row + col * bytes_per_pixel;
pixels[start] = color1;
pixels[start + 1] = color2;
pixels[start + 2] = color3;
}
}
}
if (bytes_per_pixel == 2) {
uint16_t color = packed_value & kTwoByteMask;
WriteByteAligned(buffer, color, format.coded_width, format.coded_height, format.bytes_per_row);
}
if (bytes_per_pixel == 1) {
uint8_t color = packed_value & kOneByteMask;
WriteByteAligned(buffer, color, format.coded_width, format.coded_height, format.bytes_per_row);
}
}
zx_status_t HsvGenerator(void* start, const fuchsia::sysmem::ImageFormat_2& format,
uint32_t frame_index) {
// Currently only support RGB colors
if (!IsSupportedPixelFormat(format.pixel_format.type)) {
FX_LOGS(ERROR) << "Unsupported format";
return ZX_ERR_INVALID_ARGS;
}
// Get the color:
Rgba color;
ColorSource::hsv_color(frame_index, &color.r, &color.g, &color.b);
color.a = kAlphaValue;
WriteSingleColorImage(color, format, start);
return ZX_OK;
}
} // namespace camera