Coverage Report - com.buckosoft.PicMan.business.mosaic.engine.VectorRibbon
 
Classes in this File Line Coverage Branch Coverage Complexity
VectorRibbon
0%
0/87
0%
0/36
5.8
 
 1  
 /******************************************************************************
 2  
  * VectorRibbon.java - Make a Mosaic
 3  
  * 
 4  
  * PicMan - The BuckoSoft Picture Manager in Java
 5  
  * Copyright(c) 2008 - Dick Balaska
 6  
  * 
 7  
  */
 8  
 package com.buckosoft.PicMan.business.mosaic.engine;
 9  
 
 10  
 import java.awt.Graphics2D;
 11  
 import java.awt.image.BufferedImage;
 12  
 import java.util.Iterator;
 13  
 import java.util.List;
 14  
 
 15  
 import org.apache.commons.logging.Log;
 16  
 import org.apache.commons.logging.LogFactory;
 17  
 
 18  
 import com.buckosoft.PicMan.business.mosaic.MosaicEngine;
 19  
 import com.buckosoft.PicMan.domain.MosaicTile;
 20  
 import com.buckosoft.PicMan.domain.Pic;
 21  
 import com.buckosoft.PicMan.domain.mosaic.MosaicVector;
 22  
 
 23  
 /** This engine walks through each row of a Pic and places the best tile there.
 24  
  * "Best" is determined by subtracting the precalculated MosaicVectors from the Pic and summing the different in each pixel.
 25  
  * This is performed from each tile in the set, and the one with the least difference is chosen.  
 26  
  * @author Dick Balaska
 27  
  * @since 2008/01/25
 28  
  * @see <a href="http://cvs.buckosoft.com/Projects/java/PicMan/PicMan/src/main/java/com/buckosoft/PicMan/business/mosaic/engine/VectorRibbon.java">VectorRibbon.java</a>
 29  
  */
 30  0
 public class VectorRibbon extends MosaicEngine {
 31  
         private static final boolean DEBUG = true;
 32  0
         private final Log logger = LogFactory.getLog(getClass());
 33  
         
 34  0
         private        int                curRow = 0;
 35  0
         private        int                curCol = 0;
 36  
         private        int                maxRow;
 37  
         private        int                maxCol;
 38  
         private        int                p;
 39  
         private        List<Pic>                        picList;
 40  
         @SuppressWarnings("unused")
 41  
         private        List<MosaicVector>        vectorList;
 42  0
         private        String        info = "N/A";
 43  
         private        long[]        used;
 44  
         
 45  
         /** Return our current build status
 46  
          * @return The status
 47  
          */
 48  
         public        String        getStatus() {
 49  0
                 StringBuilder sb = new StringBuilder();
 50  0
                 sb.append("curRow = ");
 51  0
                 sb.append(curRow);
 52  0
                 sb.append(" curCol = ");
 53  0
                 sb.append(curCol);
 54  0
                 sb.append(" p=");
 55  0
                 sb.append(p);
 56  0
                 return(sb.toString());
 57  
         }
 58  
 
 59  
         public String getInfo() {
 60  0
                 return(info);
 61  
         }
 62  
 
 63  
         protected boolean _build() {
 64  0
                 Graphics2D        gd = bi.createGraphics();
 65  
                 
 66  
                 // 75, pull from this size set even though the size calc should be able to deal with, say, a 50 and figure it out.
 67  0
                 picList = pmf.getDB().getPics(this.mosaicSet, 75);
 68  0
                 vectorList = pmf.getDB().getMosaicVectors(picList);
 69  
                 if (DEBUG)
 70  0
                         logger.info("Working from " + picList.size() + " pics");
 71  0
                 maxRow = this.masterPic.getHeight();
 72  0
                 maxCol = this.masterPic.getWidth();
 73  
                 //int                rowHeight = maxRow / tileHeight;
 74  0
                 long[]        rate = new long[picList.size()];                // rate each pic for this location
 75  0
                                 used = new long[picList.size()];                // number of times each pic is used
 76  0
                 info = "maxRow=" + maxRow + " maxCol=" + maxCol + " pics=" + picList.size();
 77  
                 if (DEBUG)
 78  0
                         logger.info("maxRow=" + maxRow + " rowHeight=" + tileHeight);
 79  
                 //restoreBuild(gd);
 80  0
                 for (; curRow<maxRow; curRow += tileHeight, curCol=0) {
 81  0
                         for (; curCol<maxCol; ) {
 82  
                                 int        x,y;
 83  0
                                 for (p=0; p<picList.size(); p++) {
 84  0
                                         BufferedImage mbi = pmf.getMosaicThumbNail(picList.get(p), tileHeight).getImage();
 85  
                                         //BufferedImage mbi = pmf.getThumbNail(null, tileHeight).getImage();
 86  0
                                         rate[p] = used[p];
 87  0
                                         for (x=0; x<mbi.getWidth(); x++) {
 88  0
                                                 for (y=0; y<mbi.getHeight(); y++) {
 89  0
                                                         int mpx = mbi.getRGB(x, y);
 90  
                                                         int        ppx;
 91  0
                                                         if (x+curCol >= bi.getWidth() || y+curRow >= bi.getHeight())
 92  0
                                                                 ppx = mpx;
 93  
                                                         else
 94  0
                                                                 ppx = bi.getRGB(x+curCol, y+ curRow);
 95  0
                                                         rate[p] += Math.abs((mpx - ppx) & 0xFF);
 96  0
                                                         rate[p] += Math.abs(((mpx-ppx) >> 8) & 0xFF);
 97  0
                                                         rate[p] += Math.abs(((mpx-ppx) >> 16) & 0xFF);
 98  
                                                 }
 99  
                                         }
 100  
                                         // Portrait always wins over landscape because there is less pixels to go wrong.
 101  
                                         // Give equal weight per pixel column
 102  0
                                         rate[p] /= mbi.getWidth();
 103  
                                         //logger.info("rate[" + p + "]=" + rate[p] + " ("+ picList.get(p).getName() + ")");
 104  
                                 }
 105  0
                                 long best = Long.MAX_VALUE;
 106  0
                                 int        besti = -1;
 107  0
                                 int        besti2 = -1;
 108  0
                                 for (x=0; x<rate.length; x++) {
 109  0
                                         if (rate[x] < best) {
 110  0
                                                 besti2 = besti;
 111  0
                                                 best = rate[x];
 112  0
                                                 besti = x;
 113  
                                         }
 114  
                                 }
 115  
                                 if (DEBUG) {
 116  0
                                         logger.info("besti  = " + besti + " (" + picList.get(besti).getName() + ") = " + rate[besti]);
 117  0
                                         logger.info("besti2 = " + besti2 + " (" + picList.get(besti2).getName() + ") = " + rate[besti2]);
 118  
                                 }
 119  0
                                 used[besti]++;
 120  0
                                 BufferedImage mbi = pmf.getThumbNail(picList.get(besti), tileHeight).getImage();
 121  0
                                 if (!mosaic.isBatch()) {
 122  0
                                         MosaicTile        tile = new MosaicTile(this.mid, picList.get(besti).getPid(), curCol, curRow, mbi.getWidth(), mbi.getHeight());
 123  0
                                         pmf.getDB().storeMosaicTile(tile);
 124  
                                 }
 125  0
                                 gd.drawImage(mbi, null, curCol, curRow);
 126  0
                                 curCol += mbi.getWidth();
 127  0
                                 setLastMosaicUpdate();
 128  0
                         }
 129  
                 }
 130  0
                 return(false);
 131  
         }
 132  
 
 133  
         @SuppressWarnings("unused")
 134  
         private        void restoreBuild(Graphics2D gd) {
 135  0
                 List<MosaicTile> lmt = pmf.getDB().getMosaicTiles(this.mid);
 136  
                 if (DEBUG)
 137  0
                         logger.info("Restoring " + lmt.size() + " tiles");
 138  0
                 for (; curRow<maxRow; curRow += tileHeight, curCol=0) {
 139  0
                         for (; curCol<maxCol; ) {
 140  0
                                 boolean found = false;
 141  0
                                 Iterator<MosaicTile> iter = lmt.iterator();
 142  0
                                 while (iter.hasNext()) {
 143  0
                                         MosaicTile mt = iter.next();
 144  0
                                         if (mt.getX() == curCol && mt.getY() == curRow) {
 145  0
                                                 int besti = getPicListIndex(mt.getPid());
 146  
                                                 if (DEBUG)
 147  0
                                                         logger.info("restore: besti = " + besti + " (" + picList.get(besti).getName() + ")");
 148  0
                                                 used[besti]++;
 149  0
                                                 BufferedImage mbi = pmf.getThumbNail(picList.get(besti), tileHeight).getImage();
 150  0
                                                 gd.drawImage(mbi, null, curCol, curRow);
 151  0
                                                 curCol += mbi.getWidth();
 152  0
                                                 setLastMosaicUpdate();
 153  0
                                                 found = true;
 154  0
                                                 break;
 155  
                                         }
 156  0
                                 }
 157  0
                                 if (!found)
 158  0
                                         return;
 159  0
                         }
 160  
                 }
 161  0
         }
 162  
         
 163  
         private        int        getPicListIndex(int pid) {
 164  0
                 for (int i=0; i<picList.size(); i++) {
 165  0
                         Pic p = picList.get(i);
 166  0
                         if (p.getPid() == pid)
 167  0
                                 return(i);
 168  
                 }
 169  0
                 return(-1);
 170  
         }
 171  
 }