Code: Select all
/* Created by Alexander "Shaos" Shabarshin in January 2023
and immediately turned into PULIC DOMAIN
http://xorlib.com
Build: gcc composite.c -o composite -lpng -lm
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <png.h> /* libpng */
/*
#define COLORBARS
*/
#include "cgatrick_xbm025.xbm"
#define IMGARRAY cgatrick_xbm025_bits
#define OFFSET 96
#define DX 736
#define DY 200
#define FILTERS 3
/*
./mkfilter -Bu -Lp -o 3 -a 0.0469 0.0000000000e+00 -l
*/
#define NZEROS 3
#define NPOLES 3
#define GAIN 4.1115485147e+02
double xv[FILTERS][NZEROS+1], yv[FILTERS][NPOLES+1];
static double filterstep(double v, int i)
{
xv[i][0] = xv[i][1]; xv[i][1] = xv[i][2]; xv[i][2] = xv[i][3];
xv[i][3] = v / GAIN;
yv[i][0] = yv[i][1]; yv[i][1] = yv[i][2]; yv[i][2] = yv[i][3];
yv[i][3] = (xv[i][0] + xv[i][3]) + 3 * (xv[i][1] + xv[i][2])
+ ( 5.5347203431e-01 * yv[i][0]) + ( -1.9855726416e+00 * yv[i][1])
+ ( 2.4126432180e+00 * yv[i][2]);
return yv[i][3];
}
void filtersclean(void)
{
int i,j;
for(i=0;i<FILTERS;i++)
{
for(j=0;j<=NZEROS;j++)
{
xv[i][j] = 0.0;
yv[i][j] = 0.0;
}
}
}
int savepng(char* filename, int width, int height, unsigned char* data)
{
/* Assume that it's RGB888 image */
int bitdepth = 8;
int colortype = PNG_COLOR_TYPE_RGB;
int transform = PNG_TRANSFORM_IDENTITY;
int i = 0;
int r = 0;
FILE* fp = NULL;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
static png_bytep row_pointers[1024];
if(NULL == data) { r = -1; goto endlabel; }
if(!filename || !filename[0]) { r = -2; goto endlabel; }
if(NULL == (fp = fopen(filename, "wb"))) { r = -4; goto endlabel; }
if(NULL == (png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) { r = -5; goto endlabel; }
if(NULL == (info_ptr = png_create_info_struct(png_ptr))) { r = -6; goto endlabel; }
png_set_IHDR(png_ptr, info_ptr, width, height, bitdepth,
colortype, /* PNG_COLOR_TYPE_{GRAY, PALETTE, RGB, RGB_ALPHA, GRAY_ALPHA, RGBA, GA} */
PNG_INTERLACE_NONE, /* PNG_INTERLACE_{NONE, ADAM7 } */
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
for(i = 0; i < height; ++i) row_pointers[i] = data + i*width*3;
png_init_io(png_ptr, fp);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, transform, NULL);
endlabel:
if(NULL != fp)
{
fclose(fp);
fp = NULL;
}
if(NULL != png_ptr)
{
if(NULL == info_ptr) r = -7;
png_destroy_write_struct(&png_ptr, &info_ptr);
}
return r;
}
double shiftedcos[8],shiftedsin[8];
unsigned char* img;
#define PHASEOFFSET 200
int main(int argc, char** argv)
{
int x,y,i,j,m,r,g,b,phase=0;
double d,dy,du,dv;
unsigned char c,by;
img = (unsigned char*)malloc(1288*1008*3);
if(img==NULL) return -1;
if(argc>1) phase=atoi(argv[1]);
for(i=0;i<8;i++)
{
d = M_PI*(phase+PHASEOFFSET)/180.0;
shiftedcos[i] = cos(M_PI/4.0*i+d);
shiftedsin[i] = sin(M_PI/4.0*i+d);
}
#define CLAMP(x) if(x<0) x=0; if(x>255) x=255
#define GETRGB(r,g,b,y,u,v) r=y+1.13983*v;g=y-0.39465*u-0.58060*v;b=y+2.03211*u
for(y=0;y<1008;y++)
{
if(y<4 || y>=1004)
{
memset(&img[y*1288*3],0,1288*3);
continue;
}
filtersclean();
i = (y-4)/5*DX/8+OFFSET/8;
for(x=0;x<1280;x+=16)
{
by = IMGARRAY[i++];
m = 1;
for(j=0;j<8;j++)
{
#ifndef COLORBARS
if(by&m)
d = 0.0;
else d = 1.0;
#else
switch(j)
{
case 0: case 4: d=((x/80)&8)?1.0:0.0; break;
case 1: case 5: d=((x/80)&4)?1.0:0.0; break;
case 2: case 6: d=((x/80)&2)?1.0:0.0; break;
case 3: case 7: d=((x/80)&1)?1.0:0.0; break;
}
#endif
dy = 255*filterstep(d,0);
dv = 255*filterstep(d*shiftedcos[(x+j+j)&7],1);
du = 255*filterstep(d*shiftedsin[(x+j+j)&7],2);
GETRGB(r,g,b,dy,du,dv);
CLAMP(r);CLAMP(g);CLAMP(b);
img[(y*1288+x+j*2)*3] = r;
img[(y*1288+x+j*2)*3+1] = g;
img[(y*1288+x+j*2)*3+2] = b;
dy = 255*filterstep(d,0);
dv = 255*filterstep(d*shiftedcos[(x+j+j+1)&7],1);
du = 255*filterstep(d*shiftedsin[(x+j+j+1)&7],2);
GETRGB(r,g,b,dy,du,dv);
CLAMP(r);CLAMP(g);CLAMP(b);
img[(y*1288+x+j*2+1)*3] = r;
img[(y*1288+x+j*2+1)*3+1] = g;
img[(y*1288+x+j*2+1)*3+2] = b;
m <<= 1;
}
}
for(j=0;j<8;j++)
{
dy = 255*filterstep(0,0);
dv = 255*filterstep(0,1);
du = 255*filterstep(0,2);
GETRGB(r,g,b,dy,du,dv);
CLAMP(r);CLAMP(g);CLAMP(b);
img[(y*1288+1280+j)*3] = r;
img[(y*1288+1280+j)*3+1] = g;
img[(y*1288+1280+j)*3+2] = b;
}
}
savepng("composite.png",1288,1008,img);
free(img);
return 0;
}