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.