Show HN: I made a tool to generate photomosaics with your pictures

pictiler.com

122 points by jakemanger a day ago

Hi HN!

I wanted to make some photomosaics for an anniversary gift, but I ended up building this tool and turning it into a website that anyone can use.

For those who don’t know, a photomosaic is an image made up of many smaller tile images, arranged in a way that forms a larger, recognisable picture.

The best part? Everything runs directly in your browser. No files are uploaded, and there’s no sign-up required.

ColinEberhardt a day ago

Very cool. I actually created a shareware application that rendered Photomosaics 25 years ago! Here is a link to "Mosaic Magic" from the Wayback Engine:

https://web.archive.org/web/20010405175706/http://fishsoft.c...

I managed to make a decent amount of spending money from that application during my University years.

One interesting lesson I learnt was about enterprise pricing. I think I charged ~$20 for Mosaic Magic, however, I started to get emails from organisations asking about pricing for commercial use. Nothing on my pricing page suggested that commercial use was prohibited, I guess they just thought $20 was rather cheap. From there-on, I charged $150 for "commercial use". Basically, anyone who thought they should be paying more, did!

Finally, Robert Silvers filed a patent and trademark for Photomosaics in ~2000, and was, for a while aggressively pursuing organisations that he felt was infringing. I assume this has all died down now.

  • jakemanger a day ago

    Thanks for sharing! Both the link and the story. As a University student and someone that has here also made a photomosaic app, that is super relatable.

    That's good to know about the pricing. It's free for now. Honestly didn't expect this level of interest (there's 307 people on the site right now according to analytics).

    With that interest, I may add some plans - potentially for the commercial use in particular

  • bryanthompson a day ago

    I used Mosaic Magic back in my high school journalism class to design a yearbook cover 20+ years ago! Turned out great - it won some kind of award iirc.

    • jakemanger 19 hours ago

      That is so funny - after all these years you were sitting at your computer at the same time and clicked on the same post as the creator

    • ColinEberhardt 9 hours ago

      Oh wow, so cool to meet someone who used an app I wrote 25 years ago. Great to hear from you and congrats on the prize!

  • teiferer a day ago

    Kudos to OP for not immediately thinking about how he best could monetize this.

    I'm glad FOSS made Shareware die out, but now web apps requiring me to create an account first have taken its place. Kudos to OP for resisting that too.

  • verelo a day ago

    I just read up on Robert Silvers based on this. He had an interesting career. Really unfortunate he was a patent troll...

bazzargh a day ago

While this is nice enough, it bothers me that these don't look much like "art". If you look at real roman mosaics, they do not place points in a grid - they use a technique called "opus vermiculatum" https://en.wikipedia.org/wiki/Opus_vermiculatum ... snaking the tiles around so that there is a flow to it; the overall effect is much better.

I think that'd be possible to automate too. I was doing something related over here: https://hachyderm.io/@bazzargh/112767548339559102 - in that I was trying to generate sketch-like renderings from photographs. What I did was to pick random points, look at the brightness gradient (taken from the Sobel operator, there are other ways to do this), move up the gradient a bit and sketch some parallel lines (and then various experiments with hatching for shading the flatter areas)

In a similar way you could start with a grid of tiles _with some separation_, and allow them to move and align better with the gradient of the underlying picture, and not lie _on_ edges, if possible. If they overlap, allow the tessera to be cut, and only then choose images to colour-match the average on the tile, leaving some "grout" in the image (I'd probably speckle that a bit so it didn't look too uniform). Then the result might look more like real mosaics.

I might give this a go...

  • bazzargh 26 minutes ago

    I managed to get some decent results using this algorithm (not at my own computer so can't post code, yet):

    - create a smaller greyscale copy of the image, and use sobel to calculate gradients (smaller to speed this up) - set a gradient magnitude threshold, and add those points to a queue, largest first. - for these points, add 2 squares, one either side of the queued point, in the direction of the gradient (ie you expect one to be light and one dark) - add the squares to a location hash as they are placed. (I'm using a grid size slightly larger than my square tiles). The location hash is to speed up comparisons. - skip placing a square if it would fall within a small radius of a previous square's centre (I used 0.5 of a square size). When looking up a point in the location hash, remember to look not for the point itself, but for the hash values for the corners of an axis-aligned square with your point at the centre; this is to catch overlaps when the point falls need grid lines. - once all points in this queue have been processed or skipped, we start on a new queue, containing all squares placed so far. - for each square in the queue, try to place a new square to its north, south, east and west along its alignment; as before skip these if they overlap too much - any squares we place - jitter their position and angle slightly (otherwise it looks horribly unnatural) - any squares we do place, add them to the phase 2 queue.

    The first phase is quite slow, set the threshold high. Second phase placement is very fast. My squares all use a grey stroke the same grey as the background for the grout effect, and the squares are drawn using the colour of the point picked as the square's centre (I don't bother averaging). I have it rendering this interactively, using requestAnimationFrame, so it doesn't clog up the browser - I add about 50 tiles per frame

    I'm looking at one it did of the mona lisa; it places the phase 1 tiles along her hairline and hand in a nice "vermiculatum" way, the phase 2 placement is less satisfying but with jitter it seems ok. Originally I'd thought about calculating where squares overlap and cutting tiles nicely but it was quicker just to _allow_ the overlap and so most of what you see are the whole tiles placed on top of partials. The overall effect isn't _quite_ like hand placed tiles but I like it better than a grid.

    You can see a couple of output images here. https://hachyderm.io/deck/@bazzargh/114938616011157584

  • wvlia5 a day ago

    It could be better sometimes for tiles to lie over edges. For example, there might be an edge dividing red and green areas, and one of your tiles is mostly half red and half green.

  • Theodores a day ago

    Whilst you are at it...

    https://github.com/openseadragon/openseadragon

    A photo mosaic demands to have photos that are high resolution. You don't want to zoom in to find blurry jpegs, it just isn't right!

    I have had great fun with OpenSeadragon in the past and now there is the VIPS image processing library for writing out a massive set of image tiles.

    Hence it is possible to work with thumbnails and then render out the thing with OpenSeadragon and VIPS.

    OpenSeadragon was amazing when it was a Microsoft demo a few decades ago, but time has moved on. I wonder what can be done with tilesets in HTML5 with picture tags or in SVG to present a infinitely zoomable montage.

    I like your suggestion and the options for rotating and clipping images with SVG methods. I always confuse mask and clip, but, in SVG, much could be done.

    For me, the starting point would be to do an SVG with thousands of images in it, to just watch my computer crash as I step up the resolution. Really I want to recreate OpenSeadragon in SVG...

  • wang_li a day ago

    There is a naive approach to making this kind of thing that reduces the component images to such a small size (2-3 pixels in large image) that turns this into more of a dithering exercise than looking for artifacts in each component image to match up lines. It's still a nice effect, but it's quite different when the component images are > 10% the size of the final image, instead of < 1% the size.

btbuildem a day ago

A friend of mine made this in the late 90s -- we were in highschool at the time. Of course he used it to make renditions of scantily-clad ladies out of thousands of pictures of, you guessed it.

  • jakemanger a day ago

    haha there's a few similar stories coming on here now. Great to hear.

    Hey, if you want to do that with this software, I can't see any files you upload (it's all local processing in your web browser), so go for it.

