I am comparing 2 similar images and would like to see if both are similar .Currently I used the code:
public void foo(Bitmap bitmapFoo) {
int[] pixels;
int height = bitmapFoo.getHeight();
int width = bitmapFoo.getWidth();
pixels = new int[height * width];
bitmapFoo.getPixels(pixels, 0, width, 1, 1, width - 1, height - 1);
}
and I call the function : foo(img1) where :
img1=(Bitmap)data.getExtras().get("data");
I would like to know how to get the above getpixel,I tried assigning it to variable but did not work .Should it have a return type ?? and in format it is ?
And also how do I compare 2 images??
Also both the images may be of different dimensions based on the mobile camera the snapshot is taken from .
Also can it recognize if the same image is shot in the morning and night ???
Thanks in Advance.
This code will compare pixel from base image with other image.
If both pixel at location (x,y) are same then add same pixel in result image without change. Otherwise it modifies that pixel and add to our result image.
In case of baseline image height or width is larger than other image then it will add red color for extra pixel which is not available in other images.
Both image file format should be same for comparison.
Code will use base image file format to create resultant image file and resultant image contains highlighted portion where difference observed.
Here is a Link To Code with sample example attached.
If you want to copy the pixels of the bitmap to a byte array, the easiest way is:
int height = bitmapFoo.getHeight();
int width = bitmapFoo.getWidth();
pixels = new int[height * width];
bitmapFoo.copyPixelsToBuffer(pixels);
See the documentation
I should warn you that you will have to handle this with care, any other way you will get OutOfMemoryError.
To get All Pixels
bitmapFoo.copyPixelsToBuffer(pixels);
or
bitmapFoo.getPixels(pixels, 0, width, 0, 0, width, height);
To get One Pixel
The two arguments must be two integers within the range [0, getWidth()-1] and [0, getHeight()-1]
int pix = bitmapFoo.getPixel(x, y);
Related
So i making image from camera,via native API. The problem is that,i also have an algorithms to compute some stuff(with bitmap) and problem comes,when resolution is too high(for e.g. 3000x2500),because i need wait too much time.
So first what comes in my mind,its like a workaround:
Convert from source bitmap to low-resolution(for e.g. 600x800).
Work with this low-resolution bitmap(computing some stuff and calculate coords,that are located on this low-resolution bitmap).
Get exact pixel coords and via some Math formula(that calculates width/heights or pixels?) put them into same place,but on source bitmap(with high resolution).
So how can i achieve this part? I think it's possible,but cant understand what exactly need to do.
Thanks!
OK, that is what you need
assuming you have computed some x, y values for you low res image:
int lowResX, lowResY;
Than for converting them to the hi res:
double scaleRatio = hiResImageWidth / lowResImageWidth; //be sure to use here double or float values as the result of integer division will be int, and not the double/float!
int hiResX = (int) (lowResX * scaleRatio);
int hiResY = (int) (lowResY * scaleRatio);
That's all
If you know the x,y position in your w,h bitmap then the X,Y you are looking for in your W,H bitmap are just simple ratios
x/w = X/W which you can solve easily : X = x * W/w
Similarly you get Y = y * H/h
I need to create a bitmap in android and draw some stuff on it using a canvas which will eventually be printed using a photo printer. Basically I'm trying to create a jpg of actual 5x7 size (5 inches X 7 inches). So if the bitmap is emailed or copied to a computer, it correctly fit into a 5X7 photo printing paper.
When specifying the height and width in the createbitmap method, what values do I need to specify to make the actual size of the bitmap 5x7. Is this dependent on the screen density etc., of the device?
Try this method:
public void setViewInInches(float width, float height, View v) {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int widthInches = Math.round(width * metrics.xdpi);
int heightInches = Math.round(height * metrics.ydpi);
v.setLayoutParams(new LinearLayout.LayoutParams(widthInches, heightInches));
v.requestLayout();
}
Pass in the width and height, followed by the view you want to set it to and it should work. Sample call to set image view to 5x7:
setViewInInches(5f, 7f, imageView);
How large the final image will be printed on paper is up to the printer, however you can give hints how large it should be with Bitmap.setDensity(). Note that image density is simply a numeric metadata embedded in the image file and it is up to the output device (i.e. the printer) to interpret or obey the hint.
The relationship between images size in pixel and the density you need to set to achieve a certain size is a fairly simple math, if you have an image whose pixel size is 360x504 pixels and you want to print it so the physical size of 5x7 inch, you'll need to set the density to be: 360px / 5 inch = 72ppi.
int IMAGE_WIDTH_IN_PIXEL = 360;
int IMAGE_HEIGHT_IN_PIXEL = 504;
float TARGET_WIDTH_IN_INCH = 5;
float TARGET_HEIGHT_IN_INCH = 7;
Bitmap bitmap = Bitmap.createBitmap(IMAGE_WIDTH_IN_PIXEL, IMAGE_HEIGHT_IN_PIXEL, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
... draw something ...
// you need make sure the Bitmap had the same aspect ratio as the target printing size
assert IMAGE_WIDTH_IN_PIXEL / TARGET_WIDTH_IN_INCH == IMAGE_HEIGHT_IN_PIXEL / TARGET_HEIGHT_IN_INCH;
bitmap.setDensity(IMAGE_WIDTH_IN_PIXEL / TARGET_WIDTH_IN_INCH);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outfile);
Note that how large the image is printed has nothing to do with the device's screen density, which determines how large the image will be viewed on screen.
If you have a predetermined printing density though, for example, most regular printers can print at least at 300ppi, as it's the lowest ppi which would not appear with pixelation at typical reading distance. If you have a preset ppi, what you need to control is then the image pixel size when you render the image to the Bitmap. The relationship is again pretty simple, to print an image at 5in wide at 300ppi you'll need 300ppi * 5 in = 1500 pixel wide image.
int TARGET_DENSITY = 300;
float PHYSICAL_WIDTH_IN_INCH = 5;
float PHYSICAL_HEIGHT_IN_INCH = 7;
Bitmap bitmap = Bitmap.createBitmap(PHYSICAL_WIDTH_IN_INCH * TARGET_DENSITY, PHYSICAL_HEIGHT_IN_INCH * TARGET_DENSITY, Bitmap.Config.ARGB_8888);
bitmap.setDensity(TARGET_DENSITY);
Canvas canvas = new Canvas(bitmap);
... draw something ...
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outfile);
Another possibility if the printer service supports it is to submit the intended physical size separately along with the printing request. The printer then will ignore the embedded density hint and calculate the image density required to print at that size.
first the important lines of code:
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), getDrawableForLvl(drawable));
int []pixels = new int[bitmap.getWidth()*bitmap.getHeight()];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
//..
pixels = null; // please gc remove this huge data
System.gc();
So I'm working on an Android app (game) with multiple levels. Every level is an image that I load as bitmap on level start. Then I have to analyse every pixel (line 3). For that I create an array (line 2). The images are 1280x800, so the array has a size over one million ints. No problems here and since it's a local variable it should be destroyed on method return. But it's java, so it's not -.- Depending on the device the garbage collector is running fast enough in time or not. So when a user starts and closes levels very fast it produces a java.lang.OutOfMemoryError in line 2. I guess because the old array(s) wasn't/weren't removed yet and now I have multiple ones filling the memory.
I could make the array a static member. So it's created once and is always available. Then it's not possible to have multiple instances of it. But I think that's a bad coding style, because it's also available (4 MB) when not needed.
I don't need all pixels at the same time. I'm splitting the images in more than a hundred rectangles, so I could use a way smaller array and fill it one after another with pixels. But I have problems to understand the methods parameters can someone help me here?
There is also a method to get just one pixel at position x,y, but I guess a million function calls is pretty slow.
Has someone a better idea? There is no way to force an object out of memory in java, is there?
Update1:
As vzoha suggested to get only the first quarter:
int []pixels = new int[bitmap.getWidth()/2*bitmap.getHeight()/2];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2);
gives an ArrayIndexOutOfBound. I think the function call is just getting the pixels of the first quarter, but still expects the full size array and the other fields will be left untouched.
Update2: I guess I can do it row by row (half row by half row for the first quarter):
int []pixels = new int[bitmap.getWidth()/2*bitmap.getHeight()/2];
for(int row = 0; row < bitmap.getHeight()/2; ++row)
bitmap.getPixels(pixels, bitmap.getWidth()/2, bitmap.getWidth(), 0, row, bitmap.getWidth()/2, 1);
But when I do that for 20x10 parts it's not much better than getting each pixel by itself. Well it is much better but still the method should be capable to do that with one call, shouldn't it? I just don't get this "stride" parameter: "The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative." How can it be negativ when >= width?
The size in pixels doesn't directly translate to how much memory the image will take up in memory. Bitmaps in Android (before using ART) are notoriously difficult to use heavily while avoiding OOM exceptions, enough so, that there's a page dedicated to how to use them efficiently. The problem is normally that there is actually enough memory available, but it has become fragmented and there isn't a single contiguous block the size you need available.
My first suggestion (for a quick win) would be to decode the bitmap with a specific config, you should be able to occupy only 1/4 of the amount of memory you were previously using by switching to use ALPHA_8 for your bitmap config. This will use 1 byte per pixel instead of 4 (the default is ARGB_8888)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ALPHA_8
bitmap = BitmapFactory.decodeResource(getResources(), getDrawableForLvl(drawable), options);
My next suggestion would be to scale you bitmap to start with and place the appropriate one in your hdpi,xhdpi,xxhdpi folders.
In fact it is pretty simple to get just the pixels of a specific area. But the documentation is wrong about the stride parameter. It says:
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
stride: The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative.
But the truth is it can (and must in most cases) be less than the bitmap's width, it just has to be bigger or equal to the passed width (the second to last parameter of getPixels), meaning the width of the area from which I want the pixels.
So to get the pixels of the first quarter of a bitmap:
int []pixels = new int[bitmap.getWidth()>>1 * bitmap.getHeight()>>1]; // quarter of the bitmap size
bitmap.getPixels(pixels, 0, bitmap.getWidth()>>1, 0, 0, bitmap.getWidth()>>1, bitmap.getHeight()>>1);
Or to get a specific rect with x,y (upper left corner) and width, height:
int []pixels = new int[width*height];
bitmap.getPixels(pixels, 0, width, x, y, width, height);
So pretty simple. It was just the wrong documentation that put a twist in my brain.
I have been working in printing an image via bluetooth printer. When I test it for
text printing it works perfectly. But when it comes to image, prints only string characters.
I have converted the layout into bitmap. And saved it into sd card. Do I need to convert the bitmap into
something that supports for printer. Am using "ZEBRA EZ320" printer for my application.
I have used the following code to convert the layout into bitmap,
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
I found solution to my problem.
Bitmap localBitmap=BitmapFactory.decodeResource(getResources(), image);
BluetoothConnection myConn = new BluetoothConnection(macaddr);
ZebraPrinter myPrinter = new ZebraPrinterCpcl(myConn);
myConn.open();
new ZebraPrinterLegacyDelegator(myPrinter).getGraphicsUtil().printImage(localBitmap, 0, 0, -1, -1, false);
// to reduce extra space
myConn.write("! UTILITIES\r\nIN-MILLIMETERS\r\nSETFF 10 2\r\nPRINT\r\n".getBytes());
myConn.close();
The code mentioned in the above answer uses ZebraPrinterLegacyDelegator, which is deprecated.
Use the following code,
InputStream inputStream = assetManager.open("printing/ic_launcher.png");
ZebraImageI zebraImageI = ZebraImageFactory.getImage(BitmapFactory.decodeStream(inputStream));
zebraPrinter.printImage(zebraImageI, 250, 0, 0, -1, false);
Zebra Printer instance can be created as follow,
zebraPrinter = ZebraPrinterFactory.getInstance(printerConnection);
printImage arguments are as follows,
image - the image to be printed.
x - horizontal starting position in dots.
y - vertical starting position in dots.
width - desired width of the printed image. Passing a value less than 1 will preserve original width.
height - desired height of the printed image. Passing a value less than 1 will preserve original height.
insideFormat - boolean value indicating whether this image should be printed by itself (false), or is part of a format being written to the connection (true).
And also to address your alignment problems change the x value to move the image to your convenient place.
i am trying to give a Photoshop posterization effect to imageview.here is a normal image.
after applying posterization effect it should look like this,this effect is taken from pixlr image editor
I want exact effect programmatically.
what I have tried is, I am trying to get similar effect with SaturationFilter kind of effect, as I am not able to find posterization method for android.
here is my function http://pastie.org/8007887
and resulting image is,as below which is not looking similar to Photoshop posterized effect, I have tried passing several saturation level,but no luck.i hope some one will guide me in a proper way.
found some way, http://developer.android.com/reference/android/media/effect/EffectFactory.html here is a guidline for posterization effect,and that is applicable for android API level 14,what about device which use API level <14?
There is a good library available named JHLabs' Java Image Processing.
It has lots of image processing filters available. I also use that library in my application. It is very compatible with Android also.
You can also download source code and run sample application.
JAR Download : http://www.jhlabs.com/ip/filters/Filters.zip
You could use the following
1. Android + Open CV
2. Android + Openframeworks
http://www.openframeworks.cc/setup/android-eclipse/
check out sample at
https://github.com/nkint/ofxPosterize
You can apply such effect by playing on different source code available
I would suggest you to go with this url and check the different effect https://xjaphx.wordpress.com/learning/tutorials/
The most relevant function i could see is mentioned below, try to modify it according to your need
int width = mImage.getWidth();
int height = mImage.getHeight();
int[] pixels = new int[width * height];
mImage.getPixels(pixels, 0, width, 0, 0, width, height);
for(int x = 0; x < pixels.length; ++x) {
pixels[x] = (pixels[x] == fromColor) ? targetColor : pixels[x];
}
Bitmap newImage = Bitmap.createBitmap(width, height, mImage.getConfig());
newImage.setPixels(pixels, 0, width, 0, 0, width, height);
return newImage;