This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenkernel/intern/image_gen.c

353 lines
9.1 KiB
C

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Matt Ebb, Campbell Barton, Shuvro Sarker
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/image_gen.c
* \ingroup bke
*/
#include <math.h>
#include <stdlib.h>
#include "BLI_math_base.h"
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
#include "BKE_image.h"
#include "BLF_api.h"
void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4])
{
int x, y;
/* blank image */
if (rect_float) {
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
copy_v4_v4(rect_float, color);
rect_float += 4;
}
}
}
if (rect) {
unsigned char ccol[4];
rgba_float_to_uchar(ccol, color);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
rect[0] = ccol[0];
rect[1] = ccol[1];
rect[2] = ccol[2];
rect[3] = ccol[3];
rect += 4;
}
}
}
}
void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height)
{
/* these two passes could be combined into one, but it's more readable and
* easy to tweak like this, speed isn't really that much of an issue in this situation... */
int checkerwidth = 32, dark = 1;
int x, y;
unsigned char *rect_orig = rect;
float *rect_float_orig = rect_float;
float h = 0.0, hoffs = 0.0;
float hsv[3] = {0.0f, 0.9f, 0.9f};
float rgb[3];
/* checkers */
for (y = 0; y < height; y++) {
dark = powf(-1.0f, floorf(y / checkerwidth));
for (x = 0; x < width; x++) {
if (x % checkerwidth == 0) dark = -dark;
if (rect_float) {
if (dark > 0) {
rect_float[0] = rect_float[1] = rect_float[2] = 0.25f;
rect_float[3] = 1.0f;
}
else {
rect_float[0] = rect_float[1] = rect_float[2] = 0.58f;
rect_float[3] = 1.0f;
}
rect_float += 4;
}
else {
if (dark > 0) {
rect[0] = rect[1] = rect[2] = 64;
rect[3] = 255;
}
else {
rect[0] = rect[1] = rect[2] = 150;
rect[3] = 255;
}
rect += 4;
}
}
}
rect = rect_orig;
rect_float = rect_float_orig;
/* 2nd pass, colored + */
for (y = 0; y < height; y++) {
hoffs = 0.125f * floorf(y / checkerwidth);
for (x = 0; x < width; x++) {
h = 0.125f * floorf(x / checkerwidth);
if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) &&
(fabs((y % checkerwidth) - (checkerwidth / 2)) < 4))
{
if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) ||
(fabs((y % checkerwidth) - (checkerwidth / 2)) < 1))
{
hsv[0] = fmodf(fabs(h - hoffs), 1.0f);
hsv_to_rgb_v(hsv, rgb);
if (rect) {
rect[0] = (char)(rgb[0] * 255.0f);
rect[1] = (char)(rgb[1] * 255.0f);
rect[2] = (char)(rgb[2] * 255.0f);
rect[3] = 255;
}
if (rect_float) {
rect_float[0] = rgb[0];
rect_float[1] = rgb[1];
rect_float[2] = rgb[2];
rect_float[3] = 1.0f;
}
}
}
if (rect_float) rect_float += 4;
if (rect) rect += 4;
}
}
}
/* Utility functions for BKE_image_buf_fill_checker_color */
#define BLEND_FLOAT(real, add) (real + add <= 1.0f) ? (real + add) : 1.0f
#define BLEND_CHAR(real, add) ((real + (char)(add * 255.0f)) <= 255) ? (real + (char)(add * 255.0f)) : 255
static void checker_board_color_fill(unsigned char *rect, float *rect_float, int width, int height)
{
int hue_step, y, x;
float hsv[3], rgb[3];
hsv[1] = 1.0;
hue_step = power_of_2_max_i(width / 8);
if (hue_step < 8) hue_step = 8;
for (y = 0; y < height; y++) {
hsv[2] = 0.1 + (y * (0.4 / height)); /* use a number lower then 1.0 else its too bright */
for (x = 0; x < width; x++) {
hsv[0] = (float)((double)(x / hue_step) * 1.0 / width * hue_step);
hsv_to_rgb_v(hsv, rgb);
if (rect) {
rect[0] = (char)(rgb[0] * 255.0f);
rect[1] = (char)(rgb[1] * 255.0f);
rect[2] = (char)(rgb[2] * 255.0f);
rect[3] = 255;
rect += 4;
}
if (rect_float) {
rect_float[0] = rgb[0];
rect_float[1] = rgb[1];
rect_float[2] = rgb[2];
rect_float[3] = 1.0f;
rect_float += 4;
}
}
}
}
static void checker_board_color_tint(unsigned char *rect, float *rect_float, int width, int height, int size, float blend)
{
int x, y;
float blend_half = blend * 0.5f;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if (((y / size) % 2 == 1 && (x / size) % 2 == 1) || ( (y / size) % 2 == 0 && (x / size) % 2 == 0)) {
if (rect) {
rect[0] = (char)BLEND_CHAR(rect[0], blend);
rect[1] = (char)BLEND_CHAR(rect[1], blend);
rect[2] = (char)BLEND_CHAR(rect[2], blend);
rect[3] = 255;
rect += 4;
}
if (rect_float) {
rect_float[0] = BLEND_FLOAT(rect_float[0], blend);
rect_float[1] = BLEND_FLOAT(rect_float[1], blend);
rect_float[2] = BLEND_FLOAT(rect_float[2], blend);
rect_float[3] = 1.0f;
rect_float += 4;
}
}
else {
if (rect) {
rect[0] = (char)BLEND_CHAR(rect[0], blend_half);
rect[1] = (char)BLEND_CHAR(rect[1], blend_half);
rect[2] = (char)BLEND_CHAR(rect[2], blend_half);
rect[3] = 255;
rect += 4;
}
if (rect_float) {
rect_float[0] = BLEND_FLOAT(rect_float[0], blend_half);
rect_float[1] = BLEND_FLOAT(rect_float[1], blend_half);
rect_float[2] = BLEND_FLOAT(rect_float[2], blend_half);
rect_float[3] = 1.0f;
rect_float += 4;
}
}
}
}
}
static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int width, int height, float blend)
{
int x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if (((y % 32) == 0) || ((x % 32) == 0) || x == 0) {
if (rect) {
rect[0] = BLEND_CHAR(rect[0], blend);
rect[1] = BLEND_CHAR(rect[1], blend);
rect[2] = BLEND_CHAR(rect[2], blend);
rect[3] = 255;
rect += 4;
}
if (rect_float) {
rect_float[0] = BLEND_FLOAT(rect_float[0], blend);
rect_float[1] = BLEND_FLOAT(rect_float[1], blend);
rect_float[2] = BLEND_FLOAT(rect_float[2], blend);
rect_float[3] = 1.0f;
rect_float += 4;
}
}
else {
if (rect_float) rect_float += 4;
if (rect) rect += 4;
}
}
}
}
/* defined in image.c */
static void checker_board_text(unsigned char *rect, float *rect_float, int width, int height, int step, int outline)
{
int x, y;
int pen_x, pen_y;
char text[3] = {'A', '1', '\0'};
const int mono = blf_mono_font_render;
BLF_size(mono, 54, 72); /* hard coded size! */
/* OCIO_TODO: using NULL as display will assume using sRGB display
* this is correct since currently generated images are assumed to be in sRGB space,
* but this would probably needed to be fixed in some way
*/
BLF_buffer(mono, rect_float, rect, width, height, 4, NULL);
for (y = 0; y < height; y += step) {
text[1] = '1';
for (x = 0; x < width; x += step) {
/* hard coded offset */
pen_x = x + 33;
pen_y = y + 44;
/* terribly crappy outline font! */
BLF_buffer_col(mono, 1.0, 1.0, 1.0, 1.0);
BLF_position(mono, pen_x - outline, pen_y, 0.0);
BLF_draw_buffer(mono, text);
BLF_position(mono, pen_x + outline, pen_y, 0.0);
BLF_draw_buffer(mono, text);
BLF_position(mono, pen_x, pen_y - outline, 0.0);
BLF_draw_buffer(mono, text);
BLF_position(mono, pen_x, pen_y + outline, 0.0);
BLF_draw_buffer(mono, text);
BLF_position(mono, pen_x - outline, pen_y - outline, 0.0);
BLF_draw_buffer(mono, text);
BLF_position(mono, pen_x + outline, pen_y + outline, 0.0);
BLF_draw_buffer(mono, text);
BLF_position(mono, pen_x - outline, pen_y + outline, 0.0);
BLF_draw_buffer(mono, text);
BLF_position(mono, pen_x + outline, pen_y - outline, 0.0);
BLF_draw_buffer(mono, text);
BLF_buffer_col(mono, 0.0, 0.0, 0.0, 1.0);
BLF_position(mono, pen_x, pen_y, 0.0);
BLF_draw_buffer(mono, text);
text[1]++;
}
text[0]++;
}
/* cleanup the buffer. */
BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
}
void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int width, int height)
{
checker_board_color_fill(rect, rect_float, width, height);
checker_board_color_tint(rect, rect_float, width, height, 1, 0.03f);
checker_board_color_tint(rect, rect_float, width, height, 4, 0.05f);
checker_board_color_tint(rect, rect_float, width, height, 32, 0.07f);
checker_board_color_tint(rect, rect_float, width, height, 128, 0.15f);
checker_board_grid_fill(rect, rect_float, width, height, 1.0f / 4.0f);
checker_board_text(rect, rect_float, width, height, 128, 2);
}