Giter Club home page Giter Club logo

primitive's Introduction

Primitive Pictures

Reproducing images with geometric primitives.

Example

How it Works

A target image is provided as input. The algorithm tries to find the single most optimal shape that can be drawn to minimize the error between the target image and the drawn image. It repeats this process, adding one shape at a time. Around 50 to 200 shapes are needed to reach a result that is recognizable yet artistic and abstract.

Primitive for macOS

Now available as a native Mac application!

https://primitive.lol/

Twitter

Follow @PrimitivePic on Twitter to see a new primitive picture every 30 minutes!

The Twitter bot looks for interesting photos using the Flickr API, runs the algorithm using randomized parameters, and posts the picture using the Twitter API.

You can tweet a picture to the bot and it will process it for you.

Command-line Usage

Run it on your own images! First, install Go.

go get -u github.com/fogleman/primitive
primitive -i input.png -o output.png -n 100

Small input images should be used (like 256x256px). You don't need the detail anyway and the code will run faster.

Flag Default Description
i n/a input file
o n/a output file
n n/a number of shapes
m 1 mode: 0=combo, 1=triangle, 2=rect, 3=ellipse, 4=circle, 5=rotatedrect, 6=beziers, 7=rotatedellipse, 8=polygon
rep 0 add N extra shapes each iteration with reduced search (mostly good for beziers)
nth 1 save every Nth frame (only when %d is in output path)
r 256 resize large input images to this size before processing
s 1024 output image size
a 128 color alpha (use 0 to let the algorithm choose alpha for each shape)
bg avg starting background color (hex)
j 0 number of parallel workers (default uses all cores)
v off verbose output
vv off very verbose output

Output Formats

Depending on the output filename extension provided, you can produce different types of output.

  • PNG: raster output
  • JPG: raster output
  • SVG: vector output
  • GIF: animated output showing shapes being added - requires ImageMagick (specifically the convert command)

For PNG and SVG outputs, you can also include %d, %03d, etc. in the filename. In this case, each frame will be saved separately.

You can use the -o flag multiple times. This way you can save both a PNG and an SVG, for example.

Progression

This GIF demonstrates the iterative nature of the algorithm, attempting to minimize the mean squared error by adding one shape at a time. (Use a ".gif" output file to generate one yourself!)

Static Animation

Since the algorithm has a random component to it, you can run it against the same input image multiple times to bring life to a static image.

Pencils

Creative Constraints

If you're willing to dabble in the code, you can enforce constraints on the shapes to produce even more interesting results. Here, the rectangles are constrained to point toward the sun in this picture of a pyramid sunset.

Pyramids

Shape and Iteration Comparison Matrix

The matrix below shows triangles, ellipses and rectangles at 50, 100 and 200 iterations each.

Matrix

How it Works, Part II

Say we have a Target Image. This is what we're working towards recreating. We start with a blank canvas, but we fill it with a single solid color. Currently, this is the average color of the Target Image. We call this new blank canvas the Current Image. Now, we start evaluating shapes. To evaluate a shape, we draw it on top of the Current Image, producing a New Image. This New Image is compared to the Target Image to compute a score. We use the root-mean-square error for the score.

Current Image + Shape => New Image
RMSE(New Image, Target Image) => Score

The shapes are generated randomly. We can generate a random shape and score it. Then we can mutate the shape (by tweaking a triangle vertex, tweaking an ellipse radius or center, etc.) and score it again. If the mutation improved the score, we keep it. Otherwise we rollback to the previous state. Repeating this process is known as hill climbing. Hill climbing is prone to getting stuck in local minima, so we actually do this many different times with several different starting shapes. We can also generate N random shapes and pick the best one before we start hill climbing. Simulated annealing is another good option, but in my tests I found the hill climbing technique just as good and faster, at least for this particular problem.

Once we have found a good-scoring shape, we add it to the Current Image, where it will remain unchanged. Then we start the process again to find the next shape to draw. This process is repeated as many times as desired.

Primitives

