summaryrefslogtreecommitdiff
path: root/amber/camera/libhdrplusclient/HdrPlusClientUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'amber/camera/libhdrplusclient/HdrPlusClientUtils.cpp')
-rw-r--r--amber/camera/libhdrplusclient/HdrPlusClientUtils.cpp197
1 files changed, 197 insertions, 0 deletions
diff --git a/amber/camera/libhdrplusclient/HdrPlusClientUtils.cpp b/amber/camera/libhdrplusclient/HdrPlusClientUtils.cpp
new file mode 100644
index 0000000..1fb6838
--- /dev/null
+++ b/amber/camera/libhdrplusclient/HdrPlusClientUtils.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HdrPlusClientUtils"
+#include <log/log.h>
+
+#include <fstream>
+#include <inttypes.h>
+#include <system/graphics.h>
+
+#include "HdrPlusClientUtils.h"
+
+namespace android {
+namespace hdrplus_client_utils {
+
+// Get the RGB values of the pixel at (x, y).
+static status_t getRgb(uint8_t *r, uint8_t *g, uint8_t* b, uint32_t x, uint32_t y,
+ const pbcamera::StreamConfiguration &streamConfig,
+ const pbcamera::StreamBuffer &buffer) {
+ switch (streamConfig.image.format) {
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ {
+ // Check the stream configuration has two planes.
+ if (streamConfig.image.planes.size() != 2) {
+ ALOGE("%s: NV21 should have 2 planes but it has %zu", __FUNCTION__,
+ streamConfig.image.planes.size());
+ return BAD_VALUE;
+ }
+
+ // Find the indices of Y, V, and U in the buffer.
+ uint32_t yIndex = y * streamConfig.image.planes[0].stride + x;
+ uint32_t vIndex = streamConfig.image.planes[0].scanline *
+ streamConfig.image.planes[0].stride +
+ (y / 2) * streamConfig.image.planes[1].stride + (x & ~0x1);
+ uint32_t uIndex = vIndex + 1;
+
+ // Convert YUV to RGB.
+ int32_t yc = ((uint8_t*)buffer.data)[yIndex];
+ int32_t vc = ((uint8_t*)buffer.data)[vIndex] - 128;
+ int32_t uc = ((uint8_t*)buffer.data)[uIndex] - 128;
+ *r = std::min(std::max(yc + 0.003036f * uc + 1.399457f * vc, 0.0f), 255.0f);
+ *g = std::min(std::max(yc - 0.344228f * uc - 0.717202f * vc, 0.0f), 255.0f);
+ *b = std::min(std::max(yc + 1.772431f * uc - 0.006137f * vc, 0.0f), 255.0f);
+ return OK;
+ }
+ case HAL_PIXEL_FORMAT_RGB_888:
+ {
+ // Check the stream configuration has 1 plane.
+ if (streamConfig.image.planes.size() != 1) {
+ ALOGE("%s: RGB_888 should have 1 plane but it has %zu", __FUNCTION__,
+ streamConfig.image.planes.size());
+ return BAD_VALUE;
+ }
+
+ uint32_t offset = y * streamConfig.image.planes[0].stride + x * 3;
+ *r = ((uint8_t*)buffer.data)[offset];
+ *g = ((uint8_t*)buffer.data)[offset + 1];
+ *b = ((uint8_t*)buffer.data)[offset + 2];
+ return OK;
+ }
+ default:
+ ALOGE("%s: Format %d is not supported.", __FUNCTION__, streamConfig.image.format);
+ return BAD_VALUE;
+ }
+}
+
+status_t writePpm(const std::string &filename, const pbcamera::StreamConfiguration &streamConfig,
+ const pbcamera::StreamBuffer &buffer) {
+ if (streamConfig.image.format != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
+ streamConfig.image.format != HAL_PIXEL_FORMAT_RGB_888) {
+ ALOGE("%s: format 0x%x is not supported.", __FUNCTION__, streamConfig.image.format);
+ return BAD_VALUE;
+ }
+
+ std::ofstream outfile(filename, std::ios::binary);
+ if (!outfile.is_open()) {
+ ALOGE("%s: Opening file (%s) failed.", __FUNCTION__, filename.data());
+ return NO_INIT;
+ }
+
+ uint32_t width = streamConfig.image.width;
+ uint32_t height = streamConfig.image.height;
+
+ // Write headers of the ppm file.
+ outfile << "P6";
+ outfile << " " << std::to_string(width) << " " << std::to_string(height) << " 255 ";
+
+ // Write RGB values of the image.
+ uint8_t r, g, b;
+ for (uint32_t y = 0; y < height; y++) {
+ for (uint32_t x = 0; x < width; x++) {
+ status_t res = getRgb(&r, &g, &b, x, y, streamConfig, buffer);
+ if (res != OK) {
+ ALOGE("%s: Getting RGB failed: %s (%d).", __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ outfile << r << g << b;
+ }
+ }
+
+ ALOGD("%s: Saved file: %s", __FUNCTION__, filename.data());
+
+ outfile.close();
+ return OK;
+}
+
+status_t comparePpm(const std::string &filename, const pbcamera::StreamConfiguration &streamConfig,
+ const pbcamera::StreamBuffer &buffer, float *diffRatio) {
+ if (streamConfig.image.format != HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+ ALOGE("%s: format 0x%x is not supported.", __FUNCTION__, streamConfig.image.format);
+ return BAD_VALUE;
+ }
+
+ std::ifstream ifile(filename, std::ios::binary);
+ if (!ifile.is_open()) {
+ ALOGE("%s: Opening file (%s) failed.", __FUNCTION__, filename.data());
+ return NO_INIT;
+ }
+
+ std::string s;
+
+ // Read headers of the ppm file.
+ ifile >> s;
+ if (s != "P6") {
+ ALOGE("%s: Invalid PPM file header: %s", __FUNCTION__, s.c_str());
+ return BAD_VALUE;
+ }
+
+ // Read width and height.
+ ifile >> s;
+ uint32_t width = std::stoul(s);
+
+ ifile >> s;
+ uint32_t height = std::stoul(s);
+
+ if (width != streamConfig.image.width || height != streamConfig.image.height) {
+ ALOGE("%s: Image resolution doesn't match. image %dx%d ppm %dx%d",
+ __FUNCTION__, streamConfig.image.width, streamConfig.image.height,
+ width, height);
+ return BAD_VALUE;
+ }
+
+ ifile >> s;
+ if (s != "255") {
+ ALOGE("%s: Expecting 255 but got %s", __FUNCTION__, s.c_str());
+ return BAD_VALUE;
+ }
+
+ char c;
+
+ // Get a space
+ ifile.get(c);
+
+ // Now the RGB values start.
+ uint8_t r, g, b;
+ uint64_t diff = 0;
+
+ for (uint32_t y = 0; y < height; y++) {
+ for (uint32_t x = 0; x < width; x++) {
+ status_t res = getRgb(&r, &g, &b, x, y, streamConfig, buffer);
+ if (res != OK) {
+ ALOGE("%s: Getting RGB failed: %s (%d).", __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+
+ // Get r, g, b from golden image and accumulate the differences.
+ ifile.get(c);
+ diff += abs(static_cast<int32_t>(c) - r);
+ ifile.get(c);
+ diff += abs(static_cast<int32_t>(c) - g);
+ ifile.get(c);
+ diff += abs(static_cast<int32_t>(c) - b);
+ }
+ }
+
+ if (diffRatio != nullptr) {
+ *diffRatio = diff / (static_cast<float>(width) * height * 3 * 256);
+ }
+
+ return OK;
+}
+
+} // hdrplus_client_utils
+} // namespace android