greyscale Iplimage to android bitmap - android

I am using opencv to convert android bitmap to grescale by using opencv. below is the code i am using,
IplImage image = IplImage.create( bm.getWidth(), bm.getHeight(), IPL_DEPTH_8U, 4); //creates default image
bm.copyPixelsToBuffer(image.getByteBuffer());
int w=image.width();
int h=image.height();
IplImage grey=cvCreateImage(cvSize(w,h),image.depth(),1);
cvCvtColor(image,grey,CV_RGB2GRAY);
bm is source image. This code works fine and converts to greyscale, i have tested it by saving to sdcard and then loading again, but when i try to load it using below method my app crashes, any suggestions.
bm.copyPixelsFromBuffer(grey.getByteBuffer());
iv1.setImageBitmap(bm);
iv1 is imageview where i want to set the bm.

I've never used the OpenCV bindings for Android, but here's some code to get you started. Regard it as pseudocode, because I can't try it out... but you'll get the basic idea. It may not be the fastest solution. I'm pasting from this answer.
public static Bitmap IplImageToBitmap(IplImage src) {
int width = src.width;
int height = src.height;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
for(int r=0;r<height;r++) {
for(int c=0;c<width;c++) {
int gray = (int) Math.floor(cvGet2D(src,r,c).getVal(0));
bitmap.setPixel(c, r, Color.argb(255, gray, gray, gray));
}
}
return bitmap;
}

Your IplImage grey has only one channel, and your Bitmap bm has 4 or 3 (ARGB_8888, ARGB_4444, RGB_565). Therefore the bm can't store the greyscale image. You have to convert it to rgba before use.
Example:
(your code)
IplImage image = IplImage.create( bm.getWidth(), bm.getHeight(), IPL_DEPTH_8U, 4);
bm.copyPixelsToBuffer(image.getByteBuffer());
int w=image.width(); int h=image.height();
IplImage grey=cvCreateImage(cvSize(w,h),image.depth(),1);
cvCvtColor(image,grey,CV_RGB2GRAY);
If you want to load it:
(You can reuse your image or create another one (temp))
IplImage temp = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 4); // 4 channel
cvCvtColor(grey, temp , CV_GRAY2RGBA); //color conversion
bm.copyPixelsFromBuffer(temp.getByteBuffer()); //now should work
iv1.setImageBitmap(bm);
I might it will help!

Related

Creating a Cropped bitmap without creating a new bitmap

I need to figure out a way to get a bitmap cropped without creating another bitmap that is already present.
I have two bitmaps
int width = 50;
int height = 50;
//Bitmap A
bitmapA = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmapA.copyPixelsFromBuffer(buffer);
//Bitmap B
bitmapB = Bitmap.createBitmap(45, 45, Bitmap.Config.ARGB_8888);
bitmapA has an image data, while bitmapB has no image data. I need a cropped image of bitmapA starting from (5, 5) and put it into bitmapB without creating another new Bitmap.
While I can do
bitmapC = Bitmap.createBitmap(bitmapA, 5, 5, 45, 45);
this will create another Bitmap object. I need to copy the data of bitmapA into the already created bitmapB without creating another Bitmap / calling createBitmap
Can this be done by using Rect?
Any ideas? thanks.

How do I pass a Texture2D into Android and save it as a Bitmap?

I have a unity scene where I want to pass a Texture2D into android, do some processing, then save it as a bitmap. My code isn't working. For simplicity sake i removed the processing part of it and I'm trying to just save the image as a bitmap.
On the unity side there's some initialization for the android package and this line:
_pluginInterface.CallStatic("ProcessImage", testTexture.GetNativeTexturePtr().ToInt32(), testTexture.width, testTexture.height);
On the Java side:
public static void ProcessImage(int ptr, int width, int height){
Bitmap b = Bitmap.createBitmap(width, height,Bitmap.Config.ARGB_8888); // this is just so I get the right length
int byteCount = b.getByteCount();
ByteBuffer inputBuffer = ByteBuffer.allocate(byteCount);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, ptr);
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, inputBuffer);
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
inputBuffer.rewind();
bmp.copyPixelsFromBuffer(inputBuffer);
SaveToFileDebug(bmp); // basic function that saves the bitmap
}
As you can probably tell I'm all over the place with the encodings and i think that might be the problem, but they don't seem to match between unity and android.
Thanks in advance
Instead of doing such acrobatics coding just use GetRawTextureData and use the returned byte array to create your bitmap
Example
byte[] raw = testTexture.GetRawTextureData();
_plugin.Interface.CallStatic("YourMethod",raw,width, height);
Java Side
Bitmap bmp = BitmapFactory.decodeByteArray(raw, 0, raw.length)

Changing image color takes too much time in android

