I need to convert an int array into a Bitmap. Here is what I've tried (assume that myBmp is an array of ints that represent pixel values).
Bitmap myBmp = Bitmap.createBitmap(outBmp, 100, 100, Bitmap.Config.ARGB_8888);
ImageView imgView = (ImageView)findViewById(R.id.imgView);
imgView.setImageBitmap(myBmp);
What is supposed to happen is that I see the image being displayed on screen (after the array becomes that image). However, all I see is an empty screen.
Is there an alternative way to take an int[] array and convert it into a Bitmap, or am I just doing something wrong?
Related
I have an application that currently takes black and white 176 x 144 images via camera2 in jpeg format and saves it to storage. In addition to this, I also need an int/float array where each point corresponds to the intensity of one pixel from the jpeg image. As the image is black and white this array of numbers should be sufficient to reconstruct my image by simply plotting it as a heatmap along the appropriate dimensions, as only one value per pixel is needed in black and white space.
The way I have found to do this is to convert the jpeg into a byte array into a bitmap into an int array of sRGB values into an int array of R values. This does work (code below), but seems like a really longwinded and inefficient way of doing this. Is anyone able to suggest a more direct way? Such as getting pixel values directly from the original jpeg Image?
// Convert photo (176 x 144) to byte array (1x25344)
Image mImage = someImage // jpeg capture from camera
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
//Save photo as jpeg
savePhoto(bytes);
//Save pixel values by converting to Bitmap first
Bitmap image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
int x = image.getWidth();
int y = image.getHeight();
int[] intArray = new int[x * y];
image.getPixels(intArray, 0, x, 0, 0, x, y);
for(int i = 0; i < intArray.length; i++) {
intArray[i] = Color.red(intArray[i]); //Any colour will do
}
//Save pixel values
saveIntArray(intArray);
i'm trying to draw a Bitmap but only with a selected area from the original Bitmap or Imageview. The requirement is that the final picture must show only 1/3 from the top of the original Bitmap. I attach a draft. I suppose that i should use canvas, but i do not know exactly how it works.
Thanks in advance!!
Bitmap getTheReducedBitmap(Bitmap fullLengthBitnap)
{
Bitmap backDrop=Bitmap.createBitmap(fullLengthBitnap.getWidth(), fullLengthBitnap.getHeight()/3, Bitmap.Config.RGB_565);
Canvas can = new Canvas(backDrop);
can.drawBitmap(fullLengthBitnap, 0, 0, null);
return backDrop;
}
This is the documentation for the method you should use.
private void draw(Canvas c, Bitmap bmp){
Rect r=new Rect(0,0,bmp.width,bmp.height/3);
Rect drawR=new Rect(0,0,c.width,c.height/3);
c.drawBitmap(bmp,r,drawR,null);
}
or as a one liner:
c.drawBitmap(bmp,new Rect(0,0,bmp.width,bmp.height/3),new Rect(0,0,c.width,c.height/3),null);
It allows you to specify where on the canvas you want to draw it too, and where you want the segment to be from.
#Eu.Dr. 's answer would not work if you wanted to draw anything else on the canvas below it.
val newBitmap=Bimtap
.createBitmap(your_view.width,your_view.height,Bitmap.Config.ALPHA_8)
//note: for tablet mode your_view.width,height will increase drastically so
//you might want
//to fix the size of drawing area for optimization
//ALPHA_8 each pixel requires 1 byte of memory.
//RGB_565 Each pixel is stored on 2 bytes
//ARGB_8888 Each pixel is stored on 4 bytes
//after this you can further apply the compress like
[Refer more from google][1]
val stream = ByteArrayOutputStream();
newBitmap.compress(Bitmap.CompressFormat.PNG, 80, stream);
val byteArray = stream.toByteArray(); // convert drawing photo to byte array
// save it in your internal storage.
val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES
+"attendance_sheet.png");
try{
val fo = FileOutputStream(storageDir);
fo.write(byteArray);
fo.flush();
fo.close();
}catch(Exception ex){
}
I am trying to capture an image from the camera intent and then apply an image filter on it. To elaborate the image would be an image captured by the camera and the image filter would be available in the resources as a png file. I am able to overlay the filter on top of the original image. But, once overlay-ed the original image is 'almost' invisible (which means that the filter is infact being stacked on the original image and not merely replacing it). I have a couple of images to illustrate my problem. The first image was in Photoshop - when I placed a filter on top of an image, it seemed just fine. The second image is the produced by the code cited below - you can clearly see that the filter effect is missing. Would someone have a clue as to why something like this is occurring. Am I missing some logic here?
The following is the code that I have. I apologize if you find any best practices missing here. I am initially trying to test the code:
mPictureView = (ImageView) findViewById(R.id.pictureView);
filterButton = (Button) findViewById(R.id.filter_button1);
// define the threshold fro scaling the image
private final double SCALE_THRESHOLD = 6.0;
// acquire the bitmap (photo captured) from the Camera Intent - the uri is
// passed from a previous activity that accesses the camera and the current
// activity is used to display the bitmap
Uri imageUri = getIntent().getData();
Bitmap imageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
// set the imageView in the current activity to display the picture retrieved
// from the camera
mPictureView.setImageBitmap(imageBitmap);
// get the dimensions of the original bitmap
int photoWidth = imageBitmap.getWidth();
int photoHeight = imageBitmap.getHeight();
filterButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// set the options
Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
// get the image (png file) filter from resources using the options
Bitmap filter = BitmapFactory.decodeResource(getResources(), R.drawable.colorful_filter,options);
// create a scaled copy of the filter
Bitmap filtercopy = Bitmap.createScaledBitmap(filter, (int)(photoWidth/SCALE_THRESHOLD,(int)(photoHeight/SCALE_THRESHOLD), true);
// recycle the used bitmap
filter.recycle();
filter = null;
// get a scaled, mutable copy of the orginial image
Bitmap imagecopy = Bitmap.createScaledBitmap(imageBitmap,(int)(photoWidth/SCALE_THRESHOLD), (int)(photoHeight/SCALE_THRESHOLD),true);
// recycle the used bitmap
imageBitmap.recycle();
imageBitmap = null;
Paint paint = new Paint();
paint.setAntiAlias(true);
//paint.setAlpha(230); - if a discrete value is set, then the image beneath
// the filter is visible. But, I don't understand why I need to do this.
// Besides, that reduces the efficacy of the filter
// create a canvas with the original image as the underlying image
Canvas canvas = new Canvas(imagecopy);
// now, draw the filter on top of the bitmap
canvas.drawBitmap(filtercopy, 0, 0, paint);
// recycle the used bitmap
filtercopy.recycle();
filtercopy = null;
//set the filtered bitmap as the image
mPictureView.setImageBitmap(imagecopy);
}
EDIT 1: I was able to make some progress with the help of the article that Joru has provided. The problem seems to be with blending of the 2 bitmaps. The method drawBitmap would just draw one bitmap over the other in the situation that I have. The following line of code will actually attempt to blend the 2 bitmaps. I have also attached an image which depicts my progress. The underlying bitmap is noticeably more visible now:
paint.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
I have to still play around with it for some time, before achieving the desired output.
You could try a few things:
Bitmap new = old.copy(Config.ARGB_8888, true);
To make sure the bitmap you are opening from MediaStore is in that format. If it isn't, that is likely to cause your problem.
I'm currently working on a steganogrpahy android app as a class project. I've created an object that will encode an image with in another image and return an encoded bitmap. This code is run in a seprate thread.
new Thread(new Runnable()
{
public void run()
{
Bitmap encoded_image = null;
Encryptor encryptor = new Encryptor();
encoded_image = encryptor.encode_image_in_image(
image_location,message_image_location);
}
}).start();
After encoding the bitmap I was passing the bitmap to a file browser activity that I've created to save the bitmap as a png image. This method works for smaller images however, when a large image is encoded and passed to the sub activity the application freezes and returns to the main activity.
private void pass_image_to_file_browser( Bitmap image )
{
Intent intent = new Intent(Encrypt.this,FileBrowser.class);
intent.putExtra( Intent.EXTRA_STREAM, image );
startActivity( intent );
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle bundle = this.getIntent().getExtras();
Bitmap image = bundle.getParacable(Intent.EXTRA_STREAM);
}
I was assuming a large bitmap was to large to send between activities using an intent so I decided to simply save the image in a temporary location and pass the image's location to the sub activity. Which then saves the png image where the user specifies and deletes the temporary image file.
private void save_bitmap( Bitmap image, String location )
{
FileOutputStream fileOutputStream = new FileOutputStream(location);
BufferedOutputStream buffered_output_stream = new
BufferOutputStream(fileOutputStream);
image.compress(CompressFormat.PNG, 0, buffered_output_stream);
buffered_output_stream.flush();
buffered_output_stream.close();
}
This solves the problem of sending a large bitmap from one activity to another however, has created a new problem that I haven't been able to solve. Both the temporary image that is saved before passing the file location to the sub activity and the image file after re saving the image using the file browser have both had their color changed slightly. This color change is unrecognizable to the naked eye but, when decoding the image it causes lots of problems.
One thought I had was that the Bitmap.Config was changing from ARGB_8888 to ARGB_4444 or RGB_565 however, after debug this is not the case. The bitmap is instantiated as an ARGB_8888 and saved as an ARGB_8888 bitmap and never changes in between. The code still works if I pass the entire bitmap to the file browser activity and I'm saving the bitmaps exactly the same in both places. I do not have any thoughts on what else could be causing this. I'm looking for suggestions on what else could be causing the problem. Sorry I was going to post images on the output in both cases however, stack overflow wouldn't let me at my reputation level Thanks.
Ok, after many long wasted hours worrying about the thread and the algorithm I was using to encode the the bitmap the problem was a little simpler. While decoding the image file that was to be encoded with a message I was using options.inPreferredConfig = Config.ARGB_8888; During debugging I was checking to make sure this didn't change to RGB_565. Although the bitmap object was loaded as ARBG_8888 the image file did not contain an alpha channel and thus even though the bitmap had a byte for the alpha level and would allow me to edit the alpha byte of a pixel through Bitmap.setPixel( x, y, color) the bitmap object never recognized that it had alpha values set. When compressing the bitmap compressed to RGB_565 since the object thought that there was no alpha channel. Somehow this problem was resolved by passing the bitmap to a sub activity and parsing it. I'm guessing when object was being recreated the alpha values I had set were recognized. To solve the problem with out passing the bitmap to a subactivity one must add an alpha channel after decoding a bitmap from a file. I found a function to do so here.
private Bitmap adjustOpacity( Bitmap bitmap )
{
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
dest.setPixels(pixels, 0, width, 0, 0, width, height);
return dest;
}
I'm not sure if there is a more efficient method
For anyone who stumbles upon it, like me, wondering why bitnap colors change once you write it out in PNG. I have found out that using bitmap.setPreMultiplied(false) before calling bitmap.compress(PNG, 100, fileout) preserves the color of your image if it has alpha channel values. Setpremultiplied prevents the pixels written onto disk from being multiplied by alpha channel, thus generating different pixel color values.
I'm working with Android and I really need a fast way to get a bitmap of a predetermined size to be filled with a predetermined colour.
The following code is not working for me however;
Bitmap input is a mutable bitmap
int old = input.getPixel(0, 0);
Canvas c = new Canvas(input);
Rect rect = c.getClipBounds(); // The dimensions of the bitmap are returned
c.drawARGB(a, r, g, b);
int n = input.getPixel(0, 0);
if(old==n)
Log.e(TAG, "Values didn't change!");
return input;
Rest assured, the 'old' value and the value of (a|r|g|b) are different but having 'drawn' the colour using a canvas with my mutable bitmap underneath, the bitmap retains it's old value.
I'd be happy with any method that takes a bitmap and a colour value and returns a bitmap filled with that colour.
I didn't provide enough info!
My alpha value was out of range;
int a = 0xFF<<24
So when I called
c.drawARGB(a,r,g,b);
It failed quietly and didn't change the values.