blob: 0638523569841f0e9d0d5fed397281b3fb3989b2 [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/raw12_writer.h"
#include <lib/syslog/cpp/macros.h>
#include <array>
#include <vector>
namespace camera {
// Helper methods.
std::array<uint8_t, kBytesPerDoublePixel> PixelValuesToDoublePixel(uint16_t first_pixel_val,
uint16_t second_pixel_val) {
return std::array<uint8_t, kBytesPerDoublePixel>(
{static_cast<uint8_t>(((first_pixel_val & kHighByteMask) >> kHalfByteShift)),
static_cast<uint8_t>(((second_pixel_val & kHighByteMask) >> kHalfByteShift)),
static_cast<uint8_t>((((second_pixel_val & kLowHalfByteMask) << kHalfByteShift) |
(first_pixel_val & kLowHalfByteMask)))});
}
std::pair<uint16_t, uint16_t> DoublePixelToPixelValues(
std::array<uint8_t, kBytesPerDoublePixel> double_pixel) {
return std::pair(
(double_pixel[0] << kHalfByteShift) | (double_pixel[2] & kLowHalfByteMask),
(double_pixel[1] << kHalfByteShift) | ((double_pixel[2] & kHighByteMask) >> kHalfByteShift));
}
// RAW12 Writer methods.
fpromise::result<std::unique_ptr<Raw12Writer>, zx_status_t> Raw12Writer::Create(uint32_t width,
uint32_t height) {
// TODO(nzo): consider if there's a case where odd width/height would be necessary.
if (!(width > 0 && height > 0)) {
FX_LOGS(DEBUG) << "Invalid dimensions passed in.";
return fpromise::error(ZX_ERR_INVALID_ARGS);
}
const size_t kSize = width * height * kBytesPerDoublePixel;
return fpromise::ok(std::make_unique<Raw12Writer>(width, height, kSize));
}
zx_status_t Raw12Writer::Write(zx::vmo* vmo, uint16_t r, uint16_t g, uint16_t b) {
zx_status_t status = zx::vmo::create(vmo_size(), 0, vmo);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to create VMO.";
return status;
}
std::array<uint8_t, kBytesPerDoublePixel> double_pixel_val;
auto buf = std::vector<uint8_t>(vmo_size(), 0);
// Value for colors on the first column/row will be zero, increase by constant factor up to
// maximum value for every column/row after that.
const uint16_t kGreenStepFactor = (height() == 1) ? 0 : b / (height() - 1);
const uint16_t kBlueStepFactor = (width() == 1) ? 0 : g / (width() - 1);
uint16_t green_pixel = 0;
uint16_t blue_pixel = 0;
uint32_t row_num = 0;
for (uint32_t i = 0; i < vmo_size(); i += kBytesPerDoublePixel) {
if ((i != 0) && (i % (width() * kBytesPerDoublePixel) == 0)) {
row_num++;
green_pixel += kGreenStepFactor;
blue_pixel = 0;
}
double_pixel_val = (row_num % 2 == 0) ? PixelValuesToDoublePixel(r, green_pixel)
: PixelValuesToDoublePixel(green_pixel, blue_pixel);
buf[i] = double_pixel_val[0];
buf[i + 1] = double_pixel_val[1];
buf[i + 2] = double_pixel_val[2];
blue_pixel += kBlueStepFactor;
}
status = vmo->write(&buf.front(), 0, buf.size());
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to write to VMO.";
return status;
}
return ZX_OK;
}
} // namespace camera