I am trying to change image color dynamically in android .but it takes to much time .
Below function is used for changing color.
public void greenColor(ImageView imageView,String fileName){
System.out.println("in green color method");
//initialize the Bitmap Object
Bitmap bmp = BitmapFactory.decodeFile(fileName);
// Bitmap bmp = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
//Guarantees that the image is decoded in the ARGB8888 format
bmp = bmp.copy(Bitmap.Config.ARGB_8888, true);
//Initialize the intArray with the same size as the number of pixels on the image
int[] intArray = new int[bmp.getWidth()*bmp.getHeight()];
//copy pixel data from the Bitmap into the 'intArray' array
bmp.getPixels(intArray, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
//replace the red pixels with yellow ones
try{
for (int i=0; i < intArray.length; i++)
{
//System.out.println("pixel value :"+intArray[i]);
//intArray[i] = 0xFFFF0000;
if(intArray[i] == Color.WHITE)
{
System.out.println("color white ");
} else{
System.out.println(intArray[i]);
intArray[i]=Color.GREEN;
}
}
}catch(Exception e){
System.out.println("pixel error "+e);
}
//Initialize the bitmap, with the replaced color
bmp = Bitmap.createBitmap(intArray, bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
//Draw the bitmap with the replaced color
imageView.setImageBitmap(bmp);
//----end color
}
I've tried so much and did google search, but i am unable to solve my problem ,
Is there any technique to reduce image color change time in android?
Please help me ...
in your case its taking time as you are converting the image into 2d array and checking at every index.
So if image if 2000*2000 size, just imagine how much you are processing.
If you want to change the alfa or tint then you should use the Bitmap APIs instead of doing it manually.

Android OpenCV Highgui.imread wrong color

i have code to load image from sdcard and post it to ImageView.
Mat mRgba = Highgui.imread(dir);
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mRgba, bmp);
mImage.setImageBitmap(bmp, true, null, 5.0f);
the image is loaded but it's wrong color. Color seem to be inverted (but not inverted).
Here is image comparison
I tried to load image by
Bitmap bmp = BitmapFactory.decodeFile(dir);
It worked correctly. But i have to use Highgui.imread.
What wrong with my code?
You will have to use something like this:
Mat inputImage = Highgui.imread(pathToFile);
Mat tmp = new Mat();
Imgproc.cvtColor(inputImage, tmp, Imgproc.COLOR_BGR2RGB);
Bitmap imageToShow = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(tmp, imageToShow);
You're trying to load a bitmap supposing that the image is 8-bit/color RGBA: are you sure of that?
Also note that ARGB is not RGBA. You may need to re-arrange the bytes of each pixel. Something like
int pixel = get_the_pixel();
int alpha = 0xff & pixel;
pixel = pixel<<8 | alpha;
set_the_pixel(pixel);
You'll want to do something more efficient than accessor methods shown here, but you get the idea.

Blending pixels from Two Bitmaps

I'm beating my head against a wall here, and I'm fairly certain I'm doing something stupid, so time to make my stupidity public.
I'm trying to take two images, blend them together into a third image using standard blending algorithms (Hardlight, softlight, overlay, multiply, etc).
Because Android does not have such blend properties build in, I've gone down the path of taking each pixel and combine them using an algorithm. However, the results are garbage. Below is the results of a simple multiply blend (images used, and expected result).
BASE:
BLEND:
EXPECTED RESULT:
GARBAGE RESULT:
Any help would be appreciated. Below is the code, which I've tried to strip out all the "junk", but some may have made it through. I'll clean it up if something isn't clear.
ImageView imageView = (ImageView) findViewById(R.id.ImageView01);
Bitmap base = BitmapFactory.decodeResource(getResources(), R.drawable.base);
Bitmap result = base.copy(Bitmap.Config.RGB_565, true);
Bitmap blend = BitmapFactory.decodeResource(getResources(), R.drawable.blend);
IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight());
base.copyPixelsToBuffer(buffBase);
buffBase.rewind();
IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight());
blend.copyPixelsToBuffer(buffBlend);
buffBlend.rewind();
IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight());
buffOut.rewind();
while (buffOut.position() < buffOut.limit()) {
int filterInt = buffBlend.get();
int srcInt = buffBase.get();
int redValueFilter = Color.red(filterInt);
int greenValueFilter = Color.green(filterInt);
int blueValueFilter = Color.blue(filterInt);
int redValueSrc = Color.red(srcInt);
int greenValueSrc = Color.green(srcInt);
int blueValueSrc = Color.blue(srcInt);
int redValueFinal = multiply(redValueFilter, redValueSrc);
int greenValueFinal = multiply(greenValueFilter, greenValueSrc);
int blueValueFinal = multiply(blueValueFilter, blueValueSrc);
int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal);
buffOut.put(pixel);
}
buffOut.rewind();
result.copyPixelsFromBuffer(buffOut);
BitmapDrawable drawable = new BitmapDrawable(getResources(), result);
imageView.setImageDrawable(drawable);
}
int multiply(int in1, int in2) {
return in1 * in2 / 255;
}
After reproducing, I think your issue has to do with manipulating the images in RGB565 mode. As discussed in this post, Bitmaps apparently need to be in ARGB8888 mode to manipulate properly. I first got the expected result on a multiply blend by doing the following:
Resources res = getResources();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap base = BitmapFactory.decodeResource(res, R.drawable.base, options);
Bitmap blend = BitmapFactory.decodeResource(res, R.drawable.blend, options);
// now base and blend are in ARGB8888 mode, which is what you want
Bitmap result = base.copy(Config.ARGB_8888, true);
// Continue with IntBuffers as before...
Converting the Bitmaps to ARGB8888 mode did seem to work for me, at least with the gradient test patterns. However, it you only need to do Screen or Multiply, you might try this as well:
// Same image creation/reading as above, then:
Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
p.setShader(new BitmapShader(blend, TileMode.CLAMP, TileMode.CLAMP));
Canvas c = new Canvas();
c.setBitmap(result);
c.drawBitmap(base, 0, 0, null);
c.drawRect(0, 0, base.getWidth(), base.getHeight(), p);
With that, you aren't doing the per-pixel calculations, but you are limited to the preset PorterDuff.Modes. In my quick (and dirty) testing, this was the only way I was able to get the blending to work on non-gradient images.
Simple overlay you can do this way (for simplicity it is supposed that bmp1 is equal or bigger than bmp2):
private Bitmap bitmapOverlay(Bitmap bmp1, Bitmap bmp2)
{
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0, 0, null);
canvas.drawBitmap(bmp2, 0, 0, null);
return bmOverlay;
}
For more complex blending algorithms, maybe you can help yourself with some available Bitmap/Canvas functions.

Categories

Resources