The following primitives are supported:

  • Triangle
  • Rectangle (axis-aligned)
  • Ellipse (axis-aligned)
  • Circle
  • Rotated Rectangle
  • Combo (a mix of the above in a single image)

More shapes can be added by implementing the following interface:

type Shape interface {
	Rasterize() []Scanline
	Copy() Shape
	Mutate()
	Draw(dc *gg.Context)
	SVG(attrs string) string
}

Features

  • Hill Climbing or Simulated Annealing for optimization (hill climbing multiple random shapes is nearly as good as annealing and faster)
  • Scanline rasterization of shapes in pure Go (preferable for implementing the features below)
  • Optimal color computation based on affected pixels for each shape (color is directly computed, not optimized for)
  • Partial image difference for faster scoring (only pixels that change need be considered)
  • Anti-aliased output rendering

Inspiration

This project was originally inspired by the popular and excellent work of Roger Johansson - Genetic Programming: Evolution of Mona Lisa. Since seeing that article when it was quite new, I've tinkered with this problem here and there over the years. But only now am I satisfied with my results.

It should be noted that there are significant differences in my implementation compared to Roger's original work. Mine is not a genetic algorithm. Mine only operates on one shape at a time. Mine is much faster (AFAIK) and supports many types of shapes.

Examples

Here are more examples from interesting photos found on Flickr.

Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example

primitive's People

Contributors

fogleman avatar larryng avatar linkerlin avatar mmlkrx avatar sylvaindumont avatar zwade avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

primitive's Issues

Feature request: batch processing

Hoping this isn't something obvious that I just missed, but is it possible to batch process a folder of images? If not, is it a possible feature down the line?

Possible new option

An interesting option could be to implement a score based cutoff... so instead of providing the number of primitives one would specify the desired "score" of the result.

I am not sure I fully understand the scoring at the moment. Is a score of 1 (1 x 100) meaning 100% away from source picture and a score of 0.01 (0.01 x 100) meaning 1% away from source...

install failure `r.mask.AlphaAt undefined`

Upon install via go get -u github.com/fogleman/primitive I get the following error:

# github.com/fogleman/gg
./pattern.go:101: r.mask.AlphaAt undefined (type *image.Alpha has no field or method AlphaAt)

I'm running Mac OS X 10.11.6 and go version go1.3.1 darwin/386

Not recognizing primitive as a command

Hi!

I'm having trouble trying to run primitive after following the instructions. It's similar to another open issue but not quite the same.

When I use "go get -u github.com/fogleman/primitive", should I be expecting any output? I don't see anything, but there's a pause which makes it seems like it's fetching the dependencies. When it stops, there aren't any new directories or files in my current directory.
But when I try "primitive -i input.png -o output.png -n 100" (filling in the input.png and output.png with my image name), I get an error message saying "'primitive' is not recognized as an internal or external command, operable program or batch file." I tried this both on my Windows machine and a virtual machine running Linux.

Is this something that has occurred before? Are there any other steps I should take or check?

Thank you!

Going through all mode instead of random

OK, so I pushed my original idea of going through all different mode at each iteration to pich the best form providing the lowest score. The result is that the final score doing it that way is significantly lower than just using mode 1. Mode 1 usually provide the best score of all methods.

http://imgur.com/a/11jDL

As you can see even with a lower score the triangle method provide the best looking image to my eye... but it is interesting to see that you can get lower score bay going through all possible shapes. Here is the code I used. Not optimal but you might want to try it:

