Blender V5.0
intern/libmv/intern/image.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "intern/image.h"
8
9#include <png.h>
10#include <cassert>
11
14
16 delete[] image->buffer;
17}
18
19/* Image <-> buffers conversion */
20
21void libmv_byteBufferToFloatImage(const unsigned char* buffer,
22 int width,
23 int height,
24 int channels,
25 FloatImage* image) {
26 image->Resize(height, width, channels);
27 for (int y = 0, a = 0; y < height; y++) {
28 for (int x = 0; x < width; x++) {
29 for (int k = 0; k < channels; k++) {
30 (*image)(y, x, k) = (float)buffer[a++] / 255.0f;
31 }
32 }
33 }
34}
35
36void libmv_floatBufferToFloatImage(const float* buffer,
37 int width,
38 int height,
39 int channels,
40 FloatImage* image) {
41 image->Resize(height, width, channels);
42 for (int y = 0, a = 0; y < height; y++) {
43 for (int x = 0; x < width; x++) {
44 for (int k = 0; k < channels; k++) {
45 (*image)(y, x, k) = buffer[a++];
46 }
47 }
48 }
49}
50
51void libmv_floatImageToFloatBuffer(const FloatImage& image, float* buffer) {
52 for (int y = 0, a = 0; y < image.Height(); y++) {
53 for (int x = 0; x < image.Width(); x++) {
54 for (int k = 0; k < image.Depth(); k++) {
55 buffer[a++] = image(y, x, k);
56 }
57 }
58 }
59}
60
62 unsigned char* buffer) {
63 for (int y = 0, a = 0; y < image.Height(); y++) {
64 for (int x = 0; x < image.Width(); x++) {
65 for (int k = 0; k < image.Depth(); k++) {
66 buffer[a++] = image(y, x, k) * 255.0f;
67 }
68 }
69 }
70}
71
72static bool savePNGImage(png_bytep* row_pointers,
73 int width,
74 int height,
75 int depth,
76 int color_type,
77 const char* file_name) {
78 png_infop info_ptr;
79 png_structp png_ptr;
80 FILE* fp = fopen(file_name, "wb");
81
82 if (fp == NULL) {
83 return false;
84 }
85
86 /* Initialize stuff */
87 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
88 info_ptr = png_create_info_struct(png_ptr);
89
90 if (setjmp(png_jmpbuf(png_ptr))) {
91 fclose(fp);
92 return false;
93 }
94
95 png_init_io(png_ptr, fp);
96
97 /* Write PNG header. */
98 if (setjmp(png_jmpbuf(png_ptr))) {
99 fclose(fp);
100 return false;
101 }
102
103 png_set_IHDR(png_ptr,
104 info_ptr,
105 width,
106 height,
107 depth,
108 color_type,
109 PNG_INTERLACE_NONE,
110 PNG_COMPRESSION_TYPE_BASE,
111 PNG_FILTER_TYPE_BASE);
112
113 png_write_info(png_ptr, info_ptr);
114
115 /* Write bytes/ */
116 if (setjmp(png_jmpbuf(png_ptr))) {
117 fclose(fp);
118 return false;
119 }
120
121 png_write_image(png_ptr, row_pointers);
122
123 /* End write/ */
124 if (setjmp(png_jmpbuf(png_ptr))) {
125 fclose(fp);
126 return false;
127 }
128
129 png_write_end(png_ptr, NULL);
130 fclose(fp);
131
132 return true;
133}
134
135bool libmv_saveImage(const FloatImage& image,
136 const char* prefix,
137 int x0,
138 int y0) {
139 int x, y;
140 png_bytep* row_pointers;
141
142 assert(image.Depth() == 1);
143
144 row_pointers = new png_bytep[image.Height()];
145
146 for (y = 0; y < image.Height(); y++) {
147 row_pointers[y] = new png_byte[4 * image.Width()];
148
149 for (x = 0; x < image.Width(); x++) {
150 if (x0 == x && image.Height() - y0 - 1 == y) {
151 row_pointers[y][x * 4 + 0] = 255;
152 row_pointers[y][x * 4 + 1] = 0;
153 row_pointers[y][x * 4 + 2] = 0;
154 row_pointers[y][x * 4 + 3] = 255;
155 } else {
156 float pixel = image(image.Height() - y - 1, x, 0);
157 row_pointers[y][x * 4 + 0] = pixel * 255;
158 row_pointers[y][x * 4 + 1] = pixel * 255;
159 row_pointers[y][x * 4 + 2] = pixel * 255;
160 row_pointers[y][x * 4 + 3] = 255;
161 }
162 }
163 }
164
165 static int image_counter = 0;
166 char file_name[128];
167 snprintf(
168 file_name, sizeof(file_name), "%s_%02d.png", prefix, ++image_counter);
169 bool result = savePNGImage(row_pointers,
170 image.Width(),
171 image.Height(),
172 8,
173 PNG_COLOR_TYPE_RGBA,
174 file_name);
175
176 for (y = 0; y < image.Height(); y++) {
177 delete[] row_pointers[y];
178 }
179 delete[] row_pointers;
180
181 return result;
182}
183
184void libmv_samplePlanarPatchFloat(const float* image,
185 int width,
186 int height,
187 int channels,
188 const double* xs,
189 const double* ys,
190 int num_samples_x,
191 int num_samples_y,
192 const float* mask,
193 float* patch,
194 double* warped_position_x,
195 double* warped_position_y) {
196 FloatImage libmv_image, libmv_patch, libmv_mask;
197 FloatImage* libmv_mask_for_sample = NULL;
198
199 libmv_floatBufferToFloatImage(image, width, height, channels, &libmv_image);
200
201 if (mask) {
202 libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
203 libmv_mask_for_sample = &libmv_mask;
204 }
205
206 SamplePlanarPatch(libmv_image,
207 xs,
208 ys,
209 num_samples_x,
210 num_samples_y,
211 libmv_mask_for_sample,
212 &libmv_patch,
213 warped_position_x,
214 warped_position_y);
215
216 libmv_floatImageToFloatBuffer(libmv_patch, patch);
217}
218
219void libmv_samplePlanarPatchByte(const unsigned char* image,
220 int width,
221 int height,
222 int channels,
223 const double* xs,
224 const double* ys,
225 int num_samples_x,
226 int num_samples_y,
227 const float* mask,
228 unsigned char* patch,
229 double* warped_position_x,
230 double* warped_position_y) {
231 libmv::FloatImage libmv_image, libmv_patch, libmv_mask;
232 libmv::FloatImage* libmv_mask_for_sample = NULL;
233
234 libmv_byteBufferToFloatImage(image, width, height, channels, &libmv_image);
235
236 if (mask) {
237 libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
238 libmv_mask_for_sample = &libmv_mask;
239 }
240
241 libmv::SamplePlanarPatch(libmv_image,
242 xs,
243 ys,
244 num_samples_x,
245 num_samples_y,
246 libmv_mask_for_sample,
247 &libmv_patch,
248 warped_position_x,
249 warped_position_y);
250
251 libmv_floatImageToByteBuffer(libmv_patch, patch);
252}
void Resize(int height, int width, int depth=1)
Definition array_nd.h:341
int Depth() const
Definition array_nd.h:347
int Height() const
Definition array_nd.h:345
int Width() const
Definition array_nd.h:346
#define assert(assertion)
bool libmv_saveImage(const FloatImage &image, const char *prefix, int x0, int y0)
static bool savePNGImage(png_bytep *row_pointers, int width, int height, int depth, int color_type, const char *file_name)
void libmv_floatBufferToFloatImage(const float *buffer, int width, int height, int channels, FloatImage *image)
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)
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)
void libmv_floatImageToFloatBuffer(const FloatImage &image, float *buffer)
void libmv_floatImageDestroy(libmv_FloatImage *image)
bool SamplePlanarPatch(const FloatImage &image, const double *xs, const double *ys, int num_samples_x, int num_samples_y, FloatImage *mask, FloatImage *patch, double *warped_position_x, double *warped_position_y)
void libmv_floatImageToByteBuffer(const libmv::FloatImage &image, unsigned char *buffer)
void libmv_byteBufferToFloatImage(const unsigned char *buffer, int width, int height, int channels, FloatImage *image)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
Array3Df FloatImage
bool SamplePlanarPatch(const FloatImage &image, const double *xs, const double *ys, int num_samples_x, int num_samples_y, FloatImage *mask, FloatImage *patch, double *warped_position_x, double *warped_position_y)