FloatImg/Fonderie/sfx.c

517 lines
12 KiB
C
Raw Normal View History

2020-11-02 11:25:00 +11:00
/*
* SPECIAL EFFECTS
*
* Du code bien cracra / tTh / Tetalab
*/
#include <stdio.h>
#include <string.h>
2021-05-20 18:31:28 +11:00
#include <stdint.h>
2020-11-02 11:25:00 +11:00
#include <stdlib.h>
#include <malloc.h>
2020-12-29 22:56:26 +11:00
#include <math.h>
2020-11-02 11:25:00 +11:00
2020-12-03 05:55:06 +11:00
#include "../floatimg.h"
2020-11-02 11:25:00 +11:00
2021-04-03 04:25:20 +11:00
#include "fifo.h"
2021-01-04 01:21:38 +11:00
#include "metriques.h"
2020-12-03 05:55:06 +11:00
#include "sfx.h"
2020-11-02 11:25:00 +11:00
/* -------------------------------------------------------------- */
2020-11-05 22:48:35 +11:00
/* here are global vars exported by the main module
2020-11-02 11:25:00 +11:00
*/
2020-11-03 00:51:48 +11:00
extern int verbosity;
2020-11-02 11:25:00 +11:00
2023-07-16 21:39:49 +11:00
/* -------------------------------------------------------------- */
/*
* nouveau Sun Jul 16 07:37:22 UTC 2023
2023-07-17 22:43:31 +11:00
*
* may-be this can be an on-place function ?
*
2023-07-16 21:39:49 +11:00
*/
int poke_sup_rb_g(FloatImg *src, FloatImg *dst)
{
int idx, nbpix, foo;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %p )\n", __func__, src, dst);
#endif
if ( (foo=fimg_images_not_compatible(src, dst)) )
{
fprintf(stderr, "%s: no compat %d\n", __func__, foo);
return foo;
}
nbpix = src->width * src->height;
2023-07-17 16:44:39 +11:00
if (verbosity > 1)
fprintf(stderr, "%s work on %d pixels\n", __func__, nbpix);
2023-07-16 21:39:49 +11:00
for (idx=0; idx<nbpix; idx++) {
dst->R[idx] = src->R[idx];
dst->B[idx] = src->B[idx];
2023-07-17 22:43:31 +11:00
if (src->R[idx] < src->B[idx])
2023-07-17 16:44:39 +11:00
dst->G[idx] = src->R[idx];
2023-07-16 21:39:49 +11:00
else
2023-07-17 16:44:39 +11:00
dst->G[idx] = src->B[idx];
2023-07-16 21:39:49 +11:00
}
return 0;
}
2022-05-15 05:49:59 +11:00
/* -------------------------------------------------------------- */
/* nouveau 14 mai 2022 rue Ernest Renan */
int graylevel2popcolors(FloatImg *src, FloatImg *dst, int k)
{
int x, y;
float rgb[3];
2022-05-18 19:26:29 +11:00
float theoric_maxval, real_maxv;
2022-05-15 05:49:59 +11:00
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, src, dst, k);
#endif
theoric_maxval = src->fval * src->count;
2022-05-18 19:26:29 +11:00
real_maxv = fimg_get_maxvalue(src);
#if DEBUG_LEVEL
fprintf(stderr, "maxval: theoric= %.3f real= %.3f\n", \
theoric_maxval, real_maxv);
#endif
2022-05-15 05:49:59 +11:00
fimg_clear(dst);
for (y=0; y<src->height; y++) {
for (x=0; x<src->width; x++)
{
fimg_get_rgb(src, x, y, rgb);
2022-05-18 19:26:29 +11:00
rgb[0] = real_maxv * fabs(cos(21.0 * rgb[0] / real_maxv));
rgb[1] = real_maxv * fabs(cos(31.0 * rgb[1] / real_maxv));
rgb[2] = real_maxv * fabs(cos(11.0 * rgb[2] / real_maxv));
2022-05-15 05:49:59 +11:00
fimg_put_rgb(dst, x, y, rgb);
}
}
return 0;
}
2021-01-11 08:52:33 +11:00
/* -------------------------------------------------------------- */
2021-01-12 21:05:17 +11:00
/*
* please, add some parameters !
*/
2021-03-29 20:59:24 +11:00
int incrustation_vignette(FloatImg *src, FloatImg *dst, int k)
2021-01-11 08:52:33 +11:00
{
int x, y, x4, y4;
float rgb[3];
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, src, dst, k);
#endif
x4 = dst->width / 4, y4 = dst->height / 4;
for (y=0; y<y4; y++) {
for (x=0; x<x4; x++) {
2021-01-12 08:22:03 +11:00
fimg_get_rgb(src, x*4, y*4, rgb);
2021-01-12 21:05:17 +11:00
fimg_put_rgb(dst, x+39, y+39, rgb);
2021-01-11 08:52:33 +11:00
}
}
return -1;
}
2020-12-29 10:54:15 +11:00
/* -------------------------------------------------------------- */
2021-01-04 01:21:38 +11:00
/* nouveau du premier dimanche de 2020 'nextgen' */
2021-10-16 08:21:02 +11:00
/* CE TRUC NE MARCHE PAS COMME PRÉVU */
2021-01-04 01:21:38 +11:00
static int pixel_trinitron(FloatImg *pimg, int pos[4], float *fvals)
{
2021-01-15 05:06:09 +11:00
int x, y, pline, off;
2021-11-27 09:10:29 +11:00
int ym;
2021-01-04 01:21:38 +11:00
2021-10-19 12:56:56 +11:00
fimg_clear_rectangle(pimg, pos);
2021-11-27 09:10:29 +11:00
ym = pos[1]+pos[3]-1;
#define FDIM 0.60
for (y=pos[1]; y<ym; y++) {
2021-01-15 05:06:09 +11:00
pline = y*pimg->width;
2021-11-27 09:10:29 +11:00
for (x=0; x<5; x++) {
off = pline + (x+pos[0]);
2021-10-10 21:20:52 +11:00
/* wtf i'm doing here ? */
2021-11-27 09:10:29 +11:00
if ( (pos[1]==y) || (ym-1==y) ) {
pimg->R[off] = fvals[0] * FDIM;
pimg->G[off+5] = fvals[1] * FDIM;
pimg->B[off+10] = fvals[2] * FDIM;
}
else {
pimg->R[off] = fvals[0];
pimg->G[off+5] = fvals[1];
pimg->B[off+10] = fvals[2];
}
2021-01-04 01:21:38 +11:00
}
}
return 0;
}
2021-10-10 21:20:52 +11:00
/*
2021-10-16 08:21:02 +11:00
* need more explanation, need more work
2021-10-10 21:20:52 +11:00
*/
2021-01-04 01:21:38 +11:00
int trinitron(FloatImg *pimg, int notused)
{
int x, y, coo[4], foo;
float vals[3];
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %d )\n", __func__, pimg, notused);
#endif
2023-04-30 04:29:45 +11:00
/* XXX CRITICAL BUG XXX
*
* what to do if STP is not a modulo of
* the width (or size) of the picture ?
* why if img height is 600 and stp was 16 ?
tth@redlady:~/Devel/FloatImg/Fonderie$ bc -l
600/16
37.50000000000000000000
*
* And this mistake is all around the code /o\
*
*/
#define STP 8 /* stepd for x & y axex */
2021-01-04 01:21:38 +11:00
coo[2] = coo[3] = STP;
2020-12-29 10:54:15 +11:00
2023-04-30 04:29:45 +11:00
for (y=0; y < pimg->height; y+=STP) {
2021-01-04 01:21:38 +11:00
coo[1] = y;
2023-04-30 04:29:45 +11:00
for (x=0; x < pimg->width; x+=STP) {
2021-01-04 01:21:38 +11:00
coo[0] = x;
foo = stat_zone(pimg, coo, vals);
if (foo) abort();
/* next step : plot the datas */
2023-04-30 04:29:45 +11:00
// XXX fprintf(stderr, "%s %6d %6d\n", __func__, x, y);
2021-01-04 01:21:38 +11:00
pixel_trinitron(pimg, coo, vals);
}
}
#undef STP
return 0;
}
/* -------------------------------------------------------------- */
/* nouveau du 27 decembre 2020, un soir de grand froid... */
2020-12-29 22:56:26 +11:00
int octotree_classif(FloatImg *pimg, float kdist, int notused)
2020-12-29 10:54:15 +11:00
{
int foo;
2021-01-04 01:21:38 +11:00
float mm[6], delta[3];
2020-12-29 22:56:26 +11:00
float r, g, b, kr, kg, kb, dp, trig;
int idx, sz, n8, count;
typedef struct {
float x, y, z;
} ptc_t;
ptc_t ptc[8];
2020-12-29 10:54:15 +11:00
2020-12-29 23:08:19 +11:00
#if DEBUG_LEVEL
2020-12-29 22:56:26 +11:00
fprintf(stderr, ">>> %s ( %p %f %d )\n", __func__,
pimg, kdist, notused);
2020-12-29 23:08:19 +11:00
#endif
2020-12-29 22:56:26 +11:00
2020-12-29 10:54:15 +11:00
foo = fimg_get_minmax_rgb(pimg, mm);
if (foo) {
fprintf(stderr, "oups %d in get minmax\n", foo);
return foo;
}
2020-12-31 00:42:44 +11:00
if (verbosity>1) fimg_print_minmax(mm, " input pic ");
2020-12-29 10:54:15 +11:00
/*
2020-12-29 22:56:26 +11:00
* compute the 8 center points
*/
delta[0] = mm[1] - mm[0]; /* R */
delta[1] = mm[3] - mm[2]; /* G */
delta[2] = mm[5] - mm[4]; /* B */
2020-12-29 23:08:19 +11:00
// fprintf(stderr, "delta: %11.3f %11.3f %11.3f\n",
// delta[0], delta[1], delta[2]);
2020-12-29 22:56:26 +11:00
for (idx=0; idx<8; idx++) {
kr = 0.25 * ((idx & 0x4) ? 1 : 3);
kg = 0.25 * ((idx & 0x2) ? 1 : 3);
kb = 0.25 * ((idx & 0x1) ? 1 : 3);
// fprintf(stderr, "%6d %.2f %.2f %.2f\n", idx, kr, kg, kb);
ptc[idx].x = (delta[0] * kr) + mm[0];
ptc[idx].y = (delta[1] * kg) + mm[2];
ptc[idx].z = (delta[2] * kb) + mm[4];
2020-12-29 23:08:19 +11:00
// fprintf(stderr, "%6d %.3f %.3f %.3f\n", idx,
// ptc[idx].x, ptc[idx].y, ptc[idx].z);
2020-12-29 22:56:26 +11:00
}
sz = pimg->width * pimg->height;
trig = kdist * ((mm[1] + mm[3] + mm[5])/6.0);
2020-12-29 23:08:19 +11:00
// fprintf(stderr, "trig value %f\n", trig);
2020-12-29 10:54:15 +11:00
2020-12-29 22:56:26 +11:00
count = 0;
#define X(a,b) ( ((a)-(b)) * ((a)-(b)) )
for (idx=0; idx<sz; idx++) {
r = pimg->R[idx]; g = pimg->G[idx]; b = pimg->B[idx];
for (n8=0; n8<8; n8++) {
2020-12-31 00:42:44 +11:00
dp = sqrt(X(r,ptc[n8].x)+X(g,ptc[n8].y)+X(b,ptc[n8].z));
2020-12-29 22:56:26 +11:00
if (dp < trig) {
pimg->R[idx] = ptc[n8].x;
pimg->G[idx] = ptc[n8].y;
pimg->B[idx] = ptc[n8].z;
count++;
break;
}
else {
pimg->R[idx]=pimg->G[idx]=pimg->B[idx]=0.0;
}
}
}
2020-12-29 10:54:15 +11:00
2020-12-31 00:42:44 +11:00
if (verbosity > 1) {
fprintf(stderr, "%s: %d/%d pixels, ratio %f\n", __func__, count, sz,
2020-12-29 23:08:19 +11:00
(float)count/(float)sz);
2020-12-31 00:42:44 +11:00
}
2020-12-29 10:54:15 +11:00
2020-12-29 22:56:26 +11:00
return 0;
2020-12-29 10:54:15 +11:00
}
2020-12-18 20:18:09 +11:00
/* -------------------------------------------------------------- */
/* nouveau du 19 decembre 2020, pour le grand ecran de da Scritch */
int upside_down(FloatImg *pimg)
{
float *rowpix;
float *Ps, *Pd;
int Os, Od; /* offset of lines */
int wsz;
int ya, y2;
2020-12-19 18:48:17 +11:00
if (verbosity>1) fprintf(stderr, "%s: image width is %d\n",
2020-12-18 22:16:24 +11:00
__func__, pimg->width);
2020-12-18 20:18:09 +11:00
rowpix = calloc(pimg->width, sizeof(float));
if (NULL==rowpix) {
fprintf(stderr, "%s : memory full\n", __func__);
exit(1);
}
wsz = pimg->width * sizeof(float);
2020-12-19 18:48:17 +11:00
if (verbosity>1) fprintf(stderr, "%s: wsx = %d\n", __func__, wsz);
2020-12-18 20:18:09 +11:00
for (ya=0; ya<pimg->height/2; ya++) {
y2 = pimg->height - (ya+1);
Os = (pimg->width * ya);
Od = (pimg->width * y2);
/* let's go, crash coredumping... */
Ps = pimg->R + Os;
Pd = pimg->R + Od;
memcpy(rowpix, Ps, wsz);
memcpy(Ps, Pd, wsz);
memcpy(Pd, rowpix, wsz);
Ps = pimg->G + Os;
Pd = pimg->G + Od;
memcpy(rowpix, Ps, wsz);
memcpy(Ps, Pd, wsz);
memcpy(Pd, rowpix, wsz);
Ps = pimg->B + Os;
Pd = pimg->B + Od;
memcpy(rowpix, Ps, wsz);
memcpy(Ps, Pd, wsz);
memcpy(Pd, rowpix, wsz);
}
free(rowpix);
return 0;
}
2020-12-11 05:19:35 +11:00
/* -------------------------------------------------------------- */
/* nouveau du 9 decembre 2020, en ecoutant le Fermion raconter du
superbe portnawak */
int bouger_les_pixels(FloatImg *pimg, int intensite)
{
int x, y, nx, ny;
float rgb[3];
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %d )\n", __func__, pimg, intensite);
#endif
if (intensite < 1) {
fprintf(stderr, "%s: %d bad intensity\n", __func__, intensite);
return -1;
}
for (x=0; x<pimg->width; x++) {
for (y=0; y<pimg->height; y++) {
nx = x+(rand()%intensite)-(intensite/2);
ny = y+(rand()%intensite)-(intensite/2);
if ( nx<0 || ny<0 || nx>=pimg->width
|| ny>=pimg->height )
continue;
2021-01-14 02:09:27 +11:00
/* XXX optimize here ? */
2020-12-11 05:19:35 +11:00
fimg_get_rgb(pimg, nx, ny, rgb);
fimg_put_rgb(pimg, x, y, rgb);
}
}
return 0;
}
/* -------------------------------------------------------------- */
/* nouveau du 9 decembre 2020, en ecoutant les Cernettes */
int mirror_split(FloatImg *pimg, int kaboo)
{
int line, x, xs, xd;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %d )\n", __func__, pimg, kaboo);
#endif
for (line=0; line<pimg->height; line++) {
for (x=0; x<pimg->width/2; x++) {
xs = (pimg->width * line) + x;
xd = (pimg->width * line) + (pimg->width -x);
pimg->R[xd] = pimg->R[xs];
pimg->G[xd] = pimg->G[xs];
pimg->B[xd] = pimg->B[xs];
}
}
return 0;
}
2020-11-21 08:25:30 +11:00
/* -------------------------------------------------------------- */
/* nouveau du 20 novembre 2020, pour encoder une vidz du vernissage
2021-04-03 04:12:22 +11:00
* du festival Sauvageonnes de Mixart-Myrys */
2020-11-21 08:25:30 +11:00
int des_bords_sombres_a(FloatImg *pimg, int offset)
{
float coef;
2020-11-25 20:32:02 +11:00
int xpos, xp2, lidx, y;
2020-11-21 08:25:30 +11:00
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %d )\n", __func__, pimg, offset);
#endif
2020-11-25 20:32:02 +11:00
if (offset<0 || offset>=pimg->width) {
2021-05-11 19:36:55 +11:00
fprintf(stderr, "%s: offset %d is bad\n", __func__, offset);
2020-11-21 08:25:30 +11:00
return -66;
}
for (y=0; y<pimg->height; y++) {
2020-11-25 20:32:02 +11:00
lidx = y * pimg->width; /* start of the
'y' line */
2020-11-21 08:25:30 +11:00
for (xpos=0; xpos<offset; xpos++) {
coef = (float)xpos / (float)offset;
pimg->R[xpos+lidx] *= coef;
pimg->G[xpos+lidx] *= coef;
pimg->B[xpos+lidx] *= coef;
2020-11-25 20:32:02 +11:00
xp2 = pimg->width-xpos;
pimg->R[xp2+lidx] *= coef;
pimg->G[xp2+lidx] *= coef;
pimg->B[xp2+lidx] *= coef;
2020-11-21 08:25:30 +11:00
}
}
2020-12-01 23:26:00 +11:00
return 0;
2020-11-10 10:50:25 +11:00
}
2020-11-02 11:25:00 +11:00
/* -------------------------------------------------------------- */
2021-05-11 19:36:55 +11:00
/* nouveau Mon 10 May 2021 08:46:02 PM CEST
* chez Eric 1KA */
2021-10-18 03:32:53 +11:00
int des_bords_sombres_b(FloatImg *pimg, int nbre)
2021-05-11 19:36:55 +11:00
{
2021-10-18 03:32:53 +11:00
int idx, x, foo;
float coef, *fptr;
2024-03-22 02:10:06 +11:00
2021-05-11 19:36:55 +11:00
#if DEBUG_LEVEL
2024-03-22 02:10:06 +11:00
fprintf(stderr, ">>> %s ( %p %d )\n", __func__, pimg, nbre);
2021-05-11 19:36:55 +11:00
#endif
2021-10-18 03:32:53 +11:00
for (idx=0; idx<nbre; idx++) {
coef = (float)idx / (float)nbre;
fptr = pimg->R + (idx*pimg->width);
for (x=0; x<pimg->width; x++) *fptr++ *= coef;
fptr = pimg->G + (idx*pimg->width);
for (x=0; x<pimg->width; x++) *fptr++ *= coef;
fptr = pimg->B + (idx*pimg->width);
for (x=0; x<pimg->width; x++) *fptr++ *= coef;
foo = (pimg->height-idx) - 1;
fptr = pimg->R + (foo*pimg->width);
// fprintf(stderr, "%5d %9.3f %p\n", foo, coef, fptr);
for (x=0; x<pimg->width; x++) *fptr++ *= coef;
fptr = pimg->G + (foo*pimg->width);
for (x=0; x<pimg->width; x++) *fptr++ *= coef;
fptr = pimg->B + (foo*pimg->width);
for (x=0; x<pimg->width; x++) *fptr++ *= coef;
2021-05-11 19:36:55 +11:00
}
2021-10-18 03:32:53 +11:00
// fprintf(stderr, "WARNING: %s badly implemented\n", __func__);
2021-10-10 18:25:59 +11:00
2021-10-18 03:32:53 +11:00
return 0;
2021-05-11 19:36:55 +11:00
}
/* -------------------------------------------------------------- */
2021-03-21 15:08:35 +11:00
/*
* int binarize(FloatImg *pimg, int notused) was now in
* funcs/sfx2.c
2021-03-26 15:40:45 +11:00
* same move for trinarize.
2021-03-21 15:08:35 +11:00
*/
2020-11-03 00:51:48 +11:00
/* -------------------------------------------------------------- */
int brotche_rand48_a(FloatImg *fimg, float ratio, float mval)
2020-11-02 11:25:00 +11:00
{
int nbpix, todo, foo;
int x, y;
float fval;
nbpix = fimg->width * fimg->height;
todo = (int)((float)nbpix * ratio);
2020-11-03 00:51:48 +11:00
if (verbosity > 1) {
fprintf(stderr, "%s: ratio %f nbpix %d todo %d\n", __func__,
ratio, nbpix, todo);
}
2020-11-02 11:25:00 +11:00
for (foo=0; foo<todo; foo++)
{
fval = (float)drand48() * mval;
x = rand() % fimg->width;
y = rand() % fimg->height;
fimg_plot_rgb(fimg, x, y, fval, fval, fval);
}
return 0;
}
/* -------------------------------------------------------------- */
int brotche_rand48_b(FloatImg *fimg, float ratio, float mval)
{
int nbpix, todo, foo;
int x, y;
float fval;
nbpix = fimg->width * fimg->height;
todo = (int)((float)nbpix * ratio);
if (verbosity > 1) {
2020-11-03 00:51:48 +11:00
fprintf(stderr, "%s: ratio %f nbpix %d todo %d\n", __func__,
2020-11-02 11:25:00 +11:00
ratio, nbpix, todo);
}
for (foo=0; foo<todo; foo++)
{
fval = (float)drand48() * mval;
x = 1 + (rand() % (fimg->width-2));
y = rand() % fimg->height;
fimg_plot_rgb(fimg, x-1, y, fval, 0.0, 0.0);
fimg_plot_rgb(fimg, x , y, 0.0, 0.0, fval);
fimg_plot_rgb(fimg, x+1, y, 0.0, fval, 0.0);
}
return 0;
}
/* -------------------------------------------------------------- */