I'm trying to load a bitmap in Android which I want to tile. I'm currently using the following in my view to display a bitmap:
canvas.drawBitmap(bitmap, srcRect, destRect, null)
I essentially want to use this bitmap as a background image in my app and would like to repeat the bitmap in both the X and Y directions.
I've seen the TileMode.REPEAT constant for the BitmapShader class but i am not sure if this is to be used for repeating the actual bitmap or is used for applying a filter to the bitmap.
You would do this in the xml instead of the java code. I haven't attempted this myself but I did find this example.
<xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/MainLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#drawable/backrepeat"
>
then in an xml called backrepeat.xml
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/back"
android:tileMode="repeat" />
reference
Figured out the code version:
BitmapDrawable TileMe = new BitmapDrawable(MyBitmap);
TileMe.setTileModeX(Shader.TileMode.REPEAT);
TileMe.setTileModeY(Shader.TileMode.REPEAT);
ImageView Item = new ImageView(this);
Item.setBackgroundDrawable(TileMe);
Then if you have a drawable to tile, this can be used instead to make the BitmapDrawable:
BitmapDrawable TileMe = new BitmapDrawable(BitmapFactory.decodeResource(getResources(), R.drawable.tile));
The backrepeat.xml above is buggy
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/tile"
android:tileMode="repeat"
android:dither="true" />
It seems that some people are interested in doing this in a View, at the onDraw method. The following code has worked for me:
bgTile = BitmapFactory.decodeResource(context.getResources(), R.drawable.bg_tile);
float left = 0, top = 0;
float bgTileWidth = bgTile.getWidth();
float bgTileHeight = bgTile.getHeight();
while (left < screenWidth) {
while (top < screenHeight) {
canvas.drawBitmap(bgTile, left, top, null);
top += bgTileHeight;
}
left += bgTileWidth;
top = 0;
}
<xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/MainLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#drawable/back"
android:tileMode="repeat"
>
This worked fine for me. I did not have to create the bitmap seperately. I used the tileMode attribute in the layout.
Just put this line of codes in the onCreate():-
final Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.actionbar_bg);
final BitmapDrawable bitmapDrawable = new BitmapDrawable(bmp);
bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
final ActionBar bar = getSupportActionBar();
bar.setBackgroundDrawable(bitmapDrawable);
If you want to repeat the background only vertically you can set the width of your layout to "wrap_content", whereas if you want to set the background to repeat horizontally set the height to "wrap_content". If both height and width are set to "fill_parent" then it will tile in the X and Y directions.
For example, the following code will repeat your background vertically:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="#drawable/news_detail_activity_bg">
</LinearLayout>
/* Tiled Layer Bitmap*/
public class TiledLayer {
private int cellWidth;
private int cellHeight;
private int yPosition = 0, xPosition = 0;
private int[][] grid;
private Image image;
private int[] tileXPositions;
private int[] tileYPositions;
private ArrayList animatedTiles;
private int numberOfTiles;
private int numberOfColumns;
private int numberOfRows;
private int gridColumns;
private int gridRows, width, height;
public TiledLayer(Image image, int columns, int rows, int tileWidth,
int tileHeight, int width, int height) {
this.grid = new int[columns][rows];
this.gridColumns = columns;
this.gridRows = rows;
this.width = columns * tileWidth;
this.height = rows * tileHeight;
this.animatedTiles = new ArrayList();
setStaticTileSet(image, tileWidth, tileHeight);
}
public void setStaticTileSet(Image image, int tileWidth, int tileHeight) {
this.image = image;
this.cellWidth = tileWidth;
this.cellHeight = tileHeight;
int columns = 64;//image.getWidth() / tileWidth;
int rows =40;// image.getHeight() / tileHeight;
this.tileXPositions = new int[columns];
int pos = 0;
for (int i = 0; i < columns; i++) {
this.tileXPositions[i] = pos;
pos += tileWidth;
}
this.tileYPositions = new int[rows];
pos = 0;
for (int i = 0; i < rows; i++) {
this.tileYPositions[i] = pos;
pos += tileHeight;
}
if (columns * rows < this.numberOfTiles) {
// clear the grid, when there are not as many tiles as in the
// previous set:
for (int i = 0; i < this.grid.length; i++) {
for (int j = 0; j < this.grid[i].length; j++) {
this.grid[i][j] = 0;
}
}
}
this.numberOfTiles = columns * rows;
this.numberOfColumns = columns;
this.numberOfRows = rows;
}
public int createAnimatedTile(int staticTileIndex) {
if (staticTileIndex >= this.numberOfTiles) {
throw new IllegalArgumentException("invalid static tile index: "
+ staticTileIndex + " (there are only ["
+ this.numberOfTiles + "] tiles available.");
}
this.animatedTiles.add(new Integer(staticTileIndex));
return -1 * (this.animatedTiles.size() - 1);
}
public void setAnimatedTile(int animatedTileIndex, int staticTileIndex) {
if (staticTileIndex >= this.numberOfTiles) {
}
int animatedIndex = (-1 * animatedTileIndex) - 1;
this.animatedTiles.set(animatedIndex, new Integer(staticTileIndex));
}
public int getAnimatedTile(int animatedTileIndex) {
int animatedIndex = (-1 * animatedTileIndex) - 1;
Integer animatedTile = (Integer) this.animatedTiles.get(animatedIndex);
return animatedTile.intValue();
}
public void setCell(int col, int row, int tileIndex) {
if (tileIndex >= this.numberOfTiles) {
throw new IllegalArgumentException("invalid static tile index: "
+ tileIndex + " (there are only [" + this.numberOfTiles
+ "] tiles available.");
}
this.grid[col][row] = tileIndex;
}
public int getCell(int col, int row) {
return this.grid[col][row];
}
public void fillCells(int col, int row, int numCols, int numRows,
int tileIndex) {
if (tileIndex >= this.numberOfTiles) {
throw new IllegalArgumentException("invalid static tile index: "
+ tileIndex + " (there are only [" + this.numberOfTiles
+ "] tiles available.");
}
int endCols = col + numCols;
int endRows = row + numRows;
for (int i = col; i < endCols; i++) {
for (int j = row; j < endRows; j++) {
this.grid[i][j] = tileIndex;
}
}
}
public final int getCellWidth() {
return this.cellWidth;
}
public final int getCellHeight() {
return this.cellHeight;
}
public final int getColumns() {
return this.gridColumns;
}
public final int getRows() {
return this.gridRows;
}
public final void paint(Graphics g) {
int clipX = 0;// g.getClipX();
int clipY = 0;// g.getClipY();
int clipWidth = width;// g.getClipWidth();
int clipHeight = height;// g.getClipHeight();
// jmt restore clip to previous state
int x = this.xPosition;
int y = this.yPosition;
int[][] gridTable = this.grid;
for (int i = 0; i < this.gridColumns; i++) {
int[] gridRow = gridTable[i];
for (int j = 0; j < gridRow.length; j++) {
int cellIndex = gridRow[j];
if (cellIndex != 0) {
// okay this cell needs to be rendered:
int tileIndex;
if (cellIndex < 0) {
Integer tile = (Integer) this.animatedTiles
.get((-1 * cellIndex) - 1);
tileIndex = tile.intValue() - 1;
} else {
tileIndex = cellIndex - 1;
}
// now draw the tile:
g.save(Canvas.CLIP_SAVE_FLAG);
// jmt: clear the screen
Rect r = new Rect(0, 0, cellWidth, cellHeight);
g.clipRect(r);
g.setClip(x, y, this.cellWidth, this.cellHeight);
int column = tileIndex % this.numberOfColumns;
int row = tileIndex / this.numberOfColumns;
int tileX = x - this.tileXPositions[column];
int tileY = y - this.tileYPositions[row];
g.drawImage(this.image, tileX, tileY);
g.restore();
}
y += this.cellHeight;
} // for each row
y = this.yPosition;
x += this.cellWidth;
} // for each column
// reset original clip:
g.setClip(clipX, clipY, clipWidth, clipHeight);
}
}
Related
I am currently working on zip animation to unlock android mobile screen. Changing background images is a expensive task and have not a smooth effect. I want a smooth effect in it. Any help please? Thanks
Try this:
The smooth effect makes use of Convolution Matrix:
Some image effects are better to implement using Convolution Matrix
method like: Gaussian Blur, Sharpening, Embossing, Smooth…
Check That Link to know more about Convolution Matrix or Another one
To do Convolution Matrix
import android.graphics.Bitmap;
import android.graphics.Color;
public class ConvolutionMatrix
{
public static final int SIZE = 3;
public double[][] Matrix;
public double Factor = 1;
public double Offset = 1;
public ConvolutionMatrix(int size) {
Matrix = new double[size][size];
}
public void setAll(double value) {
for (int x = 0; x < SIZE; ++x) {
for (int y = 0; y < SIZE; ++y) {
Matrix[x][y] = value;
}
}
}
public void applyConfig(double[][] config) {
for(int x = 0; x < SIZE; ++x) {
for(int y = 0; y < SIZE; ++y) {
Matrix[x][y] = config[x][y];
}
}
}
public static Bitmap computeConvolution3x3(Bitmap src, ConvolutionMatrix matrix) {
int width = src.getWidth();
int height = src.getHeight();
Bitmap result = Bitmap.createBitmap(width, height, src.getConfig());
int A, R, G, B;
int sumR, sumG, sumB;
int[][] pixels = new int[SIZE][SIZE];
for(int y = 0; y < height - 2; ++y) {
for(int x = 0; x < width - 2; ++x) {
// get pixel matrix
for(int i = 0; i < SIZE; ++i) {
for(int j = 0; j < SIZE; ++j) {
pixels[i][j] = src.getPixel(x + i, y + j);
}
}
// get alpha of center pixel
A = Color.alpha(pixels[1][1]);
// init color sum
sumR = sumG = sumB = 0;
// get sum of RGB on matrix
for(int i = 0; i < SIZE; ++i) {
for(int j = 0; j < SIZE; ++j) {
sumR += (Color.red(pixels[i][j]) * matrix.Matrix[i][j]);
sumG += (Color.green(pixels[i][j]) * matrix.Matrix[i][j]);
sumB += (Color.blue(pixels[i][j]) * matrix.Matrix[i][j]);
}
}
// get final Red
R = (int)(sumR / matrix.Factor + matrix.Offset);
if(R < 0) { R = 0; }
else if(R > 255) { R = 255; }
// get final Green
G = (int)(sumG / matrix.Factor + matrix.Offset);
if(G < 0) { G = 0; }
else if(G > 255) { G = 255; }
// get final Blue
B = (int)(sumB / matrix.Factor + matrix.Offset);
if(B < 0) { B = 0; }
else if(B > 255) { B = 255; }
// apply new pixel
result.setPixel(x + 1, y + 1, Color.argb(A, R, G, B));
}
}
// final image
return result;
}
}
Then to do Smooth effect
public static Bitmap smooth(Bitmap src, double value) {
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.setAll(1);
convMatrix.Matrix[1][1] = value;
convMatrix.Factor = value + 8;
convMatrix.Offset = 1;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
You can change values and get the smooth effect as you want.
That tutorial it's found HERE
I've searched for how to pixelate an image in android via code, the results are varied.
I've found libraries and tutorials on how to apply other effects found here: http://xjaphx.wordpress.com/learning/tutorials/
Can someone clear things up for me, what is the simplest way of pixelating an image on the fly in android
Also it would be handy if it was a function that I could how many rounds or how much I wanted the image pixelating.
Thank in advance.
The simplest way to pixelate the image would be to scale image down using "nearest neighbour" algorithm, and then scale up, using the same algorithm.
Filtering over the image trying to find an average takes much more time, but does not actually give any improvements in result quality, after all you do intentionally want your image distorted.
I have done this before in vb.net and its easily made into a function whose parameter can control how pixelated you want it.
The basic idea is to scan the image in section of blocks of X width and y height. for each block you find the average RGB value and set all those pixels to that color. the smaller the block size the less pixelated.
int avR,avB,avG; // store average of rgb
int pixel;
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
for(int x = 0; x < width; x+= pixelationAmount) { // do the whole image
for(int y = 0; y < height; y++ pixelationamount) {
avR = 0; avG = 0; avB =0;
for(int xx =x; xx <pixelationAmount;xx++){// YOU WILL WANT TO PUYT SOME OUT OF BOUNDS CHECKING HERE
for(int yy= y; yy <pixelationAmount;yy++){ // this is scanning the colors
pixel = src.getPixel(x, y);
avR += (int) (color.red(pixel);
avG+= (int) (color.green(pixel);
avB += (int) (color.blue(pixel);
}
}
avrR/= pixelationAmount^2; //divide all by the amount of samples taken to get an average
avrG/= pixelationAmount^2;
avrB/= pixelationAmount^2;
for(int xx =x; xx <pixelationAmount;xx++){// YOU WILL WANT TO PUYT SOME OUT OF BOUNDS CHECKING HERE
for(int yy= y; yy <pixelationAmount;yy++){ // this is going back over the block
bmOut.setPixel(xx, yy, Color.argb(255, avR, avG,avB)); //sets the block to the average color
}
}
}
}
sorry about the bad formatting (wrote it in notepad quickly) but thought it might give you a framework to make your own pixelate function
This is corrected of above algorithm that works:
Bitmap bmOut = Bitmap.createBitmap(OriginalBitmap.getWidth(),OriginalBitmap.getHeight(),OriginalBitmap.getConfig());
int pixelationAmount = 50; //you can change it!!
int width = OriginalBitmap.getWidth();
int height = OriginalBitmap.getHeight();
int avR,avB,avG; // store average of rgb
int pixel;
for(int x = 0; x < width; x+= pixelationAmount) { // do the whole image
for(int y = 0; y < height; y+= pixelationAmount) {
avR = 0; avG = 0; avB =0;
int bx = x + pixelationAmount;
int by = y + pixelationAmount;
if(by >= height) by = height;
if(bx >= width)bx = width;
for(int xx =x; xx < bx;xx++){// YOU WILL WANT TO PUYT SOME OUT OF BOUNDS CHECKING HERE
for(int yy= y; yy < by;yy++){ // this is scanning the colors
pixel = OriginalBitmap.getPixel(xx, yy);
avR += (int) (Color.red(pixel));
avG+= (int) (Color.green(pixel));
avB += (int) (Color.blue(pixel));
}
}
avR/= pixelationAmount^2; //divide all by the amount of samples taken to get an average
avG/= pixelationAmount^2;
avB/= pixelationAmount^2;
for(int xx =x; xx < bx;xx++)// YOU WILL WANT TO PUYT SOME OUT OF BOUNDS CHECKING HERE
for(int yy= y; yy <by;yy++){ // this is going back over the block
bmOut.setPixel(xx, yy, Color.argb(255, avR, avG,avB)); //sets the block to the average color
}
}
}
iv.setImageBitmap(bmOut);
anyway it was not what i was looking for
I have change previous algorithm completely and it really done something like mosaic filter!
the idea is to replace each block pixels with its below block pixels
use this function simply:
public void filter(){
Bitmap bmOut = Bitmap.createBitmap(OriginalBitmap.getWidth(),OriginalBitmap.getHeight(),OriginalBitmap.getConfig());
int pixelationAmount = 10;
Bitmap a = Bitmap.createBitmap(pixelationAmount,pixelationAmount,OriginalBitmap.getConfig());
Bitmap b = Bitmap.createBitmap(pixelationAmount,pixelationAmount,OriginalBitmap.getConfig());
int width = OriginalBitmap.getWidth();
int height = OriginalBitmap.getHeight();
int pixel;
int counter = 1;
int px = 0;int py = 0;int pbx=0;int pby=0;
for(int x = 0; x < width; x+= pixelationAmount) { // do the whole image
for(int y = 0; y < height; y+= pixelationAmount) {
int bx = x + pixelationAmount;
int by = y + pixelationAmount;
if(by >= height) by = height;
if(bx >= width)bx = width;
int xxx = -1;
int yyy = -1;
for(int xx =x; xx < bx;xx++){// YOU WILL WANT TO PUYT SOME OUT OF BOUNDS CHECKING HERE
xxx++;
yyy = -1;
for(int yy= y; yy < by;yy++){ // this is scanning the colors
yyy++;
pixel = OriginalBitmap.getPixel(xx, yy);
if(counter == 1)
{
a.setPixel(xxx, yyy, pixel);
px = x;//previous x
py = y;//previous y
pbx = bx;
pby = by;
}
else
b.setPixel(xxx, yyy, pixel);
}
}
counter++;
if(counter == 3)
{
int xxxx = -1;
int yyyy = -1;
for(int xx =x; xx < bx;xx++)
{
xxxx++;
yyyy = -1;
for(int yy= y; yy <by;yy++){
yyyy++;
bmOut.setPixel(xx, yy, b.getPixel(xxxx, yyyy));
}
}
for(int xx =px; xx < pbx;xx++)
{
for(int yy= py; yy <pby;yy++){
bmOut.setPixel(xx, yy, a.getPixel(xxxx, yyyy)); //sets the block to the average color
}
}
counter = 1;
}
}
}
image_view.setImageBitmap(bmOut);
}
This is the code I used:
ImageFilter is the parent class:
public abstract class ImageFilter {
protected int [] pixels;
protected int width;
protected int height;
public ImageFilter (int [] _pixels, int _width,int _height){
setPixels(_pixels,_width,_height);
}
public void setPixels(int [] _pixels, int _width,int _height){
pixels = _pixels;
width = _width;
height = _height;
}
/**
* a weighted Euclidean distance in RGB space
* #param c1
* #param c2
* #return
*/
public double colorDistance(int c1, int c2)
{
int red1 = Color.red(c1);
int red2 = Color.red(c2);
int rmean = (red1 + red2) >> 1;
int r = red1 - red2;
int g = Color.green(c1) - Color.green(c2);
int b = Color.blue(c1) - Color.blue(c2);
return Math.sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8));
}
public abstract int[] procImage();
}
public class PixelateFilter extends ImageFilter {
int pixelSize;
int[] colors;
/**
* #param _pixels
* #param _width
* #param _height
*/
public PixelateFilter(int[] _pixels, int _width, int _height) {
this(_pixels, _width, _height, 10);
}
public PixelateFilter(int[] _pixels, int _width, int _height, int _pixelSize) {
this(_pixels, _width, _height, _pixelSize, null);
}
public PixelateFilter(int[] _pixels, int _width, int _height, int _pixelSize, int[] _colors) {
super(_pixels, _width, _height);
pixelSize = _pixelSize;
colors = _colors;
}
/* (non-Javadoc)
* #see imageProcessing.ImageFilter#procImage()
*/
#Override
public int[] procImage() {
for (int i = 0; i < width; i += pixelSize) {
for (int j = 0; j < height; j += pixelSize) {
int rectColor = getRectColor(i, j);
fillRectColor(rectColor, i, j);
}
}
return pixels;
}
private int getRectColor(int col, int row) {
int r = 0, g = 0, b = 0;
int sum = 0;
for (int x = col; x < col + pixelSize; x++) {
for (int y = row; y < row + pixelSize; y++) {
int index = x + y * width;
if (index < width * height) {
int color = pixels[x + y * width];
r += Color.red(color);
g += Color.green(color);
b += Color.blue(color);
}
}
}
sum = pixelSize * pixelSize;
int newColor = Color.rgb(r / sum, g / sum, b / sum);
if (colors != null)
newColor = getBestMatch(newColor);
return newColor;
}
private int getBestMatch(int color) {
double diff = Double.MAX_VALUE;
int res = color;
for (int c : colors) {
double currDiff = colorDistance(color, c);
if (currDiff < diff) {
diff = currDiff;
res = c;
}
}
return res;
}
private void fillRectColor(int color, int col, int row) {
for (int x = col; x < col + pixelSize; x++) {
for (int y = row; y < row + pixelSize; y++) {
int index = x + y * width;
if (x < width && y < height && index < width * height) {
pixels[x + y * width] = color;
}
}
}
}
public static final Bitmap changeToPixelate(Bitmap bitmap, int pixelSize, int [] colors) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
PixelateFilter pixelateFilter = new PixelateFilter(pixels, width, height, pixelSize, colors);
int[] returnPixels = pixelateFilter.procImage();
Bitmap returnBitmap = Bitmap.createBitmap(returnPixels, width, height, Bitmap.Config.ARGB_8888);
return returnBitmap;
}
}
Here is how you use it:
int [] colors = new int [] { Color.BLACK,Color.WHITE,Color.BLUE,Color.CYAN,Color.RED};
final Bitmap bmOut = PixelateFilter.changeToPixelate(OriginalBitmap, pixelSize,colors);
I'm trying to implement adaptive thresholding algorithm by Derek Bradley using Android. But it is returning black pixels all the time. Here is my code snippet. Please suggest me about what should I do. Thanks in advance.
public static Bitmap GrayscaleToBin(Bitmap bm2)
{
Bitmap bm;
bm=bm2.copy(Config.ARGB_8888, true);
final int width = bm.getWidth();
final int height = bm.getHeight();
int[] pixels;
pixels = new int[width*height];
bm.getPixels(pixels,0,width,0,0,width,height);
//Bradley AdaptiveThrsholdging
int []intImg= new int[width*height];
int sum=0;
for(int i=0;i<width;++i){
sum=0;
for(int j=0;j<height;++j)
{
sum=sum+pixels[i+j*width];
if(i==0){intImg[i+j*width]=sum;}
else
{
intImg[i+j*width]= intImg[i-1+j*width]+sum;
}
}
}
int x1,x2,y1,y2=0,count=0;
int s=width >> 3;
int t=15;
for(int i=0;i<width;++i)
{
for(int j=0;j<height;++j)
{
x1=i-s/2;
x2=i+s/2;
y1=j-s/2;
y2=j+s/2;
if (x1 <0) x1 = 0;
if (x2>= width) x2 = width-1;
if (y1 <0) y1 = 0;
if (y2>= height) y2 = height-1;
count = (x2-x1) * (y2-y1);
sum = intImg [y2 * width + x2] -
intImg [y1 * width + x2] -
intImg [y2 * width + x1] +
intImg [y1 * width + x1];
if((pixels[i+j*width]*count)<=(sum*(100-t)/100))
{
pixels[i+j*width]=0;
}
else
{
pixels[i+j*width]=255;
}
}
}
/*---------------------------------------------------------------------------*/
bm.setPixels(pixels,0,width,0,0,width,height);
// Log.d("cdsfss","afterloop");
return bm;
}
After a Long struggle I have solved the issue with the following code.
public static Bitmap GrayscaleToBin(Bitmap bm2)
{
Bitmap bm;
bm=bm2.copy(Config.RGB_565, true);
final int width = bm.getWidth();
final int height = bm.getHeight();
int pixel1,pixel2,pixel3,pixel4,A,R;
int[] pixels;
pixels = new int[width*height];
bm.getPixels(pixels,0,width,0,0,width,height);
int size=width*height;
int s=width/8;
int s2=s>>1;
double t=0.15;
double it=1.0-t;
int []integral= new int[size];
int []threshold=new int[size];
int i,j,diff,x1,y1,x2,y2,ind1,ind2,ind3;
int sum=0;
int ind=0;
while(ind<size)
{
sum+=pixels[ind] & 0xFF;
integral[ind]=sum;
ind+=width;
}
x1=0;
for(i=1;i<width;++i)
{
sum=0;
ind=i;
ind3=ind-s2;
if(i>s)
{
x1=i-s;
}
diff=i-x1;
for(j=0;j<height;++j)
{
sum+=pixels[ind] & 0xFF;
integral[ind]=integral[(int)(ind-1)]+sum;
ind+=width;
if(i<s2)continue;
if(j<s2)continue;
y1=(j<s ? 0 : j-s);
ind1=y1*width;
ind2=j*width;
if (((pixels[ind3]&0xFF)*(diff * (j - y1))) < ((integral[(int)(ind2 + i)] - integral[(int)(ind1 + i)] - integral[(int)(ind2 + x1)] + integral[(int)(ind1 + x1)])*it)) {
threshold[ind3] = 0x00;
} else {
threshold[ind3] = 0xFFFFFF;
}
ind3 += width;
}
}
y1 = 0;
for( j = 0; j < height; ++j )
{
i = 0;
y2 =height- 1;
if( j <height- s2 )
{
i = width - s2;
y2 = j + s2;
}
ind = j * width + i;
if( j > s2 ) y1 = j - s2;
ind1 = y1 * width;
ind2 = y2 * width;
diff = y2 - y1;
for( ; i < width; ++i, ++ind )
{
x1 = ( i < s2 ? 0 : i - s2);
x2 = i + s2;
// check the border
if (x2 >= width) x2 = width - 1;
if (((pixels[ind]&0xFF)*((x2 - x1) * diff)) < ((integral[(int)(ind2 + x2)] - integral[(int)(ind1 + x2)] - integral[(int)(ind2 + x1)] + integral[(int)(ind1 + x1)])*it)) {
threshold[ind] = 0x00;
} else {
threshold[ind] = 0xFFFFFF;
}
}
}
/*-------------------------------
* --------------------------------------------*/
bm.setPixels(threshold,0,width,0,0,width,height);
return bm;
}
You can use Catalano Framework. There's an example using Bradley for Android in samples folder.
FastBitmap fb = new FastBitmap(bitmap);
fb.toGrayscale();
BradleyLocalThreshold bradley = new BradleyLocalThreshold();
bradley.applyInPlace(fb);
bitmap = fb.toBitmap();
I am developing a brick game here is the code
public class Sprite {
private static final int NO_COLUMNS = 12;
Bitmap bmp,bar,brick,scalebit;
GameView gameview;
int x,speedx=0,speedy=0;
int no_bricksperline;
private int currentFrame=0;
private int width;
private int height;
int brwidth;
int brheight;
int init=0;
float tempwidth;
String[][] bricks;
GameThread thread;
private int y;
Paint paint=new Paint();
private int barx;
private int bary;
#SuppressLint("FloatMath")
public Sprite(GameView gameview,GameThread thread,Bitmap bmp,Bitmap bar,Bitmap brick)
{
this.gameview=gameview;
this.bmp=bmp;
this.bar=bar;
this.brick=brick;
this.thread=thread;
this.no_bricksperline=gameview.getWidth()/brick.getWidth()-2;
bricks=new String[no_bricksperline][4];
brwidth=brick.getWidth();
brheight=brick.getHeight();
paint.setColor(Color.BLACK);
for (int i = 0; i < no_bricksperline; ++i)
for (int j = 0; j < 4; ++j)
bricks[i][j] = "B";
String strwidth=String.valueOf(((float)(bmp.getWidth())/NO_COLUMNS));
if(strwidth.contains("."))
{
scalebit=Bitmap.createScaledBitmap(bmp, (int)(Math.ceil(((float)bmp.getWidth())/NO_COLUMNS))*NO_COLUMNS, bmp.getHeight(), true);
}
else
{
scalebit=bmp;
}
this.width=scalebit.getWidth()/NO_COLUMNS;
this.bary=gameview.getHeight()-100;
this.height=scalebit.getHeight();
Random random=new Random();
x = random.nextInt(gameview.getWidth() - width);
y = random.nextInt(gameview.getHeight() - height)-100;
if(y<=100)
{
y=120;
}
speedx=random.nextInt(10)-5;
speedy=random.nextInt(10)-5;
}
public void update()
{
if(x>gameview.getWidth()-width-speedx || x+speedx<0)
{
speedx=-speedx;
}
if(y>gameview.getHeight()-height-speedy || y+speedy<0)
{
speedy=-speedy;
}
if(y+height >= bary-bar.getHeight()) {
if((x+width>barx-bar.getWidth()/2 && barx>x) || (x<barx+bar.getWidth()/2 && x>barx)) {
speedy=-speedy;
}
}
if(y>0 && y<=(5*brheight) && init==1)
{
if(x!=0){
int x1=x;
int y1=y;
if(x1>(no_bricksperline+1)*brwidth)
{
x1=(no_bricksperline)*brwidth;
}
if(x1<=brwidth)
{
x1=brwidth;
}
if(y1<=brheight)
{
y1=brheight;
}
if(y1>=(4*brheight) && y1<=(5*brheight))
{
y1=4*brheight;
}
int posi=(int)Math.floor(x1/brwidth)-1;
int posj=(int)Math.floor(y1/brheight)-1;
if(bricks[posi][posj]=="B")
{
bricks[posi][posj]="K";
speedy=-speedy;
}
}
}
if(y+height>bary+bar.getHeight())
{
}
x=x+speedx;
y=y+speedy;
currentFrame=++currentFrame%NO_COLUMNS;
}
#SuppressLint("DrawAllocation")
public void onDraw(Canvas canvas)
{
checkFinish();
update();
for (int i = 0; i < no_bricksperline; ++i){
for (int j = 0; j < 4; ++j) {
// ourHolder.lockCanvas();
if (bricks[i][j].contains("B"))
canvas.drawBitmap(brick, (i+1)*brick.getWidth(),(j+1)*brick.getHeight(),
null);
init=1;
}
}
int srcX=currentFrame*width;
int srcY=0;
Rect src=new Rect(srcX, srcY, srcX+width, srcY+height);
Rect dest=new Rect(x,y,x+width,y+width);
canvas.drawBitmap(scalebit,src,dest,null);
canvas.drawBitmap(bar, barx-bar.getWidth()/2, bary-bar.getHeight(),null);
}
private void checkFinish() {
int totalbricks=0;
for (int i = 0; i < no_bricksperline; ++i){
for (int j = 0; j < 4; ++j){
if(bricks[i][j] == "K"){
totalbricks++;
}
}
}
if(totalbricks==(no_bricksperline*4))
{
thread.setRunning(false);}
}
public void onTouch(MotionEvent event) {
barx= (int) event.getX();
}
}
the problem is bricks are displaying
When I use the brick image directly their are pixlated and also only 2 bricks are displaying. So I have write a logic to display min no of bricks
I have used some logic in my code
here is the code
String strwidth=String.valueOf(((float)(bmp.getWidth())/NO_COLUMNS));
if(strwidth.contains("."))
{
scalebit=Bitmap.createScaledBitmap(bmp, (int)(Math.ceil(((float)bmp.getWidth())/NO_COLUMNS))*NO_COLUMNS, bmp.getHeight(), true);
}
else
{
scalebit=bmp;
}
but there is a gap between walls and bricks. How can I make the bricks to occupy the entire screen.
use this
this.no_bricksperline=gameview.getWidth()/brick.getWidth();
instead of
this.no_bricksperline=gameview.getWidth()/brick.getWidth()-2;
If i have understood you correctly, your problem is the width of the bricks to be adjusted to fill the entire screen.
try to use this one
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
dispWidth=metrics.widthPixels;
//make the dispWidth your gameView width
use the imageview property
android:scaleType="..."
This question already has answers here:
Android Tile Bitmap
(8 answers)
Closed 8 years ago.
To draw landscapes, backgrounds with patterns etc, we used TiledLayer in J2ME. Is there an android counterpart for that. Does android provide an option to set such tiled patterns in the layout XML?
You can use this class as a equivalent "TiledLayer class of jme":
package net.obviam.walking;
import java.util.ArrayList;
import com.kilobolt.framework.Graphics;
import com.kilobolt.framework.Image;
import com.kilobolt.framework.implementation.AndroidImage;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Rect;
public class TiledLayer {
public static final int DIR_LEFT = 0;
public static final int DIR_RIGHT = 1;
public static final int DIR_UP = 2;
public static final int DIR_DOWN = 3;
private int cellWidth;
private int cellHeight;
private int yPosition = 0, xPosition = 0;
private int[][] grid;
private Image image;
private Bitmap tileArray[];
private int[] tileXPositions;
private int[] tileYPositions;
private ArrayList animatedTiles;
private int numberOfTiles;
private int numberOfColumns;
private int numberOfRows;
private int gridColumns;
private int gridRows, width, height;
int tileCounter;
public TiledLayer(Image image, int columns, int rows, int tileWidth,
int tileHeight, int width, int height) {
this.grid = new int[columns][rows];
this.gridColumns = columns;
this.gridRows = rows;
this.width = columns * tileWidth;
this.height = rows * tileHeight;
this.animatedTiles = new ArrayList();
this.cellWidth = tileWidth;
this.cellHeight = tileHeight;
int r = image.getHeight() / tileHeight;
int c = image.getWidth() / tileWidth;
tileArray = new Bitmap[(r * c) + 1];
setStaticTileSet(image, tileWidth, tileHeight);
}
public TiledLayer(Bitmap image, int columns, int rows, int tileWidth,
int tileHeight, int width, int height) {
this.grid = new int[columns][rows];
this.gridColumns = columns;
this.gridRows = rows;
this.width = columns * tileWidth;
this.height = rows * tileHeight;
this.animatedTiles = new ArrayList();
this.cellWidth = tileWidth;
this.cellHeight = tileHeight;
int r = image.getHeight() / tileHeight;
int c = image.getWidth() / tileWidth;
tileArray = new Bitmap[(r * c) + 1];
setStaticTileSet(image, tileWidth, tileHeight);
}
public void setStaticTileSet(Image image, int tileWidth, int tileHeight) {
tileArray[0] = Bitmap.createBitmap(tileWidth, tileHeight,
Config.ARGB_4444);
int rows = image.getHeight() / tileHeight;
int columns = image.getWidth() / tileWidth;
numberOfTiles = rows * columns;
for (int i = 0; i < rows; i++) {
yPosition = i * tileHeight;
for (int j = 0; j < columns; j++) {
xPosition = j * tileWidth;
tileCounter++;
tileArray[tileCounter] = Bitmap.createBitmap(
((AndroidImage) image).bitmap, xPosition, yPosition,
tileWidth, tileHeight);
}
}
if (gridColumns * gridRows < this.numberOfTiles) {
// clear the grid, when there are not as many tiles as in the
// previous set:
for (int i = 0; i < this.grid.length; i++) {
for (int j = 0; j < this.grid[i].length; j++) {
this.grid[i][j] = 0;
}
}
}
}
public void setStaticTileSet(Bitmap image, int tileWidth, int tileHeight) {
tileArray[0] = Bitmap.createBitmap(tileWidth, tileHeight,
Config.ARGB_4444);
int rows = image.getHeight() / tileHeight;
int columns = image.getWidth() / tileWidth;
numberOfTiles = rows * columns;
for (int i = 0; i < rows; i++) {
yPosition = i * tileHeight;
for (int j = 0; j < columns; j++) {
xPosition = j * tileWidth;
tileCounter++;
tileArray[tileCounter] = Bitmap.createBitmap(image, xPosition,
yPosition, tileWidth, tileHeight);
}
}
if (gridColumns * gridRows < this.numberOfTiles) {
// clear the grid, when there are not as many tiles as in the
// previous set:
for (int i = 0; i < this.grid.length; i++) {
for (int j = 0; j < this.grid[i].length; j++) {
this.grid[i][j] = 0;
}
}
}
}
public int createAnimatedTile(int staticTileIndex) {
if (staticTileIndex >= this.numberOfTiles) {
throw new IllegalArgumentException("invalid static tile index: "
+ staticTileIndex + " (there are only ["
+ this.numberOfTiles + "] tiles available.");
}
this.animatedTiles.add(new Integer(staticTileIndex));
return -1 * (this.animatedTiles.size() - 1);
}
public void setAnimatedTile(int animatedTileIndex, int staticTileIndex) {
if (staticTileIndex >= this.numberOfTiles) {
}
int animatedIndex = (-1 * animatedTileIndex) - 1;
this.animatedTiles.set(animatedIndex, new Integer(staticTileIndex));
}
public int getAnimatedTile(int animatedTileIndex) {
int animatedIndex = (-1 * animatedTileIndex) - 1;
Integer animatedTile = (Integer) this.animatedTiles.get(animatedIndex);
return animatedTile.intValue();
}
public void setCell(int col, int row, int tileIndex) {
if (tileIndex >= this.numberOfTiles) {
throw new IllegalArgumentException("invalid static tile index: "
+ tileIndex + " (there are only [" + this.numberOfTiles
+ "] tiles available.");
}
this.grid[col][row] = tileIndex;
}
public int getCell(int col, int row) {
return this.grid[col][row];
}
public boolean checkTileCollision(Sprite sp, int dir, int speed) {
int curRow, curCollumn;
int leftTile = 0, rightTile = 0, upTile = 0, downTile = 0;
curRow = sp.getY() / cellHeight;
curCollumn = sp.getX() / cellWidth;
leftTile = grid[curCollumn - 1][curRow];
rightTile = grid[curCollumn + 1][curRow];
upTile = grid[curCollumn][curRow - 1];
downTile = grid[curCollumn][curRow + 1];
if (dir == DIR_RIGHT
&& (sp.getX() + sp.getWidth() + speed) <= (curCollumn + 1)
* cellWidth)
return false;
else if (dir == DIR_RIGHT
&& ((sp.getX() + sp.getWidth() + speed)) > (curCollumn + 1)
* cellWidth && rightTile != 1)
return true;
else if (dir == DIR_LEFT
&& (sp.getX() - speed) >= (curCollumn) * cellWidth)
return false;
else if (dir == DIR_LEFT
&& (sp.getX() - speed) < (curCollumn) * cellWidth
&& leftTile != 1)
return true;
else if (dir == DIR_UP && (sp.getY() - speed) >= (curRow) * cellHeight)
return false;
else if (dir == DIR_UP && (sp.getY() - speed) < (curRow) * cellHeight
&& upTile != 1)
return true;
else if (dir == DIR_DOWN
&& (sp.getY() + sp.getHeight() + speed) <= (curRow + 1)
* cellHeight)
return false;
else if (dir == DIR_DOWN
&& (sp.getY() + sp.getHeight() + speed) > (curRow + 1)
* cellHeight && downTile != 1)
return true;
else
return false;
}
public void fillCells(int col, int row, int numCols, int numRows,
int tileIndex) {
if (tileIndex >= this.numberOfTiles) {
throw new IllegalArgumentException("invalid static tile index: "
+ tileIndex + " (there are only [" + this.numberOfTiles
+ "] tiles available.");
}
int endCols = col + numCols;
int endRows = row + numRows;
for (int i = col; i < endCols; i++) {
for (int j = row; j < endRows; j++) {
this.grid[i][j] = tileIndex;
}
}
}
public final int getCellWidth() {
return this.cellWidth;
}
public final int getCellHeight() {
return this.cellHeight;
}
public final int getColumns() {
return this.gridColumns;
}
public final int getRows() {
return this.gridRows;
}
public final void paint(Graphics g) {
for (int i = 0; i < this.gridRows; i++) {
for (int j = 0; j < this.gridColumns; j++) {
Bitmap bmp = tileArray[grid[j][i]];
g.drawImage(bmp, j * cellWidth, i * cellHeight);
}
}
}
public final void paint(Canvas c) {
for (int i = 0; i < this.gridRows; i++) {
for (int j = 0; j < this.gridColumns; j++) {
Bitmap bmp = tileArray[grid[j][i]];
c.drawBitmap(bmp, j * cellWidth, i * cellHeight, null);
// g.drawImage(bmp, j*cellWidth,i*cellHeight);
}
}
}
}