I've divide my screen up into rects, but I'm using a a for loop so I'm not storing the rects there getting remade each time. How would I store them in like an array?
public void drawGrid() {
//android.os.Debug.waitForDebugger();
int height,width;
int column,row;
int maxColumn,maxRow;
maxColumn = 4;
maxRow = 4;
column = 0;
row = 0;
height = c.getHeight()/maxRow;
width = c.getWidth()/maxColumn;
Paint pg = new Paint();
Rect[] test[];
for(int i = 0;i < 5; i++) {
int srcX = column * width;
int srcY = row * height;
Rect src =new Rect(srcX,srcY,srcX + width, srcY +height);
pg.setColor(Color.WHITE);
pg.setStyle(Paint.Style.STROKE);
pg.setStrokeWidth(5);
c.drawRect(src, pg);
if (column == maxColumn && row == maxRow){
i = 5;
} else {i=0;}
if (column == maxColumn){
row = row + 1;
column = 0;
} else {column = column + 1;}
}
}
Allocate them in advance, so that you're not instantiating objects during a drawing operation. So whenever you determine the number of rects that you'll need (i.e. if it's always the same, initialize them in the constructor). Something like this:
Rect[] rects = new Rect[rectCount];
for(int i = 0; i < rectCount; i++) rects[i] = new Rect();
Then, in your drawing loop, use:
rects[i].set(srcX, srcY, srcX + width, srcY + height);
You should avoid allocating objects during a draw operation whenever possible.
EDIT: For a 2D array:
Rect[][] rects = new Rect[rowCount][colCount];
for(int i = 0; i < rowCount; i++) {
for(int j = 0; j < colCount; j++) {
rects[i][j] = new Rect();
}
}
Then in the loop, it's the same thing:
rects[row][col].set(srcX, srcY, srcX + width, srcY + height);
Rect rectArray[] = new Rect[5];
Then inside the loop:
rectArray[i] = new Rect(srcX,srcY,srcX + width, srcY +height);
Are you always going to have a fixed number of Rectangles?
You might want to consider an Array List?
ArrayList<Rect> rects = new ArrayList<Rect>();
rects.add(new Rect(srcX,srcY,srcX + width, srcY +height));
You can do loads of useful stuff easily with these things, here are some examples:
http://javarevisited.blogspot.com.es/2011/05/example-of-arraylist-in-java-tutorial.html
Related
I tried to make my own implementation of Otsu. I already read some source code from java and some sites that explains the formula and tried to implement it. I want to share this to ask if anyone can help me or at least tell about what can I do or improve.
I already coded get width, height and the background and foreground weight, mean, variance, and within class variance.
Note that I have not implemented how to set or find the exact threshold or even change the picture to black-white(binarize) using within class variance. If you can help me, feel welcome to. I also see some java codes that has treshhold = i or treshhold = t but I can't see how they made the image to black-white.
Here is my code:
Otsu.java
Bitmap tempImg = (Bitmap) original;
Bitmap OImg = Bitmap.createBitmap(tempImg.getWidth(), tempImg.getHeight(), tempImg.getConfig());
int width = tempImg.getWidth();
int height = tempImg.getHeight();
int A, R, G, B,colorPixel;
for (int x = 0; x < width; x++) { //original image to grayscale
for (int y = 0; y < height; y++) {
colorPixel = tempImg.getPixel(x, y);
A = Color.alpha(colorPixel);
R = Color.red(colorPixel);
G = Color.green(colorPixel);
B = Color.blue(colorPixel);
R = (R + G + B) / 3;
G = R;
B = R;
OImg.setPixel(x, y, Color.argb(A, R, G,B ));
}
}
return OImg;
}
public static Bitmap Botsu(Bitmap gImg){
Bitmap tempImg = (Bitmap) gImg;
Bitmap BWimg = Bitmap.createBitmap(tempImg.getWidth(), tempImg.getHeight(), tempImg.getConfig());
int width = tempImg.getWidth();
int height = tempImg.getHeight();
int A, R, G, B, colorPixel;
// histo-thresh
double Wcv = 0;
int[] Bx = new int[256];
int[] By = new int[256];
int[] Fx = new int[256];
int[] Fy = new int[256];
double Bw =0, Bm =0, Bv =0, Bp = 0;
double Fw =0, Fm =0, Fv =0, Fp = 0;
int c = 0, ImgPix = 0, ImgPixB = 0, ImgPixF = 0, newPixel = 0;
// pixel check for histogram
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
colorPixel = tempImg.getPixel(x, y);
A = Color.alpha(colorPixel);
R = Color.red(colorPixel);
G = Color.green(colorPixel);
B = Color.blue(colorPixel);
int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
if (gray > 128) { // white - foreground
for (int z=0; z<Fx.length; z++){
if (Fx[z] == gray){
c++;
}
}
if (c==1){
Fy[gray] = Fy[gray]+1; //y axis - counter for pixels for each x
}
else{
Fx[x] = gray; //x axis - 0-255
Fy[gray] = Fy[gray]+1;
}
}//By[Bx[x]]
else{ // black - background
for (int z=0; z<Bx.length; z++){
if (Bx[z] == gray){
c++;
}
}
if (c==1){
By[gray] = By[gray]+1; //y axis - counter for pixels for each x
}
else{
Bx[x] = gray; //x axis - 0-255
By[gray] = By[gray]+1;
}
}
}
}
for (int b=0; b<By.length; b++){
ImgPixB = ImgPixB + By[b];
}
for (int f=0; f<Fy.length; f++){
ImgPixF = ImgPixF + Fy[f];
}
ImgPix = ImgPixB + ImgPixF;
//bg part hist
for (int i=0; i<By.length; i++){ //weight
Bw = Bw + By[i];
}
Bw = Bw/ImgPix;
for (int i=0; i<By.length; i++){ //pixel sum
Bp = Bp + By[i];
}
for (int i = 0; i<Bx.length; i++){ //mean
Bm = Bm + (Bx[i]*By[Bx[i]]);
}
Bm = Bm/Bp;
for (int i=0; i<Bx.length; i++){ //variance
Bv = Bv + (Math.pow((Bx[i]-Bm),2)*By[Bx[i]]); // (Bx[i]-Bm) * (Bx[i]-Bm)
}
Bv = Bv/Bp;
//fg part hist
for (int i=0; i<Fy.length; i++){ //weight
Fw = Fw + Fy[i];
}
Fw = Fw/ImgPix;
for (int i=0; i<Fy.length; i++){ //pixel sum
Fp = Fp + Fy[i];
}
for (int i = 0; i<Fx.length; i++){ //mean
Fm = Fm + (Fx[i]*Fy[Fx[i]]);
}
Fm = Fm/Fp;
for (int i=0; i<Fx.length; i++){ //variance
Fv = Fv + (Math.pow((Fx[i]-Fm),2)*Fy[Fx[i]]); // (Bx[i]-Bm) * (Bx[i]-Bm)
}
Fv = Fv/Fp;
// within class variance
Wcv = (Bw * Bv) + (Fw * Fv);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
colorPixel = tempImg.getPixel(x, y);
A = Color.alpha(colorPixel);
R = Color.red(colorPixel);
G = Color.green(colorPixel);
B = Color.blue(colorPixel);
//int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
int gray2 = (int) (Wcv * R + Wcv * G + Wcv * B);
if (gray2 > 128) {
gray2 = 255;
}
else if (gray2 <129){
gray2 = 0;
}
BWimg.setPixel(x, y, Color.argb(A, gray2, gray2, gray2));
}
}
return BWimg;
x[z] is for x-axis andy[gray] is for y-axis. I based this on the graph on Lab Book
x = 0-255
y = how many pixels is on a certain color shade
feel free to send more samples that can help me.
OUTPUT: (I added 2 function with 3 output that has an output. Other value will only return few black dots or just white image.)
if (gray2 > 128) {
gray2 = 255;
}
else if (gray2 < 129){
gray2 = 0;
}
if (gray2 > 64 && gray2 < 129) {
gray2 = 255;
}
else if (gray2 < 65){
gray2 = 0;
}
I'm writing code that performs a projective transform (https://math.stackexchange.com/questions/296794/finding-the-transform-matrix-from-4-projected-points-with-javascript) on an image using 4 user selected points.
In doing so I have to use very large arrays (300k+ indices). When I run it, my phone screen blacks out and after a few seconds gives the message " has stopped working." However, it continues to print Log messages to my AndroidStudio logcat containing information about the array that it's working on, letting me know that it's still running.
I'm not very knowledgeable about computational efficiency, so I might be making some fatal mistake involving matrix manipulation. The part of the code that it breaks on is the final portion of transform(), and the logcat prints the "rounded" values while the phone shows a "stopped working" message.
I've included the relevant code. Any advice on anything I'm doing wrong (related or not) is appreciated as this is my first experience with Android development.
I'm more or less just following the transformation provided by in the math.stackexchange link.
public class projTransform extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_proj_transform);
Intent parent_intent = getIntent();
Uri imgUri = parent_intent.getData();
pointArray = parent_intent.getDoubleArrayExtra("points");
//dimens[0-3]: width, height, minX, minY
dimens = parent_intent.getIntArrayExtra("dimens");
transform(imgUri,pointArray, dimens);
}
//A*B = C
private static double[][] mMult(double[][] A, double[][] B){
int mA = A.length;
int nA = A[0].length;
int mB = B.length;
int nB = B[0].length;
if (nA != mB) throw new RuntimeException("Illegal matrix dimensions.");
double[][] C = new double[mA][nB];
for (int i = 0; i < mA; i++)
for (int j = 0; j < nB; j++)
for (int k = 0; k < nA; k++)
C[i][j] += A[i][k] * B[k][j];
return C;
}
//A*x = y
private static double[] mMult(double[][] A, double[] x){
int m = A.length;
int n = A[0].length;
if (x.length != n) throw new RuntimeException("Illegal matrix dimensions.");
double[] y = new double[m];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
y[i] += A[i][j] * x[j];
return y;
}
//https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3.C3.973_matrices
//A^(-1)
private static double[][] mInvert3x3(double[][] X){
double[][] Y = new double[3][3];
double A,B,C,D,E,F,G,H,I,detX;
A = X[1][1]*X[2][2] - X[1][2]*X[2][1];
B = -(X[1][0]*X[2][2] - X[1][2]*X[2][0]);
C = X[1][0]*X[2][1] - X[1][1]*X[2][0];
D = -(X[0][1]*X[2][2] - X[0][2]*X[2][1]);
E = X[0][0]*X[2][2] - X[0][2]*X[2][0];
F = -(X[0][0]*X[2][1] - X[0][1]*X[2][0]);
G = X[0][1]*X[1][2] - X[0][2]*X[1][1];
H = -(X[0][0]*X[1][2] - X[0][2]*X[1][0]);
I = X[0][0]*X[1][1] - X[0][1]*X[1][0];
detX = X[0][0]*A + X[0][1]*B + X[0][2]*C;
Y[0][0] = A/detX;
Y[1][0] = B/detX;
Y[2][0] = C/detX;
Y[0][1] = D/detX;
Y[1][1] = E/detX;
Y[2][1] = F/detX;
Y[0][2] = G/detX;
Y[1][2] = H/detX;
Y[2][2] = I/detX;
return Y;
}
private void transform(Uri data, double[] sourceArray, int[] dimens){
if (data != null) {
try {
InputStream imgStream = getContentResolver().openInputStream(data);
tempBmp = BitmapFactory.decodeStream(imgStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedbmp = Bitmap.createBitmap(tempBmp, 0, 0, tempBmp.getWidth(), tempBmp.getHeight(), matrix, true);
crop = new int[dimens[0] * dimens[1]];
rotatedbmp.getPixels(crop, 0, dimens[0], dimens[2], dimens[3], dimens[0], dimens[1]);
//map for original bmp
double[][] sourceMap = tMap(sourceArray);
Log.e("sourceMap",toString(sourceMap));
//map for transformed bmp
double[] destArray = new double[] {0,0,0,destHeight,destWidth,0,destHeight,destWidth};
double[][] destMap = tMap(destArray);
Log.e("destMap",toString(destMap));
// C = B*[A^(-1)]
double[][] finalMap = mMult(sourceMap, mInvert3x3(destMap));
Log.e("width", String.valueOf(dimens[0]));
int[] destPixels = new int[destHeight*destWidth];
int[] temp;
for(int i=0; i<destHeight-1; i++){
for(int j=0; j<destWidth-1; j++){
temp = pixelMap(finalMap,i,j);
Log.e("rounded", String.valueOf(temp[0]) + ", " + String.valueOf(temp[1]));
destPixels[(i*destWidth)+j] = crop[(temp[0]*dimens[0]) + temp[1]];
}
}
display(destPixels, destWidth, destHeight);
}
}
//produces mapping matrix given corners
//A,B in SE post
private double[][] tMap(double[] pointArray){
double[][] tempArray = new double[3][3];
tempArray[0][0] = pointArray[0];
tempArray[1][0] = pointArray[1];
tempArray[0][1] = pointArray[2];
tempArray[1][1] = pointArray[3];
tempArray[0][2] = pointArray[4];
tempArray[1][2] = pointArray[5];
for(int i=0; i<3; i++){
tempArray[2][i] = 1;
}
//Log.e("tempArray",toString(tempArray));
double[] tempVector = new double[] {pointArray[6], pointArray[7], 1};
//Log.e("tempVector",toString(tempVector));
double[][] inverted = mInvert3x3(tempArray);
//Log.e("inverted",toString(inverted));
double[] coef = mMult(inverted, tempVector);
//Log.e("coef",toString(coef));
double[][] tran = new double[3][3];
for(int i=0; i<3; i++){
for (int j=0; j<3; j++){
tran[i][j] = tempArray[i][j]*coef[j];
}
}
return tran;
}
private int[] pixelMap(double[][] map, double x, double y){
double[] tempVector = new double[] {x,y,1};
double[] primeVector = mMult(map,tempVector);
return new int[] {(int) Math.round(primeVector[0]/primeVector[2]), (int) Math.round(primeVector[1]/primeVector[2])};
}
You don't need to divide by the determinant; the adjoint instead of the inverse is sufficient. Apart form that, you're creating a lot of objects.
The tight loop is one with the two nested loops around the pixelMap call. Try to inline pixelMap there, and try to avoid creating new arrays. Use separate variables for all the infividual coordinates. Use the fact that you know the dimensions.
x = finalMap[0][0]*i + finalMap[0][1]*j + finalMap[0][2];
and so on. If you want to, you can move finalMap into a set of 9 local variables to help the optimizer. Also disable the logging line, since caching and transfering that much log output takes considerable resources. Do one log line when you start the loop, and another when you're done. In the end, the loop would look somewhat like this:
for(int i=0; i<destHeight-1; i++){
for(int j=0; j<destWidth-1; j++){
double x = finalMap00*i + finalMap01*j + finalMap02;
double y = finalMap10*i + finalMap11*j + finalMap12;
double z = finalMap20*i + finalMap21*j + finalMap22;
int xi = (int)Math.round(x/z), yi = (int)Math.round(y/z);
destPixels[(i*destWidth)+j] = crop[(xi*srcWidth) + yi];
}
}
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 need to convert a 2d integer array (subSrc) to a bitmap. Any solutions?
private Bitmap decimation(Bitmap src){
Bitmap dest = Bitmap.createBitmap(
src.getWidth(), src.getHeight(), src.getConfig());
int bmWidth = src.getWidth();
int bmHeight = src.getHeight();`enter code here`
int[][] subSrc = new int[bmWidth/2][bmWidth/2];
for(int k = 0; k < bmWidth-2; k++){
for(int l = 0; l < bmHeight-2; l++){
subSrc[k][l] = src.getPixel(2*k, 2*l); <---- ??
I looked for a method that received an 2d array (int[][]) and created a Bitmap, and found none, so I wrote one myself:
public static Bitmap bitmapFromArray(int[][] pixels2d){
int width = pixels2d.length;
int height = pixels2d[0].length;
int[] pixels = new int[width * height];
int pixelsIndex = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
pixels[pixelsIndex] = pixels2d[i][j];
pixelsIndex ++;
}
}
return Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888);
}
I also wrote a reverse method:
public static int[][] arrayFromBitmap(Bitmap source){
int width = source.getWidth();
int height = source.getHeight();
int[][] result = new int[width][height];
int[] pixels = new int[width*height];
source.getPixels(pixels, 0, width, 0, 0, width, height);
int pixelsIndex = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
result[i][j] = pixels[pixelsIndex];
pixelsIndex++;
}
}
return result;
}
I hope you find it useful!
you can use
setPixel(int, int, int) or setPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height) methos od bitmap class.
Bitmap dest = Bitmap.createBitmap(
src.getWidth()/2, src.getHeight()/2, src.getConfig());
int bmWidth = src.getWidth();
int bmHeight = src.getHeight();
for(int k = 0; k < bmWidth/2; k++){
for(int l = 0; l < bmHeight/2; l++){
dest.setPixel(k,l,src.getPixel(2*k, 2*l));
But this will be slower i think.
for the 2nd method you uhave to do something like this
int subSrc = new int[(bmWidth/2*)(bmHeight/2)];
for(int k = 0; k < bmWidth-2; k++){
subSrc[k] = src.getPixel(2*(k/bmWidth), 2*(k%bmHeight)); <---- ??
So, you are essentially trying to pull pixels out, do something to them, then make a Bitmap as a result?
The routines expect the pixels to be in a single-dimensional array, so you'll want to put them into the array more like this:
int data[] = new int[size];
data[x + width*y] = pixel(x,y);
...
Then use Bitmap.createBitmap() that accepts the single-dimensional array. You'll want to use the Bitmap.Config for ARGB in your example, since you're using b.getPixel(x,y) which always returns a color in ARGB format.
Bitmap result = Bitmap.createBitmap(data, width, height, Bitmap.Config.ARGB_8888);
i want to get the Position of the character at the time of touch on the editext box in my application with the help of the coordinates of Ontouch. How should this be possible .
Please help me
Thanks in advance
I've written a method to do just that. It's for TextView, but should work for EditText since it extends TextView. Make a custom EditText and stick this method in there.
NOTE x and y are the getX() and getY() component of the MotionEvent during OnTouch
public int getCharIndexFromCoordinate( int x, int y ) {
// Offset the top padding
int height = getPaddingTop();
for (int i = 0; i < getLayout().getLineCount(); i++) {
Rect bounds = new Rect();
getLayout().getLineBounds( i, bounds );
height += bounds.height();
if ( height >= y ) {
int lineStart = getLayout().getLineStart( i );
int lineEnd = getLayout().getLineEnd( i );
Spanned span = (Spanned) getText();
RelativeSizeSpan[] sizeSpans = span.getSpans( lineStart, lineEnd, RelativeSizeSpan.class );
float scaleFactor = 1;
if ( sizeSpans != null ) {
for (int j = 0; j < sizeSpans.length; j++) {
scaleFactor = sizeSpans[j].getSizeChange();
}
}
String lineSpan = getText().subSequence( lineStart, lineEnd ).toString();
float[] widths = new float[lineSpan.length()];
TextPaint paint = getPaint();
paint.getTextWidths( lineSpan, widths );
float width = 0;
for (int j = 0; j < lineSpan.length(); j++) {
width += widths[j] * scaleFactor;
if ( width >= x || j == lineSpan.length() - 1 ) {
return lineStart + j;
}
}
}
}
return -1;
}