Odd bitmap factory behavior (android) - android

static Boolean[][] squares = new Boolean[32][32];
static BitmapFactory.Options opts = new BitmapFactory.Options();
public static Boolean[][] getFrame(int id){
opts.inPreferredConfig = Bitmap.Config.ALPHA_8;
opts.outHeight = 32;
opts.outWidth = 32;
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.raw.f11, opts);
for (int y = 0; y < 32; y++) {
for (int x = 0; x < 32; x++) {
int pixel = bmp.getPixel(x, y);
if(pixel == -1)
squares[x][y] = false;
else
squares[x][y] = true;
}
}
return squares;
}
I'm having an issue here, bitmap factory seems to not be importing my bitmaps correctly. Here's what the original looks like and here's what getPixel (and getPixels) returns me. This happens with and without any options declared. I'd like to know why it seems to be importing 2rds of the picture at 2x resolution. I have tried 1 bit and 4 bit bitmaps as well as declaring the 1 bit and 4 bit Bitmap.Config. Using the Boolean array data to draw rectangles in a grid on a canvas. Thanks in advance.

I suppose you noticed it on screen?
If so, what is the xml for the ImageView? Maybe you inadvertently set an erroneous width or height?

Might be a late answer but I would try
opts.inScaled = false;

Related

Remove Background of an Image, Split it in same sizes and Change color(overlay)

I've been searching the internet for changing colour or overlaying a specific part of a bitmap. I've a square bitmap and I want to change the colour in a matrix pattern that is in equal 9 blocks which can be understood from the following image. (Cyan colour line here is for demonstration only)
I've read about boundary fill algorithm in College but here for java, I came to know that it is too bulky to perform such an operation for 9 specific parts. And I don't know how to use Paint with Canvas for such a square scenario.
So is there a method or something which can help me figure out how to paint a specific square by providing the size or location without performing a huge task on UI.
Here's what I need to achieve:
I can change the color, location,size by myself if there's something which can help me out.
Also, as there is white background, is there a way to not paint the background or do I have to use PNG?
Update:
I'm successfully able to divide the image in 9 equal parts using following code but PorterDuffColorFilter is not working as expected.
Code:
public void splitBitmap(Bitmap bitmap) {
int width, height;
// Divide the original bitmap width by the desired vertical column count
width = bitmap.getWidth() / 3;
// Divide the original bitmap height by the desired horizontal row count
height = bitmap.getHeight() / 3;
// Loop the array and create bitmaps for each coordinate
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
// Create the sliced bitmap
smallimages.add(Bitmap.createBitmap(bitmap, x * width, y * height, width, height));
}
}
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
The above code provides 9 bitmaps which then set to a GridLayout. But No mode of PorterDuffColorFilter is useful. Either the images remain original or is painted completely. I've tried every one of the modes available and none worked.
I've done something similar to this so after changing my code a bit, I think this is what you want:
Assuming that you don't have PNG,
First, remove the white background from your image Source:
Setting the white color as Transparent, you can use any color you want.
private static final int[] FROM_COLOR = new int[]{255, 255, 255};
private static final int THRESHOLD = 3;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.test_colors);
ImageView iv = (ImageView) findViewById(R.id.img);
Drawable d = getResources().getDrawable(RES);
iv.setImageDrawable(adjust(d));
}
private Drawable adjust(Drawable d)
{
int to = Color.TRANSPARENT;
//Need to copy to ensure that the bitmap is mutable.
Bitmap src = ((BitmapDrawable) d).getBitmap();
Bitmap bitmap = src.copy(Bitmap.Config.ARGB_8888, true);
for(int x = 0;x < bitmap.getWidth();x++)
for(int y = 0;y < bitmap.getHeight();y++)
if(match(bitmap.getPixel(x, y)))
bitmap.setPixel(x, y, to);
return new BitmapDrawable(bitmap);
}
private boolean match(int pixel)
{
//There may be a better way to match, but I wanted to do a comparison ignoring
//transparency, so I couldn't just do a direct integer compare.
return Math.abs(Color.red(pixel) - FROM_COLOR[0]) < THRESHOLD &&
Math.abs(Color.green(pixel) - FROM_COLOR[1]) < THRESHOLD &&
Math.abs(Color.blue(pixel) - FROM_COLOR[2]) < THRESHOLD;
}
Above code will change the color to transparent and below code will split the bitmap into 9 same size bitmaps:
public void splitBitmap(Bitmap bitmap) {
ArrayList<Bitmap> smallimages = new ArrayList<>(9);
int width, height;
// Divide the original bitmap width by the desired vertical column count
width = bitmap.getWidth() / 3;
// Divide the original bitmap height by the desired horizontal row count
height = bitmap.getHeight() / 3;
// Loop the array and create bitmaps for each coordinate
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
// Create the sliced bitmap
smallimages.add(Bitmap.createBitmap(bitmap, x * width, y * height, width, height));
}
}
}
At last, you can use PorterDuffColorFilter on every bitmap:
imageView.setImageDrawable(arrayList.get(0));
imageView.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP);
There can be problems as it works for me and might not for you but this is the way you can achieve your needed result.
If any problem persists, I can help.

