1
2
3
4
5
6
7
8 package com.buckosoft.PicMan.business.mosaic.engine;
9
10 import java.awt.Color;
11 import java.awt.Graphics2D;
12 import java.awt.image.BufferedImage;
13 import java.util.Iterator;
14 import java.util.List;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18
19 import com.buckosoft.PicMan.business.mosaic.MosaicEngine;
20 import com.buckosoft.PicMan.domain.MosaicTile;
21 import com.buckosoft.PicMan.domain.Pic;
22
23
24
25
26
27
28
29
30
31 public class HSVRibbon extends MosaicEngine {
32 private static final boolean DEBUG = true;
33 private final Log logger = LogFactory.getLog(getClass());
34
35 private int mosaicId = 2;
36 private int curRow = 0;
37 private int[] curCols;
38 private int curCol;
39 private int maxRow;
40 private int maxCol;
41 private int p;
42 private List<Pic> picList;
43 private String info = "N/A";
44 private int[] used;
45 private int tileRows;
46 private String buildStep = "Idle";
47 private int pass = -1;
48
49
50
51
52 public String getStatus() {
53 StringBuilder sb = new StringBuilder();
54 sb.append(buildStep);
55 sb.append(": pass=");
56 sb.append(pass);
57 if (!buildStep.equals("Calc")) {
58 sb.append(" curRow = ");
59 sb.append(curRow);
60 sb.append(" curCol = ");
61 sb.append(curCol);
62 }
63 sb.append(" p=");
64 sb.append(p);
65 return(sb.toString());
66 }
67
68
69
70
71 public String getInfo() {
72 return(info);
73 }
74
75 protected boolean _build() {
76 Graphics2D gd = bi.createGraphics();
77
78
79 picList = pmf.getDB().getPics(this.mosaicSet, 75);
80 if (DEBUG)
81 logger.info("Working from " + picList.size() + " pics");
82 maxRow = this.masterPic.getHeight();
83 maxCol = this.masterPic.getWidth();
84 tileRows = maxRow / tileHeight;
85 if (tileRows * tileHeight < maxRow)
86 tileRows++;
87 curCols = new int[tileRows];
88
89 float[][] rate = new float[tileRows][picList.size()];
90 used = new int[picList.size()];
91 info = "tileRows=" + tileRows + " maxCol=" + maxCol + " pics=" + picList.size();
92 if (DEBUG)
93 logger.info("tileRows=" + tileRows + " rowHeight=" + tileHeight);
94 restoreBuild(gd);
95 boolean workDone = true;
96 float[] mpxHsb = new float[3];
97 float[] ppxHsb = new float[3];
98 while (workDone) {
99 pass++;
100 workDone = false;
101 BufferedImage mbi;
102 int x,y;
103 buildStep = "Calc";
104 for (p=0; p<picList.size(); p++) {
105 mbi = pmf.getMosaicThumbNail(picList.get(p), tileHeight).getImage();
106 for (curRow=0; curRow<tileRows; curRow++) {
107 curCol = curCols[curRow];
108 int cr = curRow * tileHeight;
109
110
111
112
113 if (curCol < maxCol) {
114 workDone = true;
115
116 rate[curRow][p] = used[p];
117 rate[curRow][p] = 0;
118 for (x=0; x<mbi.getWidth(); x++) {
119 for (y=0; y<mbi.getHeight(); y++) {
120 int mpx = mbi.getRGB(x, y);
121 int ppx;
122 if (x+curCol >= bi.getWidth() || y+cr >= bi.getHeight())
123 ppx = mpx;
124 else
125 ppx = bi.getRGB(x+curCol, y+cr);
126
127 Color.RGBtoHSB((mpx>>16) & 0xFF, (mpx>>8) & 0xFF, mpx&0xFF, mpxHsb);
128 Color.RGBtoHSB((ppx>>16) & 0xFF, (ppx>>8) & 0xFF, ppx&0xFF, ppxHsb);
129 if (ppxHsb[0] > mpxHsb[0]) ppxHsb[0] += 1.0;
130 rate[curRow][p] += Math.abs(mpxHsb[0] - ppxHsb[0]);
131 rate[curRow][p] += Math.abs(mpxHsb[0] - ppxHsb[0]);
132 rate[curRow][p] += Math.abs(mpxHsb[0] - ppxHsb[0]);
133
134
135
136
137 }
138 }
139
140
141 rate[curRow][p] /= mbi.getWidth();
142
143 }
144 }
145 }
146 buildStep = "Draw";
147 for (curRow=0; curRow<tileRows; curRow++) {
148 curCol = curCols[curRow];
149 int cr = curRow * tileHeight;
150 if (curCol >= maxCol)
151 continue;
152 float best = Float.MAX_VALUE;
153 int besti = -1;
154 int besti2 = -1;
155 for (x=0; x<rate.length; x++) {
156 if (rate[curRow][x] < best) {
157 besti2 = besti;
158 best = rate[curRow][x];
159 besti = x;
160 }
161 }
162 p = besti;
163 if (DEBUG) {
164 if (besti == -1)
165 logger.info("row=" + curRow + " besti == -1");
166 else
167 logger.info("besti = " + besti + " (" + picList.get(besti).getName() + ") = " + rate[curRow][besti]);
168 if (besti2 == -1)
169 logger.info("row=" + curRow + " besti2 == -1");
170 else
171 logger.info("besti2 = " + besti2 + " (" + picList.get(besti2).getName() + ") = " + rate[curRow][besti2]);
172 }
173 used[besti]++;
174 mbi = pmf.getThumbNail(picList.get(besti), tileHeight).getImage();
175 MosaicTile tile = new MosaicTile(mosaicId, picList.get(besti).getPid(), curCol, cr, mbi.getWidth(), mbi.getHeight());
176 pmf.getDB().storeMosaicTile(tile);
177 gd.drawImage(mbi, null, curCol, cr);
178 curCols[curRow] += mbi.getWidth();
179 setLastMosaicUpdate();
180 }
181 }
182 buildStep = "Done";
183 return(false);
184 }
185
186 private void restoreBuild(Graphics2D gd) {
187 List<MosaicTile> lmt = pmf.getDB().getMosaicTiles(mosaicId);
188 if (DEBUG)
189 logger.info("Restoring " + lmt.size() + " tiles");
190 boolean workDone = true;
191 buildStep = "Restore";
192 while (workDone) {
193 workDone = false;
194 pass++;
195 updateRestoreStatus();
196 for (curRow=0; curRow<tileRows; curRow++) {
197 curCol = curCols[curRow];
198 int cr = curRow * tileHeight;
199 Iterator<MosaicTile> iter = lmt.iterator();
200 while (iter.hasNext()) {
201 MosaicTile mt = iter.next();
202 if (mt.getX() == curCol && mt.getY() == cr) {
203 int besti = getPicListIndex(mt.getPid());
204 if (DEBUG)
205 logger.info("restore: besti = " + besti + " (" + picList.get(besti).getName() + ")");
206 used[besti]++;
207 BufferedImage mbi = pmf.getThumbNail(picList.get(besti), tileHeight).getImage();
208 gd.drawImage(mbi, null, curCol, cr);
209 curCols[curRow] += mbi.getWidth();
210 setLastMosaicUpdate();
211 workDone = true;
212 break;
213 }
214 }
215 }
216 }
217 }
218
219 private void updateRestoreStatus() {
220 buildStep = "Restore";
221 }
222
223 private int getPicListIndex(int pid) {
224 for (int i=0; i<picList.size(); i++) {
225 Pic p = picList.get(i);
226 if (p.getPid() == pid)
227 return(i);
228 }
229 return(-1);
230 }
231 }