| // 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 <cmath> |
| #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. |
| fit::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 fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| const size_t kSize = width * height * kBytesPerDoublePixel; |
| return fit::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 |