android get bitmap of imageview same as seen on screen

i want to get exacly bitmap show on screen after(scale,filtercolor,...) and work with its pixel for example in order to remove transparent pixel :
for (int y = 0; y < sourceBitmap1.getHeight(); y++)
for (int x = 0; x < sourceBitmap1.getWidth(); x++)
if (sourceBitmap1.getPixel(x, y) == Color.TRANSPARENT) {
//todo do something
}
but it is important to get bitmap related to target Imageview. as i see other post can do this with this method:
public static Bitmap loadBitmapFromView(ImageView i) {
i.setDrawingCacheEnabled(true);
i.measure(FrameLayout.MeasureSpec.makeMeasureSpec(0, FrameLayout.MeasureSpec.UNSPECIFIED),
FrameLayout.MeasureSpec.makeMeasureSpec(0, FrameLayout.MeasureSpec.UNSPECIFIED));
i.layout(0, 0, i.getMeasuredWidth(), i.getMeasuredHeight());
i.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(i.getDrawingCache(true));
i.setDrawingCacheEnabled(false);
return b;
}
but method return null , any idea?
thanks in advanced
try this to get bitmap from imageview
Bitmap bitmap = ((BitmapDrawable) imgview.getDrawable()).getBitmap();

createBitmap not loading subimage correctly OR draw(Canvas) not displaying properly

I have a resource, "cards.png" which contains all of the cards needed for a deck of cards.
The resource is exactly 896x352, and each card is exactly 64x88.
The "Card" object is a simple one, with a string for the suit, a string for the value, and a bitmap.
I use "Bitmap.createBitmap" to create a subimage from the big original one.
Later, when I draw, it did not appear that the function loaded the images properly. Some cards are "offset" by a number of pixels, and it seems to get worse as I try to read the image from left to right.
I have tried everything, and found that there are a lot of unanswered similar questions here, so wondering if I am going about this the wrong way?
The resource "R.drawable.cards" is referenced in the "/game/res/drawable" folder.
The code for loading the card bitmaps is:
public GameScreen(Context context){
int x=0, y=0;
Bitmap cards = BitmapFactory.decodeResource(context.getResources(), R.drawable.cards);
for (Card card: deck.getCards()){
if (card.getSuit().equals("C")){
y = 0;
} else if (card.getSuit().equals("D")){
y = 88;
} else if (card.getSuit().equals("H")){
y = 176;
} else if (card.getSuit().equals("S")){
y = 264;
} else {
x=0;
y=0;
}
if (card.getValue().equals("A")){
x = 0;
} else if (card.getValue().equals("10")){
x = 576;
} else if (card.getValue().equals("J")){
x = 640;
} else if (card.getValue().equals("Q")){
x = 704;
} else if (card.getValue().equals("K")){
x = 768;
} else if (card.getValue().equals("Joker")){
// Joker
x = 832;
} else {
x = 64 * (Integer.parseInt(card.getValue())-1);
}
Bitmap bitmap = Bitmap.createBitmap(cards, x, y, CardBitmapWidth, CardBitmapHeight);
card.setBitmap(bitmap);
}
}
The code to draw is:
public void draw(Canvas canvas){
int x = 0;
int y = 0;
for (Card card: cards){
canvas.drawBitmap(card.getBitmap(), x, y, null);
x += card.getBitmap().getWidth();
if (x>canvas.getWidth()){
x = 0;
y += card.getBitmap.getHeight();
}
}
}
Make sure the image is not being scaled when loaded:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap cards = BitmapFactory.decodeResource(context.getResources(), R.drawable.cards, options);

Create 1 imageView with 9 image Files

