Files
test/intern/libmv/intern/image.cc
2023-06-15 13:35:34 +10:00

253 lines
7.3 KiB
C++

/* SPDX-FileCopyrightText: 2011 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "intern/image.h"
#include "intern/utildefines.h"
#include "libmv/tracking/track_region.h"
#include <png.h>
#include <cassert>
using libmv::FloatImage;
using libmv::SamplePlanarPatch;
void libmv_floatImageDestroy(libmv_FloatImage* image) {
delete[] image->buffer;
}
/* Image <-> buffers conversion */
void libmv_byteBufferToFloatImage(const unsigned char* buffer,
int width,
int height,
int channels,
FloatImage* image) {
image->Resize(height, width, channels);
for (int y = 0, a = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int k = 0; k < channels; k++) {
(*image)(y, x, k) = (float)buffer[a++] / 255.0f;
}
}
}
}
void libmv_floatBufferToFloatImage(const float* buffer,
int width,
int height,
int channels,
FloatImage* image) {
image->Resize(height, width, channels);
for (int y = 0, a = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int k = 0; k < channels; k++) {
(*image)(y, x, k) = buffer[a++];
}
}
}
}
void libmv_floatImageToFloatBuffer(const FloatImage& image, float* buffer) {
for (int y = 0, a = 0; y < image.Height(); y++) {
for (int x = 0; x < image.Width(); x++) {
for (int k = 0; k < image.Depth(); k++) {
buffer[a++] = image(y, x, k);
}
}
}
}
void libmv_floatImageToByteBuffer(const libmv::FloatImage& image,
unsigned char* buffer) {
for (int y = 0, a = 0; y < image.Height(); y++) {
for (int x = 0; x < image.Width(); x++) {
for (int k = 0; k < image.Depth(); k++) {
buffer[a++] = image(y, x, k) * 255.0f;
}
}
}
}
static bool savePNGImage(png_bytep* row_pointers,
int width,
int height,
int depth,
int color_type,
const char* file_name) {
png_infop info_ptr;
png_structp png_ptr;
FILE* fp = fopen(file_name, "wb");
if (fp == NULL) {
return false;
}
/* Initialize stuff */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info_ptr = png_create_info_struct(png_ptr);
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_init_io(png_ptr, fp);
/* Write PNG header. */
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_set_IHDR(png_ptr,
info_ptr,
width,
height,
depth,
color_type,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
/* Write bytes/ */
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_write_image(png_ptr, row_pointers);
/* End write/ */
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_write_end(png_ptr, NULL);
fclose(fp);
return true;
}
bool libmv_saveImage(const FloatImage& image,
const char* prefix,
int x0,
int y0) {
int x, y;
png_bytep* row_pointers;
assert(image.Depth() == 1);
row_pointers = new png_bytep[image.Height()];
for (y = 0; y < image.Height(); y++) {
row_pointers[y] = new png_byte[4 * image.Width()];
for (x = 0; x < image.Width(); x++) {
if (x0 == x && image.Height() - y0 - 1 == y) {
row_pointers[y][x * 4 + 0] = 255;
row_pointers[y][x * 4 + 1] = 0;
row_pointers[y][x * 4 + 2] = 0;
row_pointers[y][x * 4 + 3] = 255;
} else {
float pixel = image(image.Height() - y - 1, x, 0);
row_pointers[y][x * 4 + 0] = pixel * 255;
row_pointers[y][x * 4 + 1] = pixel * 255;
row_pointers[y][x * 4 + 2] = pixel * 255;
row_pointers[y][x * 4 + 3] = 255;
}
}
}
static int image_counter = 0;
char file_name[128];
snprintf(
file_name, sizeof(file_name), "%s_%02d.png", prefix, ++image_counter);
bool result = savePNGImage(row_pointers,
image.Width(),
image.Height(),
8,
PNG_COLOR_TYPE_RGBA,
file_name);
for (y = 0; y < image.Height(); y++) {
delete[] row_pointers[y];
}
delete[] row_pointers;
return result;
}
void libmv_samplePlanarPatchFloat(const float* image,
int width,
int height,
int channels,
const double* xs,
const double* ys,
int num_samples_x,
int num_samples_y,
const float* mask,
float* patch,
double* warped_position_x,
double* warped_position_y) {
FloatImage libmv_image, libmv_patch, libmv_mask;
FloatImage* libmv_mask_for_sample = NULL;
libmv_floatBufferToFloatImage(image, width, height, channels, &libmv_image);
if (mask) {
libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
libmv_mask_for_sample = &libmv_mask;
}
SamplePlanarPatch(libmv_image,
xs,
ys,
num_samples_x,
num_samples_y,
libmv_mask_for_sample,
&libmv_patch,
warped_position_x,
warped_position_y);
libmv_floatImageToFloatBuffer(libmv_patch, patch);
}
void libmv_samplePlanarPatchByte(const unsigned char* image,
int width,
int height,
int channels,
const double* xs,
const double* ys,
int num_samples_x,
int num_samples_y,
const float* mask,
unsigned char* patch,
double* warped_position_x,
double* warped_position_y) {
libmv::FloatImage libmv_image, libmv_patch, libmv_mask;
libmv::FloatImage* libmv_mask_for_sample = NULL;
libmv_byteBufferToFloatImage(image, width, height, channels, &libmv_image);
if (mask) {
libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
libmv_mask_for_sample = &libmv_mask;
}
libmv::SamplePlanarPatch(libmv_image,
xs,
ys,
num_samples_x,
num_samples_y,
libmv_mask_for_sample,
&libmv_patch,
warped_position_x,
warped_position_y);
libmv_floatImageToByteBuffer(libmv_patch, patch);
}