func (model *Model) BestHillClimbState(buffer *image.RGBA, t ShapeType, a, n, age, m int, rnd *rand.Rand) *State {
    var bestEnergy float64
    var bestState *State
    //v("%d\n",m)
    if t != 0 {
        for i := 0; i < m; i++ {
            state := model.BestRandomState(buffer, t, a, n, rnd)
            before := state.Energy()
            state = HillClimb(state, age).(*State)
            energy := state.Energy()
            vv("%dx random: %.6f -> %dx hill climb: %.6f\n", n, before, age, energy)
            if i == 0 || energy < bestEnergy {
                bestEnergy = energy
                bestState = state
            }
        }
    } else {
        for j := 1; j < 6; j++ {
            for i := 0; i < m; i++ {
                state := model.BestRandomState(buffer, ShapeType(j), a, n, rnd)
                before := state.Energy()
                state = HillClimb(state, age).(*State)
                energy := state.Energy()

                if i == 0 && j == 1 || energy < bestEnergy {
                    vv("%dx random: %.6f -> %dx hill climb: %.6f\n", n, before, age, energy)
                    bestEnergy = energy
                    bestState = state
                }
            }
        }
    }

    return bestState
}

This is the parameters I used:

primitive -i src.jpg -o test0v1.svg -n 1000 -v -m 0

vs

primitive -i src.jpg -o test1v1.svg -n 1000 -v -m 1

Obviously the downside is that it take 5 times longer to get the result...

New code as of Oct 3 21h34 PM issues

I noticed the following issue:

worker.go:

func (worker *Worker) RandomState(t ShapeType, a int) *State {
    switch t {
    default:
        return worker.RandomState(ShapeType(worker.Rnd.Intn(6)+1), a)

should be changed to

func (worker *Worker) RandomState(t ShapeType, a int) *State {
    switch t {
    default:
        return worker.RandomState(ShapeType(worker.Rnd.Intn(8)+1), a)

I also noticed that the SVG vs PNG images produced are quite different:

http://imgur.com/a/uRtQg

I used the following to produce the output:

primitive -i dst.jpg -o testdst.svg -o testdst.png -n 500 -v -a 0 -m 0 -r 512 -s 512 -rep 5

Inconsistent -rep parsing withmultiple configs

Apparently it's possible to pass multiple -m {mode} -n {num} configs, which is really cool. However, when I was trying it, I noticed that some -rep settings were not being used (or it wasn't using the right ones).

This is the command I'm using:

> GOPATH=/Users/davethegr8/Dropbox/primitives time go run src/github.com/fogleman/primitive/main.go -v -i flower.jpg -o "flower/20171017145645-m0-n1-rep1-m1-n1-rep2-m5-n1-rep2-m6-n1-rep2.svg" -m 0 -n 1 -rep 1 -m 1 -n 1 -rep 2 -m 5 -n 1 -rep 2 -m 6 -n 1 -rep 2

And here's output:

0 <== I hacked in fmt.Println(Repeat) in func (i *shapeConfigArray) Set(value string)
1
2
2
2
{1 0 128 0} <== added fmt.Println(config) in for _, config := range Configs
{1 1 128 1}
{1 5 128 2}
{1 6 128 2}
reading flower.jpg
0: t=0.000, score=0.222857
count=1, mode=0, alpha=128, repeat=0
1: t=0.626, score=0.165856, n=21553, n/s=34.4k
count=1, mode=1, alpha=128, repeat=1
0 1 <== added fmt.Println(i, repeat) in model.go line 124
2: t=1.377, score=0.114709, n=19751, n/s=26.3k
count=1, mode=5, alpha=128, repeat=2
0 2
1 2
3: t=1.515, score=0.103102, n=18435, n/s=133.5k
count=1, mode=6, alpha=128, repeat=2
0 2
1 2
4: t=1.664, score=0.102205, n=18285, n/s=122.8k
writing flower/20171017145645-m0-n1-rep1-m1-n1-rep2-m5-n1-rep2-m6-n1-rep2.svg

real	0m2.363s
user	0m9.185s
sys	0m0.188s

You can see that while I'm passing 4 -rep values, 5 are printed out, and when the shapeConfig objects are built, they are off by 1 with the default value getting stuck on the beginning.

I tried to see if I could fix the issue, but I'm not familiar enough with go.

Feature Request: Full control of all shapes used on the Mac application

I'd like to suggest an option where a user can suggest exactly which shapes are used before running an image. The current options are "all" or a single type of shape. My use case is that I don't like the "streaky" effect created by lines but I like the combo option otherwise, so I would like to run the generation with only triangles, circles, rectangles, etc.

Other potential mode

Very interesting what you have done.

I was wondering if the following mode would not provide even better fit quicker:

bestscore = 1
for each mode (triangle, rectangle, etc, etc)
  get newscore
  if newscore is < bestscore then keep output
end
return best shape

This way you would get a blend of shapes that provide the quickest score decrease based on the best shape for the iteration.

Trying to understand the source code so I could try to implement. This could become a new -m option for "optimized blend mode"

Super awesome!

Just wanted to say thanks! Please close. No action needed.

Example pictures have all rights reserved?

Examples

One example from README.md: link

Using google's reverse image search I've found which looks like original picture from flickr (as stated in the README.md - originals are from flickr): flickr_link

There are more:

From README.md: link
From flickr.com: flickr_link

I have not searched more.

Problem

Both examples have All rights reserved for license.

In photography (or any other creative activity) just as in software programming, there are licenses which must be respected even if you can break them easily (how can let flickr download images with all rights reserved this easily - is another topic and mystery to me).

As an amateur photographer I have seen this a few times. People from different industries forget that other creative work is under some license as well and it's not always allowed to modify or share work without attribution or informing the original author.

Confusion

@fogleman, maybe you've asked for permission from authors to use these photos? Maybe there are originals somewhere, which are under public domain or creative commons? Or maybe google found some stolen content? Then I am sorry for my confusion.

Solutions

@fogleman - you have a very nice collection of open source software projects, where some of them I am following and/or using, though if the problem is true, probably the best solution would be to find other pictures on flickr which are allowed to be modified[0] (their search allows to filter by license) and use them as examples. Also, not forget to mention the original author and the original picture. It would be just very good practice to do so even if license does not enforces this. Example section would be much nicer as well, as we could compare original images with transformed ones.

macOS app

I have not done reverse search, but are all images in https://primitive.lol/ have licenses for sharing modified work?

[0] This is important - not all CC images are allowed to be modified.

Can I perform transforming black-n-white image to nonoverlapping triangles?

I'm wondering if I could transform black-n-white images to nonoverlapping triangles like this by using your library:

I'm pretty sure that answer is "No", but it's worth to ask :) Maybe you know some other tool which can perform what I'm asking for?

Thanks a million! You're the badass, I'm totally amazed by PrimitivePic 🚀

SVG Output?

It would be wonderfully awesome if you supported either SVG or some other vector form of output ;)

Gif speed

It is possible to make the gif go faster?

Awesome tool

Edge case bug?

Looks like 0 is passed to Intn?

panic: invalid argument to Intn

goroutine 8 [running]:
panic(0x539800, 0xc42000edb0)
    /usr/lib/go/src/runtime/panic.go:500 +0x1a1
math/rand.(*Rand).Intn(0xc4200104a0, 0x0, 0x0)
    /usr/lib/go/src/math/rand/rand.go:116 +0xd0
github.com/fogleman/primitive/primitive.NewRandomEllipse(0x1, 0x1, 0xc4200104a0, 0x0)
    /usr/lib/go/src/github.com/fogleman/primitive/primitive/ellipse.go:22 +0x8d
github.com/fogleman/primitive/primitive.(*Model).RandomState(0xc420072210, 0xc420018600, 0x3, 0x80, 0xc4200104a0, 0x20)
    /usr/lib/go/src/github.com/fogleman/primitive/primitive/model.go:198 +0x3bd
github.com/fogleman/primitive/primitive.(*Model).BestRandomState(0xc420072210, 0xc420018600, 0x3, 0x80, 0x64, 0xc4200104a0, 0x0)
    /usr/lib/go/src/github.com/fogleman/primitive/primitive/model.go:179 +0x7e
github.com/fogleman/primitive/primitive.(*Model).BestHillClimbState(0xc420072210, 0xc420018600, 0x3, 0x80, 0x64, 0x64, 0x2, 0xc4200104a0, 0x0)
    /usr/lib/go/src/github.com/fogleman/primitive/primitive/model.go:162 +0xcf
github.com/fogleman/primitive/primitive.(*Model).runWorker(0xc420072210, 0x3, 0x80, 0x64, 0x64, 0x2, 0xc42005a180)
    /usr/lib/go/src/github.com/fogleman/primitive/primitive/model.go:154 +0x234
created by github.com/fogleman/primitive/primitive.(*Model).runWorkers
    /usr/lib/go/src/github.com/fogleman/primitive/primitive/model.go:136 +0x13b

Portrait mode

If I input a jpg with portrait dimensions (e.g. taken on a phone), the output png/svg files are rotated 90 degrees. Is there a way to have them output to the original orientation?

Command-line usage

How and where to use this command-line primitive -i input.png -o output.png -n 100 after install Go ?

Missing requirement?

Attempting to install I am prompted with this error. Any ideas what I am doing wrong here?

[I] ~ $ go get -u github.com/fogleman/primitive
# github.com/fogleman/primitive/primitive
go/src/github.com/fogleman/primitive/primitive/util.go:145:13: error: reference to undefined field or method ‘RGBAAt’
    c := rgba.RGBAAt(x, y)
             ^

Problems with setting up primitive

Hi!

I am trying to download and use primitive, but I am having some issues at the moment.. after I install Go (which is properly installed now) I run the command
go get -u github.com/fogleman/primitive
and I get this: error: cannot open .git/FETCH_HEAD: Permission denied
package github.com/fogleman/primitive: exit status 1

I don't understand what I am doing wrong, is there anything I can do to use it?

Thanks a lot!

Gio

Export steps

I'm having a great artistic time with Primitive. As a photograph myself there's a lot of reinterpretations of my previous works that are now accessible. So thank you for such a tool with massive palette of expressivity.

Currently the tool mix a lot of steps together. Reading the file, analysing the content, finding the best solution to match the forms, drawing them and writing the file.

Would it be possible to have an option to export the drawing steps in a basic file (Json ?) so we can draw the result in another tool (for people not confortable with Go) or have a handle in the Api so we can add other treatment to the form before it is drawn (for Gopher).

Thank you Michael for any feedback on the idea.

Link back to original Flickr images in README?

Hi, it would probably be cool if you would link back to the original Flickr images so that

  1. We can see the input images
  2. The artists get proper credit!

Edit add: and on the Twitter account as well :)

(Or maybe add an optional text watermark with those details?)

Scale 0?

<g transform="translate(9 143) rotate(54) scale(62 0)">

Doesn't look right. Looks like a bug?

Feature request: transparent background

Hi,

I want to use this to generate character sprites for a video game idea. Is there a way to make primitive work with a fully transparent background?

Thanks,

SVG Export broken when setting mode to polygon

It seems that SVG export is currently broken when applying the "-m 8" switch for polygon mode. PNGs render just fine, but when switching to SVG, the resulting XML is almost empty, aka no polygons are declared:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="680" height="1024">
<rect x="0" y="0" width="680" height="1024" fill="#797261" />
<g transform="scale(4.000000) translate(0.5 0.5)">










</g>
</svg>

Tested with "kodim19" test image (http://optipng.sourceforge.net/pngtech/corpus/kodak/kodim19.png) using the following switches: "primitive -i kodim19.png -o kodim19_primitive.svg -n 10 -m 8". My environment is WSL, Linux Subsystem for Windows, Ubuntu 16.04 based, Fish shell, Golang v. 1.7.4 installed via LinuxBrew)

Original Test Image:
kodim19

PNG output for -m 8 polygons:
kodim19_primitive

As you can see, other simple SVG shapes export just fine. Here's an example with -m 0 (Mixed mode): "primitive -i kodim19.png -o kodim19_primitive.svg -n 10 -m 0". Notice how the lines in which polygons should have been declared stay empty:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="680" height="1024">
<rect x="0" y="0" width="680" height="1024" fill="#797261" />
<g transform="scale(4.000000) translate(0.5 0.5)">
<ellipse fill="#322100" fill-opacity="0.501961" cx="100" cy="255" rx="78" ry="78" />
<g transform="translate(105.514796 130.100027) rotate(280.849337) scale(59.841250 23.290682)"><ellipse fill="#ffe0ac" fill-opacity="0.501961" cx="0" cy="0" rx="1" ry="1" /></g>
<ellipse fill="#f1c892" fill-opacity="0.501961" cx="20" cy="157" rx="37" ry="37" />
<ellipse fill="#aeaba8" fill-opacity="0.501961" cx="152" cy="71" rx="32" ry="52" />
<g transform="translate(18.213148 240.040670) rotate(137.721049) scale(46.473918 22.640788)"><ellipse fill="#342b03" fill-opacity="0.501961" cx="0" cy="0" rx="1" ry="1" /></g>
<ellipse fill="#3b3512" fill-opacity="0.501961" cx="159" cy="195" rx="47" ry="31" />
<ellipse fill="#4e5e7b" fill-opacity="0.501961" cx="57" cy="6" rx="79" ry="79" />


<rect fill="#6d7174" fill-opacity="0.501961" x="14" y="72" width="84" height="56" />
</g>
</svg>

Performance

Hey there,

First of all, thanks for making this available open source! :D

I'm working on a side project. It's a mobile app with a backend. It has user profiles and user uploaded photos. I came across this repo today and I really, really, really want to use this for my project. It's such a beautiful effect.

I've played around with it a bit on my laptop using different parameters and a bunch of different images of people. For me, the best result is when I use 200 iterations and the default resize option of 256. The problem is, this takes around 50+ seconds (with -v enabled). And this is on my rMBP (top of the range a couple of years ago, so the specs are decent).

If I did this on a backend server, it would probably take even longer, since the server I could afford wouldn't be a beast.

This is probably a really stupid question, I know, but is there any way the code could be further optimised to increase the overall performance of it?

I was going to use this together with my NodeJS backend and somehow make it work. But knowing that it might add ~1 minute of extra processing time per image upload, I'm not too sure anymore.

Do you have any recommendations? I tried playing around with the resize parameter, but setting it to 64 or even 128 is too low for my liking. The effect just isn't as good as 256. Same with the iteration count. Anything lower than 200 just isn't as beautiful.

Thanks

failed MSpanList_Insert

Used it like so:

primitive -i mushroom.jpg -o mushroom-primitive.jpg -n 100 -r=256

With this pic:

![mushroom](https://cloud.githubusercontent.com/assets/1270998/18768354/8ddb334e-80f2-11e6-8bc2-2976f49cf947.jpg)

Error log:

failed MSpanList_Insert 0x35dd90 0x4b897ae7b8e 0x0
fatal error: MSpanList_Insert

runtime stack:
runtime.MSpanList_Insert(0x30aa68, 0x35dd90)
    /usr/local/go/src/runtime/mheap.c:692 +0x8f
runtime.MHeap_Alloc(0x307660, 0x1, 0x1000000002b, 0xe209)
    /usr/local/go/src/runtime/mheap.c:240 +0x66
runtime.MCentral_CacheSpan(0x310ff8, 0x35dcc0)
    /usr/local/go/src/runtime/mcentral.c:85 +0x167
runtime.MCache_Refill(0x349000, 0x2b, 0x35dcc0)
    /usr/local/go/src/runtime/mcache.c:90 +0xa0

goroutine 1 [running]:
runtime.switchtoM()
    /usr/local/go/src/runtime/asm_amd64.s:198 fp=0xc2088bf8b8 sp=0xc2088bf8b0
runtime.mallocgc(0x1000, 0x0, 0x3, 0x1d3f9)
    /usr/local/go/src/runtime/malloc.go:178 +0x849 fp=0xc2088bf968 sp=0xc2088bf8b8
runtime.rawmem(0x1000, 0x1000)
    /usr/local/go/src/runtime/malloc.go:371 +0x39 fp=0xc2088bf990 sp=0xc2088bf968
runtime.growslice(0x174b20, 0xc2080e4800, 0x53, 0x53, 0x1a, 0x0, 0x0, 0x0)
    /usr/local/go/src/runtime/slice.go:83 +0x237 fp=0xc2088bf9f0 sp=0xc2088bf990
github.com/fogleman/primitive/primitive.rasterizeTriangle(0xff, 0x21, 0xff, 0x73, 0x23, 0x8d, 0x0, 0x0, 0x0)
    /Users/jmazz/go/src/github.com/fogleman/primitive/primitive/triangle.go:126 +0x348 fp=0xc2088bfa98 sp=0xc2088bf9f0
github.com/fogleman/primitive/primitive.(*Triangle).Rasterize(0xc2084c5e40, 0x0, 0x0, 0x0)
    /Users/jmazz/go/src/github.com/fogleman/primitive/primitive/triangle.go:101 +0x74 fp=0xc2088bfae8 sp=0xc2088bfa98
github.com/fogleman/primitive/primitive.(*Model).Energy(0xc208058180, 0x35b770, 0xc2084c5e40, 0xc208032a40, 0xc2084c5e40)
    /Users/jmazz/go/src/github.com/fogleman/primitive/primitive/model.go:213 +0x44 fp=0xc2088bfb78 sp=0xc2088bfae8
github.com/fogleman/primitive/primitive.(*State).Energy(0xc20803ccc0, 0x1db160)
    /Users/jmazz/go/src/github.com/fogleman/primitive/primitive/state.go:16 +0x4c fp=0xc2088bfba8 sp=0xc2088bfb78
github.com/fogleman/primitive/primitive.HillClimb(0x35b7b8, 0xc20803ccc0, 0x64, 0x0, 0x0)
    /Users/jmazz/go/src/github.com/fogleman/primitive/primitive/anneal.go:63 +0xec fp=0xc2088bfc00 sp=0xc2088bfba8
github.com/fogleman/primitive/primitive.(*Model).BestHillClimbState(0xc208058180, 0xc208032a40, 0x1, 0x64, 0x64, 0xa, 0x3a7e5)
    /Users/jmazz/go/src/github.com/fogleman/primitive/primitive/model.go:135 +0xf4 fp=0xc2088bfd00 sp=0xc2088bfc00
github.com/fogleman/primitive/primitive.(*Model).Step(0xc208058180)
    /Users/jmazz/go/src/github.com/fogleman/primitive/primitive/model.go:122 +0x55 fp=0xc2088bfd58 sp=0xc2088bfd00
main.main()
    /Users/jmazz/go/src/github.com/fogleman/primitive/main.go:109 +0x69a fp=0xc2088bff98 sp=0xc2088bfd58
runtime.main()
    /usr/local/go/src/runtime/proc.go:63 +0xf3 fp=0xc2088bffe0 sp=0xc2088bff98
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc2088bffe8 sp=0xc2088bffe0

Mac app

hi,

It's possible to create a Mac app that runs a go script ? How? Thanks a lot

output to .gif file format fails under windows

In Windows the "convert" command is already being used by "convert.exe" command to convert file systems. Trying to output to gif fails with "exit status 4".

Reason:

"convert -loop 0 -delay 50 C:\Users\xxxxx\AppData\Local\Temp\239865135*.png -delay 200 C:\Users\xxxxx\AppData\Local\Temp\239865135\000038.png test.gif"

According to the docs, the complete command should be:

"magick convert" rose.jpg rose.png

http://www.imagemagick.org/script/convert.php

Silently fails when specifying jpg as output

Running latest Go on Windows 10, specifying

primitive.exe -i file.jpg -o otherfile.jpg -n 100 -v

fails to write the output file with no error, verbose output ends with writing otherfile.jpg.
Switching to -o otherfile.png works.

Should probably mention that installation requires Git

Since Go is only mentioned as a dependency, then Git should be mentioned as well (is required for go get command). Otherwise you probably could get away with just telling how this is a Go application, and let people figure the rest themselves.

Feature suggestion: colour gradient

I find these images hypnotic. I would like to see one composed of shapes with an RGB colour gradient fill. In many cases one shape (e.g., rectangle) with a gradient fill could outperform many single colour shapes.

So fewer parameters needed to fit the same image.

Support source image transparency

The simple case I'm thinking is when transparency in my source image is a simple mask i.e. the opaque areas are contiguous and the alpha channel is either zero or one (apart from anti-aliasing at the edges). I imagine I'm looking for a solution that mainly picks primitives that (mostly) fit within the mask, i.e. the output primitives can be fully opaque.

The more complex case is one with graduations of transparency and islands of full transparency. I imagine in that case you'd want to add the alpha channel as an extra dimension along with rgb (for error calculation etc.)

Multiple outputs

Right now primitive only writes one output file (except for saving frames 9caadaa),

For instance, if I want to save an svg and a png, I must do this:

primitive -n 100 -i x.jpg -o a.svg
gm convert -size 300 a.svg a.png

But what if primitive supported this,

primitive -n 100 -i x.jpg -o a.svg -o a.png

I don't know if the go flags package supports the above; if not, how about,

primitive -n 100 -i x.jpg a.svg a.png

which is probably easier to implement (but backward incompatible).

Option to output added shapes

Thank you for your hard work on Primitive. It is nothing short of amazing.

When you output e.g. an SVG with %d in the name, each frame is saved separately. Do you think it would be possible to add an option to export just the shape that got added for every frame?

What are you doing with primitive?

It looks like at least a few of you are building things on top of primitive? I'm just curious what you're working on. Let me know if you want. :)

Windows 10 primitive command not recognized

Hi,
first of all i'm new to go :)
The steps i did:

  1. Install go from golang.org (Installdir C:\Go)
  2. Path Variable added: C:\Go\bin
  3. GOROOT = C:\Go\
  4. Created new workingdirectory C:\Go\workspace
  5. GOPATH= C:\Go\workspace
  6. then i run go get -u github.com/fogleman/primitive which runs through smooth
    After that i tried running primitive but it isn't recognized as a command, i tried powershell and command line.
    What did i miss?

Element size based on color

While I am not sure how to implement it, I would like to propose a new way of shape generation.
Right now it starts with large shapes and adds smaller ones with each progression. I'd like to start with large dark shapes, and continue to medium large medium bright shapes up to small bright shapes.
This would replicate a more traditional way of painting, and - I hope - make an interesting effect.
Is there a way to implement it in the current codebase?

Background color, edge-treatment, transparency and generated SVG integration

Hi Michael

I wanted to have a snooze on this before writing the issue as it was 4AM and my mind was far below even at its usually unimpressive level. Even now it's probably not the clearest, and could perhaps be better broken down in to a number of component issues by yourself.

In short I am quite happy indeed with the generated SVGs and have been able to get them loading in to my Lua/LÖVE-based game environment after writing my quick and hacky svg2love tool.

The issue I am facing now is that for anything but 'picture in a square' level of graphical integration, there is a need to obtain non-hard edges on the images, and/or some additional intelligence in primitive with respect to output and transparency.

Transparency: Currently it seems that primitive assumes that an image should be drawn to 100% opacity in all places, drawing a background rectangle in output SVGs to kick off the process. What I would really like is the option to not include this background rectangle or the assumption that it is based on. For example, if I could run with a switch like primitive -b 000000 to have primitive assume that the background was already present and black. In this case, the background rectangle would not be drawn in the resulting SVG but more importantly the other colors would have been chosen in such a manner as to create the desired output assuming a black background. Then if I were to paste on to a blackish background, the majority of the image would have solid opacity, and the image would integrate more closely with arbitrary environments without demanding a square border.

Edges: There are semi-frequently significant edge artifacts in the images. Thus far I have been dealing with these by cropping, but I wonder if there is an algorithmic enhancement or adjustment that you could make to avoid having, for example, long shapes occurring along the edge of an image bringing with them an additional 'gutter' to the output image.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.