mentalgear a day ago

Nice! Almost 20 years ago I paid good money to get this done.

I see that your method also uses a lot of tinting and even overlaying the original image.

Would be great though if this was adjustable via sliders!

Thank You for making this available local-/privacy-first & in-browser!

  • jakemanger a day ago

    No worries! This is adjustable via sliders (in the bottom left area)

    Thanks for the kind words!

pimlottc a day ago

Small suggestion: in the "Try These Examples" section, the call-to-action is click a button that is not initially visible. Users have to hover over the image to see the "recreate" button, which is not obvious. You should add a dedicate "Recreate" button below each example so it's immediately clear what to do.

Also it would a good idea to have a detail view of a sample image at 100% to show that the images are made up of other photos. Maybe even an interactive zoom window. At monitor resolutions, the full images mostly just look like smudgy photos, and not all users may be familiar with photomosiacs. Even the "view" option on the sample mosiacs does not let you see the detail of the individual tiles very well.

  • jakemanger a day ago

    Thank you for the feedback! I actually just did a quick change to add that recreate button CTA like you said. Much better and easy to understand.

    I'll work on that detailed sample image view too. That's a great idea - job for tomorrow.

the_arun a day ago

If we combine this with canvas printing, we have an art business.

  • codingdave a day ago

    There are a plethora of print shops with API access to set this kind of thing up. The problem these days is pricing, specifically shipping. While people may be willing to pay for the work itself, shipping canvasses or framed prints gets expensive fast. This is why so many artists and photographers who sell their photos just sell posters... they are cheap to ship and don't give people sticker shock.

  • jakemanger a day ago

    I suppose you could make an art business. Or at least do what a few camera stores do

jnovacho a day ago

How exactly does this work? The example I chose is a mosaic of photos, over which is overlayed the original image with alpha set to 50%.

So it does not use the submitted photos as tiles, right?

  • jakemanger a day ago

    If you adjust the overlay alpha to 0% you'll see it does use the submitted photos as tiles.

    Click the "Create Mosaic" button and you should see it arrange the tiles live in the best possible way to reproduce the image. The overlay is a common technique people use to make the main image more visible. It's a personal preference thing.

    Generally, the more diverse or colours you select for your tile images, the more clear and "good" the main mosaic image will be

aosaigh a day ago

Excited to check this out. Did you write your own library for this or use something like OpenSeaDragon behind-the-scenes?

  • jakemanger a day ago

    This is completely my own library running in the cloud. Started as a little experiment for myself and now it's blown out into this

    • aosaigh a day ago

      I would potentially pay a licensing fee for the library if it could be used in other apps (and commercial settings).

darod a day ago

why does this require uploading my photos? can't something like this run native?

  • waltbosz a day ago

    The website says it runs locally. In browser JavaScript , you can import a file from local file system to JavaScript's local scope without sending it to a server. I'm guessing that's how this app works.

    If you want to know for sure, open your browser's dev tools, switch to the network tab, import a file and watch to see if a network request is made.

    • jakemanger a day ago

      Yes, that's exactly right. All your images are processed locally and don't leave your device. They are all processed in the web browser with javascript and your dev tools like you say should show that.

      • wvlia5 a day ago

        I think he means "why does it have to upload to the browser, can't it just read from the filesystem?" it should work, but browsers make it more complicated.

wvlia5 a day ago

Will you implement a recursive mosaic feature (some tiles bigger than others)?

  • jakemanger a day ago

    I could. That sounds like a great idea! Was thinking about uneven sized tiles. I just tried to make the basic photo mosaic with even sized tiles for now

cactusplant7374 a day ago

How hard is it to get something like this to work with HEIC?

  • jakemanger a day ago

    Are you on Mac? If you right click a file/s > Quick Actions > Convert Image then you should be able to convert to JPEG or PNG.

    Funnily enough I also made a universal file converter app which could do it for you on other platforms. Its at https://howtoconvert.co