Search code examples
c++algorithmvisual-c++image-processingphoto

Photo Mosaic Algorithm. How to create a mosaic photo given the basic image and a list of tiles?


Hy.What I have to do is to create a program (using C or C++), that takes as input a 24bits/pixel bitmap and a gathering of images and I have to create a mosaic image , similar to the input image using the library of images given(To create a mosaic Photo similar to the input).

So far I can access the input's image pixels and the colors from it but I'm kind of stuck. My question is Where should I start? I need a basic algorithm that could do such a thing. And I can't really find any(maybe I'm looking wrong). And also can someone tell me a random photo downloader, so that i can download small images for the project? Can someone help me? Please, tell me where to start and what to use.


Solution

  • I've done this in Scala. The Dr Dobbs article was extremely useful to me.

    Sample image:

    Sample photomosaic

    Here's my basic algorithm:

    def createMosaic(targetImage:BufferedImage,
      index:PhotoIndexer.PhotoIndex,
      opacity:Float,
      targetWidth:Int,
      targetHeight:Int,
      numRows:Int,
      numColumns:Int, callback:PhotoMosaicCallback): ImageGrid = {
    
          var indexCopy = index
    
          // Map from the buffered image to that image's average color
          var colorMap:Map[BufferedImage,Color] =
          index.values.map(data => (data.thumbnail, data.avgColor)).toMap
    
          // We look at rectangular regions of the target image, calculate their average
          // colors, and then pick images that match those colors.
          val sampleWidth = targetImage.getWidth / numColumns
          val sampleHeight = targetImage.getHeight / numRows
    
          // Used to report the progress of the process
          var counter = 1
          val numSubImages = numRows * numColumns
    
          val imageGrid:ImageGrid = Array.fill(numRows, numColumns)(Nil)
    
          // for each patch in the image
          for (row <- 0 until numRows) {
            for (column <- 0 until numColumns) {
              val x = column * sampleWidth
              val y = row * sampleHeight
              // This is the small rectangular region of the target image that we're
              // currently considering
              val subImage = targetImage.getData(new Rectangle(x,y,sampleWidth,sampleHeight))
              val avgImageColor = calculateColorFromRaster(subImage)
    
              val nearest:Seq[BufferedImage] = getNearestColorImages(avgImageColor, colorMap)
    
              // nearest is in sorted order; pick one of them and draw it to correct place in
              // image
              imageGrid(row)(column) = nearest
    
              callback.photosCalculated(row, column, nearest)
    
              val percent = 100.0 * counter / numSubImages
              // TODO: for GUI version, use a display bar
              if (counter % 100 == 0) {
                println(percent + " completed (" + counter + " of" + numSubImages + ")")
              }
              counter+=1
            }
          }
          imageGrid
    }
    

    My full sourcecode is available on github