Last active
March 23, 2023 23:50
-
-
Save Oldes/4b75133736ee548e96570e269621a445 to your computer and use it in GitHub Desktop.
Reproducing images with geometric primitives. Using curves.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REBOL [ | |
Title: "Reproducing images with geometric primitives." | |
type: module | |
name: primitive | |
date: 24-Mar-2023 | |
author: "Oldes" | |
version: 0.2.0 | |
license: MIT | |
purpose: {This is a try to have something like this https://github.com/fogleman/primitive} | |
exports: [primitivize] | |
needs: [3.10.5 blend2d] | |
usage: [primitivize/with %source.jpg [max-steps 2000 seed 12 save %result.jpg]] | |
] | |
primitivize: function [ | |
source [image! file!] | |
/with options [block!] | |
][ | |
unless image? source [ source: load :source ] | |
if source/size/x > 256 [ source: resize source 256 ] | |
size: source/size | |
output: make image! size | |
temp1: make image! size | |
temp2: make image! size | |
;; initial image difference | |
dif: image-diff source output | |
max-radius: 100 | |
max-steps: 1000 | |
max-similarity: 1% | |
mod-radius: 0.9 | |
line-width: 30 | |
out-file: none | |
alpha: 0.7 | |
step: 0 | |
scale: 600% | |
if options [ | |
parse options [any [ | |
'max-radius set v: number! (max-radius: v) | |
| 'mod-radius set v: number! (mod-radius: min v 1.0) | |
| 'max-steps set v: number! (max-steps: v) | |
| 'max-similarity set v: number! (max-similarity: v) | |
| 'alpha set v: number! (alpha: min v 1.0) | |
| 'scale set v: number! (scale: v) | |
| 'seed set v: skip (random/seed :v) | |
| 'save set v: file! (out-file: v) | |
| skip | |
]] | |
] | |
commands: [ | |
pen (clr) | |
line-cap 2 2 ;= rounded ends | |
line-width (line-width * (1.1 - (step / max-steps))) | |
shape [ | |
move (pos) | |
curv (pos - (as-pair random max-radius random max-radius) + (as-pair random max-radius random max-radius)) | |
(pos - (as-pair random max-radius random max-radius) + (as-pair random max-radius random max-radius)) | |
] | |
] | |
all-commands: make block! max-steps * 9 | |
until [ | |
pos: random size | |
clr: pick source pos | |
;; drawing with reduced opacity | |
clr/4: alpha * clr/4 | |
;; draw 2 versions and use the one with better result | |
change temp1 output | |
change temp2 output | |
draw temp1 c1: compose/deep commands | |
draw temp2 c2: compose/deep commands | |
;? c1 | |
d1: image-diff source temp1 | |
d2: image-diff source temp2 | |
;print ["diffs:" d1 tab d2] | |
either any [ | |
d1 < dif | |
d2 < dif | |
][ | |
++ step | |
;; Use the better version as a new output and store its draw commands, | |
;; so the image may be later be redrawn in a higher resolution. | |
dif: either d1 < d2 [ | |
change output temp1 | |
append append all-commands 'scale scale | |
append append all-commands c1 'reset-matrix | |
;probe c1 | |
d1 | |
][ | |
change output temp2 | |
append append all-commands 'scale scale | |
append append all-commands c2 'reset-matrix | |
;probe c2 | |
d2 | |
] | |
print ["Step:" step " with diff:" dif] | |
;; lower the maximum size of objects with increased steps.. | |
;; (initially drawing larger objects and then smaller and smaller) | |
max-radius: 100 * (1.1 - (step / max-steps)) | |
][ | |
;; None of the new versions have better result! | |
;; Try smaller object where is better chance to have improved similarity. | |
max-radius: max-radius * mod-radius | |
if max-radius < 1 [ | |
;; If still not able to improve the output, then reduce line width, | |
;; so there is better chance to improve the image | |
line-width: line-width * 0.5 | |
;; reset the max-radius as well | |
max-radius: 100 * (1.1 - (step / max-steps)) | |
] | |
] | |
;; stop continuation if... | |
any [ | |
step = max-steps ;; maximum number of primitives reached | |
dif < max-similarity ;; or the output image is already good enough | |
] | |
] | |
;; Use collected draw commands scaled... | |
save %result-scaled.jpg draw scale * size all-commands | |
;; Save the original output result... | |
if out-file [ | |
try/except [ | |
save out-file output | |
][ print ["Failed to save file:" out-file] ] | |
] | |
output | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment