| 60 |
60 |
}
|
| 61 |
61 |
}
|
| 62 |
62 |
|
|
63 |
private int mCreatedBufSize;
|
|
64 |
|
| 63 |
65 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 64 |
66 |
|
| 65 |
67 |
private BandagedCreatorWorkerThread()
|
| ... | ... | |
| 116 |
118 |
|
| 117 |
119 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 118 |
120 |
|
| 119 |
|
private boolean containsBlackness(byte[] tmp, int width)
|
|
121 |
private int firstBlackPixel(byte[] tmp, int width)
|
| 120 |
122 |
{
|
| 121 |
123 |
for(int i=0; i<width; i++)
|
| 122 |
124 |
{
|
| 123 |
|
if( tmp[4*i]==0 && tmp[4*i+3]==-1 ) return true;
|
|
125 |
if( tmp[4*i]==0 && tmp[4*i+3]==-1 ) return i;
|
|
126 |
}
|
|
127 |
|
|
128 |
return -1;
|
|
129 |
}
|
|
130 |
|
|
131 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
132 |
|
|
133 |
private int lastBlackPixel(byte[] tmp, int width)
|
|
134 |
{
|
|
135 |
for(int i=width-1; i>=0; i--)
|
|
136 |
{
|
|
137 |
if( tmp[4*i]==0 && tmp[4*i+3]==-1 ) return i;
|
| 124 |
138 |
}
|
| 125 |
139 |
|
| 126 |
|
return false;
|
|
140 |
return -1;
|
| 127 |
141 |
}
|
| 128 |
142 |
|
| 129 |
143 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| ... | ... | |
| 137 |
151 |
buf.position(i*wBytes);
|
| 138 |
152 |
buf.get(tmp);
|
| 139 |
153 |
|
| 140 |
|
if( containsBlackness(tmp,width) ) return i;
|
|
154 |
if( firstBlackPixel(tmp,width)>=0 ) return i;
|
| 141 |
155 |
}
|
| 142 |
156 |
|
| 143 |
157 |
return 0;
|
| ... | ... | |
| 154 |
168 |
buf.position(i*wBytes);
|
| 155 |
169 |
buf.get(tmp);
|
| 156 |
170 |
|
| 157 |
|
if( containsBlackness(tmp,width) ) return i;
|
|
171 |
if( firstBlackPixel(tmp,width)>=0 ) return i;
|
| 158 |
172 |
}
|
| 159 |
173 |
|
| 160 |
174 |
return width-1;
|
| 161 |
175 |
}
|
| 162 |
176 |
|
| 163 |
177 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 164 |
|
// GL uses a coordinate system from mathematics; i.e. (0,0) is in the lower-left corner. 2D stuff
|
| 165 |
|
// has the origin on the upper-left corner; we have to flip our bitmap upside down!
|
| 166 |
|
//
|
| 167 |
|
// We also need to figure out the topmost and bottommost rows where the object starts and cut out
|
| 168 |
|
// a square section from the 'input' so that the object is vertically centralized.
|
| 169 |
178 |
|
| 170 |
|
private ByteBuffer adjustBuffer(ByteBuffer input, byte[] tmp, int width, int height)
|
|
179 |
private int computeLeftColumn(ByteBuffer buf, byte[] tmp, int width, int firstrow, int lastrow)
|
| 171 |
180 |
{
|
| 172 |
181 |
int wBytes = 4*width;
|
|
182 |
int currentBest = width;
|
| 173 |
183 |
|
| 174 |
|
ByteBuffer output = ByteBuffer.allocateDirect(wBytes*width);
|
| 175 |
|
output.order(ByteOrder.LITTLE_ENDIAN);
|
| 176 |
|
|
| 177 |
|
int firstRow = computeFirstRow(input,tmp,width,height);
|
| 178 |
|
int lastRow = computeLastRow(input,tmp,width,height);
|
| 179 |
|
int startRow = (firstRow+lastRow+width)/2;
|
| 180 |
|
|
| 181 |
|
for(int i=0; i<width; i++)
|
|
184 |
for(int i=firstrow; i<lastrow; i++)
|
| 182 |
185 |
{
|
| 183 |
|
input.position((startRow-i)*wBytes);
|
| 184 |
|
input.get(tmp);
|
| 185 |
|
output.position(i*wBytes);
|
| 186 |
|
output.put(tmp);
|
|
186 |
buf.position(i*wBytes);
|
|
187 |
buf.get(tmp);
|
|
188 |
|
|
189 |
int pixel = firstBlackPixel(tmp,width);
|
|
190 |
if( pixel>=0 && pixel<currentBest ) currentBest = pixel;
|
| 187 |
191 |
}
|
| 188 |
192 |
|
| 189 |
|
output.rewind();
|
| 190 |
|
return output;
|
|
193 |
return currentBest;
|
| 191 |
194 |
}
|
| 192 |
195 |
|
| 193 |
196 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 194 |
197 |
|
| 195 |
|
private void replaceColor(byte[] tmp, int index, int numColors)
|
|
198 |
private int computeRightColumn(ByteBuffer buf, byte[] tmp, int width, int firstrow, int lastrow)
|
| 196 |
199 |
{
|
| 197 |
|
byte A = (byte)0xab;
|
| 198 |
|
int CUTOFF = 100;
|
|
200 |
int wBytes = 4*width;
|
|
201 |
int currentBest = 0;
|
| 199 |
202 |
|
| 200 |
|
switch(numColors)
|
|
203 |
for(int i=firstrow; i<lastrow; i++)
|
| 201 |
204 |
{
|
| 202 |
|
case 4: if( tmp[index+1]==0 ) { tmp[index]=A; tmp[index+1]=0; tmp[index+2]=0; }
|
| 203 |
|
else
|
| 204 |
|
{
|
| 205 |
|
if( tmp[index]==tmp[index+1] )
|
| 206 |
|
{
|
| 207 |
|
if( tmp[index]<0 || tmp[index]>CUTOFF ) { tmp[index]=A; tmp[index+1]=A; tmp[index+2]=0; }
|
| 208 |
|
}
|
| 209 |
|
else { tmp[index]=0; tmp[index+1]=0; tmp[index+2]=A; }
|
| 210 |
|
}
|
| 211 |
|
break;
|
| 212 |
|
case 6: if( tmp[index+2]!=0 )
|
| 213 |
|
{
|
| 214 |
|
if( tmp[index]==0 ) { tmp[index]=0; tmp[index+1]=0; tmp[index+2]=A; }
|
| 215 |
|
}
|
| 216 |
|
else
|
| 217 |
|
{
|
| 218 |
|
if( tmp[index]==tmp[index+1] ) { tmp[index]=A; tmp[index+1]=A; tmp[index+2]=0; }
|
| 219 |
|
else { tmp[index]=A; tmp[index+1]=0; tmp[index+2]=0; }
|
| 220 |
|
}
|
| 221 |
|
break;
|
| 222 |
|
case 8: if( tmp[index+2]!=0 )
|
| 223 |
|
{
|
| 224 |
|
if( tmp[index+1]==0 ) { tmp[index]=A; tmp[index+1]=0; tmp[index+2]=0; }
|
| 225 |
|
}
|
| 226 |
|
else
|
| 227 |
|
{
|
| 228 |
|
if( tmp[index+1]==0 ) { tmp[index]=0; tmp[index+1]=0; tmp[index+2]=A; }
|
| 229 |
|
else
|
| 230 |
|
{
|
| 231 |
|
if( tmp[index]==tmp[index+1] ) { tmp[index]=A; tmp[index+1]=A; tmp[index+2]=0; }
|
| 232 |
|
else { tmp[index]=0; tmp[index+1]=A; tmp[index+2]=0; }
|
| 233 |
|
}
|
| 234 |
|
}
|
| 235 |
|
break;
|
| 236 |
|
|
| 237 |
|
case 12:if( tmp[index+2]==0 )
|
| 238 |
|
{
|
| 239 |
|
if( tmp[index+1]==0 ) {tmp[index]=A; tmp[index+1]=0; tmp[index+2]=0;}
|
| 240 |
|
else {tmp[index]=0; tmp[index+1]=A; tmp[index+2]=0;}
|
| 241 |
|
}
|
| 242 |
|
else
|
| 243 |
|
{
|
| 244 |
|
if( tmp[index]==tmp[index+1] )
|
| 245 |
|
{
|
| 246 |
|
if( tmp[index]<0 || tmp[index]>CUTOFF ) {tmp[index]=A; tmp[index+1]=A; tmp[index+2]=0;}
|
| 247 |
|
}
|
| 248 |
|
else {tmp[index]=0; tmp[index+1]=0; tmp[index+2]=A;}
|
| 249 |
|
}
|
| 250 |
|
break;
|
|
205 |
buf.position(i*wBytes);
|
|
206 |
buf.get(tmp);
|
|
207 |
|
|
208 |
int pixel = lastBlackPixel(tmp,width);
|
|
209 |
if( pixel>=0 && pixel>currentBest ) currentBest = pixel;
|
| 251 |
210 |
}
|
|
211 |
|
|
212 |
return currentBest;
|
| 252 |
213 |
}
|
| 253 |
214 |
|
| 254 |
215 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
216 |
// GL uses a coordinate system from mathematics; i.e. (0,0) is in the lower-left corner. 2D stuff
|
|
217 |
// has the origin on the upper-left corner; we have to flip our bitmap upside down!
|
|
218 |
//
|
|
219 |
// We also need to figure out the topmost and bottommost rows where the object starts and cut out
|
|
220 |
// a square section from the 'input' so that the object is vertically centralized.
|
| 255 |
221 |
|
| 256 |
|
private ByteBuffer replaceColors(ByteBuffer input, byte[] tmp, int size, int numColors)
|
|
222 |
private ByteBuffer adjustBuffer(ByteBuffer input, byte[] tmp, int width, int height)
|
| 257 |
223 |
{
|
| 258 |
|
int marker = (int)(255*BandagedCreatorRenderer.BRIGHTNESS);
|
| 259 |
|
int wBytes = 4*size;
|
| 260 |
|
|
| 261 |
|
ByteBuffer output = ByteBuffer.allocateDirect(wBytes*size);
|
|
224 |
int firstRow = computeFirstRow(input,tmp,width,height);
|
|
225 |
int lastRow = computeLastRow(input,tmp,width,height);
|
|
226 |
int leftColumn = computeLeftColumn(input,tmp,width,firstRow,lastRow);
|
|
227 |
int rightColumn= computeRightColumn(input,tmp,width,firstRow,lastRow);
|
|
228 |
|
|
229 |
int rowHeight = lastRow-firstRow;
|
|
230 |
int colWidth = rightColumn-leftColumn;
|
|
231 |
int size = Math.max(rowHeight,colWidth);
|
|
232 |
size = (int)(1.1f*size);
|
|
233 |
int half = size/2;
|
|
234 |
int centerX = (leftColumn+rightColumn)/2;
|
|
235 |
int centerY = (firstRow+lastRow)/2;
|
|
236 |
int sL=size, sR=size, sT=size, sB=size;
|
|
237 |
|
|
238 |
if( centerX-half< 0 )
|
|
239 |
{
|
|
240 |
android.util.Log.e("D", "buffer encroaches on the left! centerX="+centerX+" centerY="+centerY+" size="+size);
|
|
241 |
sL = 2*centerX;
|
|
242 |
}
|
|
243 |
if( centerX+half>width )
|
|
244 |
{
|
|
245 |
android.util.Log.e("D", "buffer encroaches on the right! centerX="+centerX+" centerY="+centerY+" size="+size);
|
|
246 |
sR = 2*(width-centerX);
|
|
247 |
}
|
|
248 |
if( centerY-half< 0 )
|
|
249 |
{
|
|
250 |
android.util.Log.e("D", "buffer encroaches on the top! centerX="+centerX+" centerY="+centerY+" size="+size);
|
|
251 |
sT = 2*centerY;
|
|
252 |
}
|
|
253 |
if( centerY+half>height)
|
|
254 |
{
|
|
255 |
android.util.Log.e("D", "buffer encroaches on the bottom! centerX="+centerX+" centerY="+centerY+" size="+size);
|
|
256 |
sB = 2*(height-centerY);
|
|
257 |
}
|
|
258 |
/*
|
|
259 |
if( sL==size && sR==size && sT==size && sB==size )
|
|
260 |
{
|
|
261 |
android.util.Log.e("D", "EVERYTHING ALL RIGHT centerX="+centerX+" centerY="+centerY+" size="+size);
|
|
262 |
}
|
|
263 |
*/
|
|
264 |
int minH = Math.min(sL,sR);
|
|
265 |
int minV = Math.min(sT,sB);
|
|
266 |
mCreatedBufSize = Math.min(minH,minV);
|
|
267 |
half = mCreatedBufSize/2;
|
|
268 |
int wBytes = 4*mCreatedBufSize;
|
|
269 |
ByteBuffer output = ByteBuffer.allocateDirect(wBytes*mCreatedBufSize);
|
| 262 |
270 |
output.order(ByteOrder.LITTLE_ENDIAN);
|
|
271 |
int startRow = centerY+half;
|
|
272 |
int distR = width-centerX-half;
|
| 263 |
273 |
|
| 264 |
|
for(int i=0; i<size; i++)
|
|
274 |
for(int i=0; i<mCreatedBufSize; i++)
|
| 265 |
275 |
{
|
| 266 |
|
input.position(i*wBytes);
|
| 267 |
|
input.get(tmp);
|
| 268 |
|
|
| 269 |
|
for(int j=0; j<size; j++)
|
| 270 |
|
{
|
| 271 |
|
if( tmp[4*j]==marker && tmp[4*j+1]==marker && tmp[4*j+2]==marker )
|
| 272 |
|
{
|
| 273 |
|
tmp[4*j ]=0;
|
| 274 |
|
tmp[4*j+1]=0;
|
| 275 |
|
tmp[4*j+2]=0;
|
| 276 |
|
tmp[4*j+3]=0;
|
| 277 |
|
}
|
| 278 |
|
else if( tmp[4*j]!=0 || tmp[4*j+1]!=0 || tmp[4*j+2]!=0 ) replaceColor(tmp,4*j,numColors);
|
| 279 |
|
}
|
| 280 |
|
|
|
276 |
input.position((startRow-i)*4*width + 4*distR );
|
|
277 |
input.get(tmp,0,wBytes);
|
| 281 |
278 |
output.position(i*wBytes);
|
| 282 |
|
output.put(tmp);
|
|
279 |
output.put(tmp,0,wBytes);
|
| 283 |
280 |
}
|
| 284 |
281 |
|
| 285 |
282 |
output.rewind();
|
| ... | ... | |
| 290 |
287 |
|
| 291 |
288 |
private void process(WorkLoad load)
|
| 292 |
289 |
{
|
| 293 |
|
int width = load.width;
|
| 294 |
|
int height= load.height;
|
|
290 |
int width = load.width;
|
|
291 |
int height = load.height;
|
| 295 |
292 |
|
| 296 |
293 |
byte[] tmp = new byte[4*width];
|
| 297 |
294 |
ByteBuffer bufSquare = adjustBuffer(load.buffer,tmp,width,height);
|
| 298 |
|
// ByteBuffer bufTransp = replaceColors(bufSquare,tmp,width,load.numColors);
|
| 299 |
|
|
| 300 |
295 |
final String filename = load.filename;
|
| 301 |
296 |
BufferedOutputStream bos =null;
|
| 302 |
297 |
final Activity act = mWeakAct.get();
|
| ... | ... | |
| 304 |
299 |
try
|
| 305 |
300 |
{
|
| 306 |
301 |
bos = new BufferedOutputStream(new FileOutputStream(filename));
|
| 307 |
|
Bitmap bmp = Bitmap.createBitmap( width, width, Bitmap.Config.ARGB_8888);
|
|
302 |
Bitmap bmp = Bitmap.createBitmap( mCreatedBufSize, mCreatedBufSize, Bitmap.Config.ARGB_8888);
|
| 308 |
303 |
bmp.copyPixelsFromBuffer(bufSquare);
|
| 309 |
304 |
bmp.compress(Bitmap.CompressFormat.PNG, 90, bos);
|
| 310 |
305 |
|
Improve icon creation.