Files
OmaPhoto/tests/CameraRawFixtures.h

87 lines
2.9 KiB
C++

#pragma once
#include "Document/BrushStroke.h"
#include "Document/CameraRaw.h"
#include <QColor>
#include <QPainter>
#include <algorithm>
#include <array>
#include <vector>
// Swift's CameraRawTests helpers: solid pictures and straight bytes.
namespace CameraRawFixtures {
inline QImage image(int width, int height, double red, double green, double blue, double alpha = 1)
{
QImage context = BrushRaster::context(width, height, false);
QPainter painter(&context);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.fillRect(context.rect(), QColor::fromRgbF(float(red), float(green), float(blue), float(alpha)));
return context;
}
inline QImage gray(int width = 4, int height = 4, double alpha = 1)
{
return image(width, height, 128 / 255.0, 128 / 255.0, 128 / 255.0, alpha);
}
// Straight RGBA, top row first, rounded as Swift's.
inline std::vector<std::array<int, 4>> pixels(const QImage &source)
{
const QImage drawn = source.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
std::vector<std::array<int, 4>> result;
for (int y = 0; y < drawn.height(); ++y) {
const uchar *row = drawn.constScanLine(y);
for (int x = 0; x < drawn.width(); ++x) {
const uchar *p = row + x * 4;
const int alpha = p[3];
std::array<int, 4> pixel{0, 0, 0, alpha};
for (int channel = 0; channel < 3; ++channel)
pixel[size_t(channel)] = alpha == 0 ? 0 : std::min(255, (p[channel] * 255 + alpha / 2) / alpha);
result.push_back(pixel);
}
}
return result;
}
inline int chroma(const std::array<int, 4> &pixel)
{
return std::max({pixel[0], pixel[1], pixel[2]}) - std::min({pixel[0], pixel[1], pixel[2]});
}
// Two tones side by side, one pixel each.
inline QImage pair(int left, int right)
{
QImage context = BrushRaster::context(2, 1, false);
context.setPixelColor(0, 0, QColor(left, left, left));
context.setPixelColor(1, 0, QColor(right, right, right));
return context;
}
// A step, 40 to 200 at x 12.
inline QImage step()
{
QImage context = BrushRaster::context(24, 4, false);
for (int y = 0; y < 4; ++y)
for (int x = 0; x < 24; ++x)
context.setPixelColor(x, y, x < 12 ? QColor(40, 40, 40) : QColor(200, 200, 200));
return context;
}
// A checkerboard of 2-pixel squares: a warp shows on it.
inline QImage checker(int width = 24, int height = 24)
{
QImage context = BrushRaster::context(width, height, false);
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x) {
const bool light = ((x / 2) + (y / 2)) % 2 == 0;
const double level = light ? 0.9 : 0.1;
context.setPixelColor(x, y, QColor::fromRgbF(float(level), float(level), float(level)));
}
return context;
}
inline int peakIndex(const std::array<double, 256> &bins)
{
return int(std::max_element(bins.begin(), bins.end()) - bins.begin());
}
}