From 494577bbfcd8dbfd2b51f58cada98f7e958dfc2d Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Jun 11 2025 15:59:22 +0000 Subject: mosaic --- diff --git a/onefile/data-src/textures/PTP-Elements_08-512x512.png b/onefile/data-src/textures/PTP-Elements_08-512x512.png new file mode 100644 index 0000000..94ed035 Binary files /dev/null and b/onefile/data-src/textures/PTP-Elements_08-512x512.png differ diff --git a/onefile/data-src/textures/PTP-Elements_09-512x512.png b/onefile/data-src/textures/PTP-Elements_09-512x512.png new file mode 100644 index 0000000..2c49a19 Binary files /dev/null and b/onefile/data-src/textures/PTP-Elements_09-512x512.png differ diff --git a/onefile/data-src/textures/PTP-Elements_10-512x512.png b/onefile/data-src/textures/PTP-Elements_10-512x512.png new file mode 100644 index 0000000..cbc0d84 Binary files /dev/null and b/onefile/data-src/textures/PTP-Elements_10-512x512.png differ diff --git a/onefile/data-src/textures/PTP-Foliage_01-512x512.png b/onefile/data-src/textures/PTP-Foliage_01-512x512.png new file mode 100644 index 0000000..c436928 Binary files /dev/null and b/onefile/data-src/textures/PTP-Foliage_01-512x512.png differ diff --git a/onefile/data-src/textures/PTP-Foliage_05-512x512.png b/onefile/data-src/textures/PTP-Foliage_05-512x512.png new file mode 100644 index 0000000..28b37d6 Binary files /dev/null and b/onefile/data-src/textures/PTP-Foliage_05-512x512.png differ diff --git a/onefile/data-src/textures/PTP-Foliage_09-512x512.png b/onefile/data-src/textures/PTP-Foliage_09-512x512.png new file mode 100644 index 0000000..5e6676e Binary files /dev/null and b/onefile/data-src/textures/PTP-Foliage_09-512x512.png differ diff --git a/onefile/data-src/textures/PTP-Ground_07-512x512.png b/onefile/data-src/textures/PTP-Ground_07-512x512.png new file mode 100644 index 0000000..a52e7eb Binary files /dev/null and b/onefile/data-src/textures/PTP-Ground_07-512x512.png differ diff --git a/onefile/data-src/textures/PTP-Ground_11-512x512.png b/onefile/data-src/textures/PTP-Ground_11-512x512.png new file mode 100644 index 0000000..02fbfec Binary files /dev/null and b/onefile/data-src/textures/PTP-Ground_11-512x512.png differ diff --git a/onefile/data/output/mosaic/.placeholder b/onefile/data/output/mosaic/.placeholder new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/onefile/data/output/mosaic/.placeholder diff --git a/onefile/data/textures/PTP-Elements_08.png b/onefile/data/textures/PTP-Elements_08.png new file mode 100644 index 0000000..6b13399 Binary files /dev/null and b/onefile/data/textures/PTP-Elements_08.png differ diff --git a/onefile/data/textures/PTP-Elements_09.png b/onefile/data/textures/PTP-Elements_09.png new file mode 100644 index 0000000..c98b62e Binary files /dev/null and b/onefile/data/textures/PTP-Elements_09.png differ diff --git a/onefile/data/textures/PTP-Elements_10.png b/onefile/data/textures/PTP-Elements_10.png new file mode 100644 index 0000000..3b20efc Binary files /dev/null and b/onefile/data/textures/PTP-Elements_10.png differ diff --git a/onefile/data/textures/PTP-Foliage_01.png b/onefile/data/textures/PTP-Foliage_01.png new file mode 100644 index 0000000..1c3c2ed Binary files /dev/null and b/onefile/data/textures/PTP-Foliage_01.png differ diff --git a/onefile/data/textures/PTP-Foliage_05.png b/onefile/data/textures/PTP-Foliage_05.png new file mode 100644 index 0000000..dcefd6b Binary files /dev/null and b/onefile/data/textures/PTP-Foliage_05.png differ diff --git a/onefile/data/textures/PTP-Foliage_09.png b/onefile/data/textures/PTP-Foliage_09.png new file mode 100644 index 0000000..c21d1a2 Binary files /dev/null and b/onefile/data/textures/PTP-Foliage_09.png differ diff --git a/onefile/data/textures/PTP-Ground_07.png b/onefile/data/textures/PTP-Ground_07.png new file mode 100644 index 0000000..479c324 Binary files /dev/null and b/onefile/data/textures/PTP-Ground_07.png differ diff --git a/onefile/data/textures/PTP-Ground_11.png b/onefile/data/textures/PTP-Ground_11.png new file mode 100644 index 0000000..db8d167 Binary files /dev/null and b/onefile/data/textures/PTP-Ground_11.png differ diff --git a/onefile/mosaic.c b/onefile/mosaic.c new file mode 100644 index 0000000..18cb8ba --- /dev/null +++ b/onefile/mosaic.c @@ -0,0 +1,321 @@ + +#include +#include +#include +#include +#include + + +#define COUNT 64 +#define TEXCOUNT 512 +#define FRAMECOUNT 512 +#define W 512 +#define H 512 +#define STEP 0.05 +#define EDGE 0 +//#define SAVE "data/output/mosaic/frame%03d.png" + + +typedef struct { + int w, h; + unsigned char *pixels; +} Tex; + +typedef struct { + Tex *tex0; + Tex *tex1; + double alpha; +} Frame; + +typedef struct { + int x, y; + int l, t, w, h; + unsigned int color; + Frame frames[FRAMECOUNT]; +} Point; + +typedef struct { + double k[3]; + + Point *point; + double weight; + double alpha; + double edge; + + Point *point2; + double weight2; +} Pixel; + + + +Point points[COUNT]; +Pixel pixels[H][W]; + +Tex textures[TEXCOUNT]; +int texturesCnt; + +unsigned char image[H][W][4]; +Animation anim; + + +int wrapX(int x) + { return (x%W + W)%W; } +int wrapY(int y) + { return (y%H + H)%H; } +Pixel* getPixel(int x, int y) + { return &pixels[wrapY(y)][wrapX(x)]; } + + +int updatePixel(Pixel *p, int x, int y, int mode) { + Pixel *pp = getPixel(x, y); + double w = p->weight + p->k[mode] + pp->k[mode]; + if (!pp->point || pp->weight > w) { + pp->point2 = pp->point = p->point; + pp->weight2 = pp->weight = w; + return 1; + } + return 0; +} + + +void updatePixel2(Pixel *p, int x, int y, int mode) { + Pixel *pp = getPixel(x, y); + if (p->point == pp->point) return; + + double w = pp->weight + pp->k[mode] + p->k[mode]; + if (p->point2 == p->point || p->weight2 > w) { + p->point2 = pp->point; + p->weight2 = w; + } +} + + +void generateFrames(Frame *frames) { + int start; + int switches = 1 + rand()%10; + for(int i = 0; i < switches; ++i) { + start = rand()%FRAMECOUNT; + frames[start].tex1 = &textures[rand()%texturesCnt]; + } + + double alpha = 1; + Tex *t0 = frames[start].tex1, *t1 = t0; + for(int i = start; i < FRAMECOUNT*10; ++i) { + Frame *f = &frames[i%FRAMECOUNT]; + if (alpha < 1) { + alpha += STEP; + if (alpha >= 1) { + alpha = 1; + t0 = t1; + } + } else + if (f->tex1 && f->tex1 != t1) { + t1 = f->tex1; + alpha = 0; + } + f->tex0 = t0; + f->tex1 = t1; + f->alpha = alpha; + } + + //if (frames == points->frames) + // for(int i = 0; i < FRAMECOUNT; ++i) + // printf("%3d %3d %3d %f\n", i, frames[i].tex0 - textures, frames[i].tex1 - textures, frames[i].alpha); +} + + +Animation generateAnim(int frameId, const char *filename) { + // update image + Pixel *p = pixels[0]; + unsigned char black[] = { 0, 0, 0, 255 }; + //unsigned char white[] = { 255, 255, 255, 255 }; + unsigned char *c = image[0][0]; + for(int y = 0; y < H; ++y) + for(int x = 0; x < W; ++x, ++p) { + Frame *f0 = &p->point->frames[frameId]; + Frame *f1 = &p->point2->frames[frameId]; + + Tex *t0 = f0->tex0; + Tex *t1 = f0->tex1; + Tex *t2 = f1->tex0; + Tex *t3 = f1->tex1; + + double a00 = 1 - f0->alpha; + double a01 = f0->alpha; + double a10 = 1 - f1->alpha; + double a11 = f1->alpha; + + if (t0 == t1) { a00 = 0; a01 = 1; } + if (t2 == t3) { a10 = 0; a11 = 1; } + + double a0 = p->alpha*a00; + double a1 = p->alpha*a01; + double a2 = (1 - p->alpha)*a10; + double a3 = (1 - p->alpha)*a11; + + double k = 0; + if (t0 == t2) k += a00 < a10 ? a00 : a10; + if (t0 == t3) k += a00 < a11 ? a00 : a11; + if (t1 == t2) k += a01 < a10 ? a01 : a10; + if (t1 == t3) k += a01 < a11 ? a01 : a11; + double a4 = p->edge*(1 - k)*EDGE; + + unsigned char *c0 = t0->pixels + (y%t0->h*t0->w + x%t0->w)*4; + unsigned char *c1 = t1->pixels + (y%t1->h*t1->w + x%t1->w)*4; + unsigned char *c2 = t2->pixels + (y%t2->h*t2->w + x%t2->w)*4; + unsigned char *c3 = t3->pixels + (y%t3->h*t3->w + x%t3->w)*4; + unsigned char *c4 = black; + for(int i = 0; i < 4; ++i) + *c++ = (*c0++*a0 + *c1++*a1 + *c2++*a2 + *c3++*a3)*(1 - a4) + *c4++*a4; + } + + if (filename) imageSave(filename, W, H, image); + return createAnimationFromImageEx(W, H, image, TRUE, TRUE, FALSE, FALSE); +} + + +void generate() { + // clear + memset(points, 0, sizeof(points)); + memset(pixels, 0, sizeof(pixels)); + memset(image, 0, sizeof(image)); + + // generate k + Pixel *p = pixels[0]; + for(int y = 0; y < H; ++y) + for(int x = 0; x < W; ++x, ++p) { + p->k[0] = exp(randomFloat()-0.5)*4; + p->k[1] = exp(randomFloat()-0.5); + p->k[2] = (p->k[0] + p->k[1])*0.75; + } + + // generate points + for(int i = 0; i < COUNT; ++i) { + Point *pt = &points[i]; + pt->x = rand()%W; + pt->y = rand()%H; + pt->color = colorByHSV(randomFloat()*360, 1, 1); + generateFrames(pt->frames); + + Pixel *p = getPixel(pt->x, pt->y); + p->point = p->point2 = pt; + p->weight = p->weight2 = randomFloat(); + } + + // expand points + int found = 1, i = 0; + while(found) { + found = 0; + Pixel *p = pixels[0]; + for(int y = 0; y < H; ++y) + for(int x = 0; x < W; ++x, ++p) { + if (!p->point) continue; + if (updatePixel(p, x-1, y, 0)) found = 1; + if (updatePixel(p, x+1, y, 0)) found = 1; + if (updatePixel(p, x, y-1, 1)) found = 1; + if (updatePixel(p, x, y+1, 1)) found = 1; + if (updatePixel(p, x-1, y-1, 2)) found = 1; + if (updatePixel(p, x+1, y-1, 2)) found = 1; + if (updatePixel(p, x-1, y+1, 2)) found = 1; + if (updatePixel(p, x+1, y+1, 2)) found = 1; + } + printf("%d\n", i++); fflush(stdout); + } + + // expand points2 + p = pixels[0]; + for(int y = 0; y < H; ++y) + for(int x = 0; x < W; ++x, ++p) { + updatePixel2(p, x-1, y, 0); + updatePixel2(p, x+1, y, 0); + updatePixel2(p, x, y-1, 1); + updatePixel2(p, x, y+1, 1); + updatePixel2(p, x-1, y-1, 2); + updatePixel2(p, x+1, y-1, 2); + updatePixel2(p, x-1, y+1, 2); + updatePixel2(p, x+1, y+1, 2); + + double a = (p->weight2 - p->weight)*0.5 + 0.5; + if (a < 0) a = 0; + if (a > 1) a = 1; + + double edge = 1 - (p->weight2 - p->weight)/p->k[2]/8; + if (edge > 1) edge = 1; + if (edge < 0) edge = 0; + if (p->point == p->point2) edge = 0; + + p->alpha = a; + p->edge = edge; + } + + // generate animation + animationClear(anim); + for(int i = 0; i < FRAMECOUNT; ++i) { + #ifdef SAVE + char filename[1024] = {}; + sprintf(filename, SAVE, i); + printf("generate: %s\n", filename); fflush(stdout); + animationInsert(anim, i, generateAnim(i, filename)); + #else + printf("generate frame %d\n", i); fflush(stdout); + animationInsert(anim, i, generateAnim(i, NULL)); + #endif + } + animationSetFps(anim, 32); + animationSetLoop(anim, TRUE); +} + + +void loadTexture(const char *filename) { + printf("load texture: %s\n", filename); + Tex *t = &textures[texturesCnt]; + if (imageLoad(filename, &t->w, &t->h, &t->pixels)) + ++texturesCnt; +} + + +void loadTextures(const char *dirname) { + Directory dir = openDirectoryEx(dirname, "", ".png", FALSE, TRUE, FALSE); + if (dir) { + for(int i = 0; i < directoryGetCount(dir); ++i) + loadTexture(directoryGetFull(dir, i)); + closeDirectory(dir); + } +} + + +void init() { + anim = createAnimationEmpty(); + loadTextures("data/textures"); + generate(); +} + + +void draw() { + double w = windowGetWidth(); + double h = windowGetHeight(); + double t = windowGetSeconds(); + + saveState(); + //scale(w/W, h/H); + + noStroke(); + animationSetFrame(anim, ((int)(t*32))%FRAMECOUNT); + fillTexture(anim, 0, 0, W, H, TRUE); + rect(0, 0, w, h); + + //stroke(COLOR_BLACK); + //for(int i = 0; i < COUNT; ++i) + // point(points[i].x, points[i].y); + + restoreState(); +} + + +int main() { + windowSetVariableFrameRate(); + windowSetResizable(TRUE); + windowSetInit(&init); + windowSetDraw(&draw); + windowRun(); +}