I searched from a way to create a single imageView from 9 image files like this :
IMG1 - IMG2 - IMG3
IMG4 - IMG5 - IMG6
IMG7 - IMG8 - IMG9
I seen several interesting topics that helps me. One of these talks about a solution that may fits my needs. In this topic, Dimitar Dimitrov propose this :
You can try to do it with the raw data, by extracting the pixel data
from the images as 32-bit int ARGB pixel arrays, merge in one big
array, and create a new Bitmap, using the methods of the Bitmap class
like copyPixelsToBuffer(), createBitmap() and setPixels().
source : Render Two images in ImageView in Android?
So i may extract the 32-bits ARGB pixels from each image file and then create a Bitmap in which i could use the setPixels function to fill in. The problem is that i don't know how i can "extract the 32-bits ARGB pixels from each image file" ...
I also saw things about canvas and surfaceView but i never uses them. Furthermore the final object will only be sometimes pinched zoomed (when the user wants it), so i think it'll be easier for me to make it works using a single imageView ...
So i began with this portion of code inside an AsyncTask (to avoid using the UI Thread)
but i already get an OUT OF MEMORY Exception
...
#Override
protected Bitmap doInBackground(Void... params) {
return this.createBigBitmap();
}
public Bitmap createBigBitmap() {
Bitmap pageBitmap = Bitmap.createBitmap(800, 1066, Bitmap.Config.ARGB_8888); // OUT OF MEMORY EXCEPTION
// create an ArrayList of the 9 page Parts
ArrayList<Bitmap> pageParts = new ArrayList<Bitmap>();
for(int pagePartNum = 1; pagePartNum <= 9; pagePartNum++){
Bitmap pagePartBitmap = getPagePart(pageNum, pagePartNum);
pageParts.add(pagePartBitmap);
}
// try to copy the content of the 9 bitmaps into a single one bitmap
int[] pixels = null;
int offsetX = 0, offsetY = 0, pagePartNum = 0;
for (int x = 0; x < this.nbPageRows; x++) {
for (int y = 0; y < this.nbPageColumns; y++) {
pagePartNum = x * this.nbPageColumns + y;
Bitmap pagePartBitmap = pageParts.get(pagePartNum);
// read pixels from the pagePartBitmap
pixels = new int[pagePartBitmap.getHeight() * pagePartBitmap.getWidth()];
pagePartBitmap.getPixels(pixels, 0, pagePartBitmap.getWidth(), 0, 0, pagePartBitmap.getWidth(), pagePartBitmap.getHeight());
// compute offsetY
if(x == 0)
offsetY = 0;
if(x == 1)
offsetY = pageParts.get(0).getHeight();
if(x == 2)
offsetY = pageParts.get(0).getHeight() * 2;
// compute offsetX
if(y == 0)
offsetX = 0;
if(y == 1)
offsetX = pageParts.get(0).getWidth();
if(y == 2)
offsetX = pageParts.get(0).getWidth() * 2;
// write pixels read to the pageBitmap
pageBitmap.setPixels(pixels, 0, pagePartBitmap.getWidth(), offsetX, offsetY, pagePartBitmap.getWidth(), pagePartBitmap.getHeight());
offsetX += pagePartBitmap.getWidth();
offsetY += pagePartBitmap.getHeight();
}
}
return pageBitmap;
}
// get a bitmap from one of the 9 existing image file page part
private Bitmap getPagePart(int pageNum, int pagePartNum) {
String imgFilename = this.directory.getAbsolutePath()
+ File.separator + "z-"
+ String.format("%04d", pageNum)
+ "-" + pagePartNum + ".jpg";
// ajoute le bitmap de la partie de page
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeFile(imgFilename, opt);
}
Thank you very much
Read BitmapRegionDecoder and this
Edit
Look at Efficient Bitmap Handling in android to come out from OOM error.
Use following code to decode your bitmap.
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = 4;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}

Making specific color in bitmap transparent

I have an Android application to display an image on another image, such that second image's white colour is transparent. To do this, I have used two ImageViews, with the original image to be overlaid as bitmap1 and the image to be made transparent as bitmap2. When I run this, I get some exceptions at the setPixel method.
Here's my code:
Bitmap bitmap2 = null;
int width = imViewOverLay.getWidth();
int height = imViewOverLay.getHeight();
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
if(bitMap1.getPixel(x, y) == Color.WHITE)
{
bitmap2.setPixel(x, y, Color.TRANSPARENT);
}
else
{
bitmap2.setPixel(x, y, bitMap1.getPixel(x, y));
}
}
}
imViewOverLay is the ImageView of the overlay image. Any idea what might be going wrong in the above code?
The most obvious error is that you're not creating bitmap2 - unless you've not posted all the code of course.
You declare it and set it to null, but then don't do anything else until you try to call bitmap2.setPixel.
i think you need to make it mutable
Loading a resource to a mutable bitmap
i did this
BitmapFactory.Options bitopt=new BitmapFactory.Options();
bitopt.inMutable=true;
mSnareBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.snare, bitopt);
also, i found i needed to set alpha to something less than 255 for it to render the image with transparent background.
mPaint.setAlpha(250);
canvas.drawBitmap(mSnareBitmap, 0, 30, mPaint);
by the way, using white as your transparent color isn't a great idea because you will get aliasing problems at the edges of your opaque objects. i use green because my overlay images don't have any green in (like a green screen in the movies) then i can remove the green inside the loop and set the alpha value based on the inverse of the green value.
private void loadBitmapAndSetAlpha(int evtype, int id) {
BitmapFactory.Options bitopt=new BitmapFactory.Options();
bitopt.inMutable=true;
mOverlayBitmap[evtype] = BitmapFactory.decodeResource(getResources(), id, bitopt);
Bitmap bm = mOverlayBitmap[evtype];
int width = bm.getWidth();
int height = bm.getHeight();
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
int argb = bm.getPixel(x, y);
int green = (argb&0x0000ff00)>>8;
if(green>0)
{
int a = green;
a = (~green)&0xff;
argb &= 0x000000ff; // save only blue
argb |= a; // put alpha back in
bm.setPixel(x, y, argb);
}
}
}
}

Categories

Resources