Generating rotated bitmaps without resizing - android

I'm trying to build a ring from twenty copies of a single image, which is a 1/20th slice of the full ring. I generate bitmaps that are this original image rotated to their correct degree amounts. The original image is a 130x130 square
The code that generates the rotated slices looks like this:
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.battery_green);
FileOutputStream fos;
for(int i = 0; i < 20; i++) {
String idName = "batt_s_"+i;
Matrix m = new Matrix();
m.setRotate((i * 18)-8, bmp.getWidth()/2, bmp.getHeight()/2);
Bitmap newBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
try {
fos = context.openFileOutput(idName+"_"+color+".png", Context.MODE_WORLD_READABLE);
newBmp.compress(CompressFormat.PNG, 100, fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
m.reset();
BattConfigureSmall.saveInitPref(context, true);
}
The ImageViews that these generated bitmaps are eventually being slotted into all have scaleType="center" in their XML. However, the generated output looks like this:
Not exactly a perfect ring. The slices themselves, if rotated correctly, do make a perfect ring, because in API level 11 and up I'm using the android:rotate XML attribute on these ImageViews, but I need to support API levels 7-10 as well, so can anybody give me some advice? Thank you.

Don't use the matrix with createBitmap for this scenario, it'll do some odd things with image sizing, I think. Instead, create a new Bitmap and Canvas then draw to it with the matrix:
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.battery_green);
FileOutputStream fos;
Paint paint = new Paint();
paint.setAntiAlias(true);
Matrix m = new Matrix();
for(int i = 0; i < 20; i++) {
String idName = "batt_s_"+i;
m.setRotate((i * 18)-8, bmp.getWidth()/2, bmp.getHeight()/2);
Bitmap newBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBmp);
canvas.drawBitmap(bmp, m, paint);
try {
fos = context.openFileOutput(idName+"_"+color+".png", Context.MODE_WORLD_READABLE);
newBmp.compress(CompressFormat.PNG, 100, fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
m.reset();
BattConfigureSmall.saveInitPref(context, true);
}

Related

Cropping Image view

i M passing a bitmap from one activity to other, after taking the screen shot
Bitmap bitmap;
bitmap = takeScreenshot();
try {
//Write file
String filename = "bitmap.png";
FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
//Cleanup
stream.close();
bitmap.recycle();
//Pop intent
Intent in1 = new Intent(this, FinalImageShare.class);
in1.putExtra("image", filename);
startActivity(in1);
} catch (Exception e) {
e.printStackTrace();
}
here i am getting the image in other activity , the problem is that the tool bar height is also coming (i m hiding the toool bar by setVisibility, )i want to crop the image so that toolbar height wont come.TIA
imageView=(ImageView)findViewById(R.id.imageView);
String filename = getIntent().getStringExtra("image");
try {
FileInputStream is = this.openFileInput(filename);
bmp = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
You can use createBitmap method, like so:
resizedbitmap = Bitmap.createBitmap(bitmap, 0, 0, yourwidth, yourheight);
Where bitmap is the bitmap you create, and resizedbitmap is the cropped one.
createBitmap() method takes as parameter in this case: bitmap, start X, start Y, width and height.
You can use those two methods to get your width and height:
bitmap.getWidth(), bitmap.getHeight()
Check also this link to learn about the createBitmap method:
Developer site
Or you can use the drawing cache property for this, like this :
View main = findViewById(R.id.view);
Bitmap screenshot;
main.setDrawingCacheEnabled(true);
screenshot = Bitmap.createBitmap(main.getDrawingCache());
main.setDrawingCacheEnabled(false);
Or similar to the last one, ctx.getWindow().getDecorView() View to get full screen bitmap cache:
View view = ctx.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
Bitmap bmap = view.getDrawingCache();
int contentViewTop = ctx.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop(); /* skip status bar in screenshot */
Storage.shareBitmapInfo = Bitmap.createBitmap(bmap, 0, contentViewTop, bmap.getWidth(), bmap.getHeight() - contentViewTop, null, true);
view.setDrawingCacheEnabled(false);
Hope this helps!

Android || Rotation of Bitmap Image

Please suggest me the way to rotate the bitmap image in android.
I have following sample but when I rotate the image with 10 degrees it gets black at corners as well as size of image is increased.
When i rotate image continuously with 10 degrees it throw memory out of bound exception.
private void rotateImage(String sourcePath, float angle) {
Bitmap bitmap = BitmapFactory.decodeFile(sourcePath);
Matrix matrix = new Matrix();
matrix.setRotate(angle);
Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
File file = new File(sourcePath);
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file);
rotated.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close();
bitmap.recycle();
rotated.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
Try ExifInterface for image rotation
check this solution for details, how to use ExifInterface
See more info about Exif

android: how to rotate bitmap foreground without rotating background

I have a project that needs to rotate a bitmap, the bitmap is in GRAYSCALE/Black and White mode. When I rotate that bitmap, it works but the background (the white part of the bitmap) is rotated too. Is there anyway to rotate just the foreground (the non white part of the bitmap) only? or if I must create a new function to do that, can you explain the algorithm?
Thanks for your help..
I edit for the relevant code :
int i;
InputStream inStream = context.getResources().openRawResource(R.raw.register2);
BufferedInputStream bis = new BufferedInputStream(inStream, 8000);
DataInputStream dis=new DataInputStream(bis);
byte[] music=null;
try {
music = new byte[inStream.available()];
i=0;
while(dis.available()>0)
{
music[i]=dis.readByte();
i++;
}
dis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap bm = Bitmap.createBitmap(260, 300, Bitmap.Config.ARGB_8888);
ByteBuffer byteBuff=ByteBuffer.allocate(260*300);
bm.setHasAlpha(false);
if(false)
byteBuff.put(music);
int[] intbuffer = new int[260*300];
for (int x=0; x<intbuffer.length; ++x)
intbuffer[x] = (int) music[x];
bm.setPixels(intbuffer, 0, 260, 0, 0, 260, 300);
//img1.setImageBitmap(bm);
//Canvas canvas=new Canvas(bm);
Matrix matrix=new Matrix();
matrix.postRotate(-90);
Bitmap rotated=Bitmap.createBitmap(bm, 0, 0, 260, 300, matrix, true);
//matrix.setRotate(4,bm.getWidth()/2,bm.getHeight()/2);
//canvas.drawBitmap(bm, matrix, new Paint());
img1.setImageBitmap(rotated);
Given that your foreground and background pixels are diff in color-
You need to extract/separate out your foreground pixels and background pixels in two different bitmaps. The two new bitmaps that you create should only have the pixels extracted from your original bitmap rest everything should be transparent.
Once you have your foreground and background bitmap separated , just rotate your foreground and then merge back.

Bitmap.getPixel only returning 0

I have the following code for creating a bitmap:
public PixelMapper(Path inputPath){
RectF src = new RectF();
inputPath.computeBounds(src, true);
int width = (int)src.width()+1;
int height = (int)src.height()+1;
largeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Paint canvasPaint = new Paint();
canvasPaint.setAntiAlias(false);
canvasPaint.setColor(Color.BLACK);
canvasPaint.setStyle(Style.STROKE);
canvasPaint.setStrokeWidth(5);
Canvas canvas = new Canvas(largeBitmap);
canvas.drawPath(inputPath, canvasPaint);
bitmap = Bitmap.createScaledBitmap(largeBitmap, SIDE_OF_BITMAP, SIDE_OF_BITMAP, true);
bitmap = Bitmap.createBitmap(bitmap);//so that a immutable bitmap is created
drawPixelMap();
}
public void drawPixelMap(){
for(int x=0; x<bitmap.getWidth(); x++){
String msg="";
for(int y=0; y<bitmap.getHeight(); y++){
msg = Integer.toHexString( bitmap.getPixel(x,y) );
Log.v("bitmap", msg);
}
}
}
int[] pixels = new int[64];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, SIDE_OF_BITMAP, SIDE_OF_BITMAP);
bitmap.setPixels(pixels, 0, 8, 0, 0, 8, 8);
for ( int pixel : pixels)
Log.v("bitmap", Integer.toHexString(pixel) );
The problem is that all the log messages are "0": both getPixel and getPixels return "0". What is worse is that if I remove the line bitmap.getPixels(...); and leave the bitmap.setPixels(...) line,the image is still drawn as before. It seems that the bitmap variable is just a reference and a bitmap doesn't exist, and for some reason, I am unable to get those pixels.
I know the bitmap is created as required as I am able to view it on a ImageView. It shows black and white pixels with a few grey ones too. Code:
Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, 128, 128, false);
imageView1.setImageBitmap(newBitmap);
The SIDE_OF_BITMAP = 8, all classes (Path, Bitmap, Canvas) are of android.
I tried saving the bitmap to file with the following code:
public String saveToStorage(String fileName){
if( !storageDir.exists() )
storageDir.mkdirs();
File file = new File(storageDir, fileName + ".png");
try{
OutputStream out = new FileOutputStream(file);
boolean result = bitmap.compress(CompressFormat.PNG, 100, out);
out.close();
return Boolean.toString(result);
}
catch (FileNotFoundException e){
Log.e("save", "cannot save file", e);
return "File not found exception";
}
catch (IOException e){
Log.e("save", "IO error", e);
return "IO Exception";
}
}
but it returns "false" i.e. the bitmap.compress method returns false. Please give me any help at all, not necessarily sample code.
I found my mistake. It lies in the line
largeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
The Bitmap.Config.ALPHA_8 only creates a mask. It does not create actual pixels. That is why I was getting the erroneous results. However, when I was setting it to a ImageView I was getting the required result because its background (by default) is white.
I solved my problem by changing the Bitmap.Config.ALPHA_8 to Bitmap.Config.ARGB_8888
The line
bitmap = Bitmap.createBitmap(bitmap);
creates a immutable bitmap of the same dimension/color depth, etc as the source bitmap, but not converting the source bitmap from mutable to immutable. So your new bitmap is blank.
You can first create a immutable bitmap using newBitmap = Bitmap.createBitmap(int[], int, int, Bitmap.Config), then create a canvas for it by canvas = new Canvas(newBitmap). Your bitmap can now be copied to newBitmap by canvas.drawBitmap(bitmap, 0, 0, null).

Android Rotate Picture before saving

I just finished my camera activity and it's wonderfully saving the data.
What I do after the picture is taken:
protected void savePictureData() {
try {
FileOutputStream fs = new FileOutputStream(this.photo);
fs.write(this.lastCamData);
fs.close(); //okay, wonderful! file is just written to the sdcard
//---------------------
//---------------------
//TODO in here: dont save just the file but ROTATE the image and then save it!
//---------------------
//---------------------
Intent data = new Intent(); //just a simple intent returning some data...
data.putExtra("picture_name", this.fname);
data.putExtra("byte_data", this.lastCamData);
this.setResult(SAVED_TOOK_PICTURE, data);
this.finish();
} catch (IOException e) {
e.printStackTrace();
this.IOError();
}
}
What I want to is already as comment given in the code above. I dont want the image just to be saved to file but to be rotated and then saved! Thanks!
//EDIT: What I am currently up to (Works but still runs into memory issues with large images)
byte[] pictureBytes;
Bitmap thePicture = BitmapFactory.decodeByteArray(this.lastCamData, 0, this.lastCamData.length);
Matrix m = new Matrix();
m.postRotate(90);
thePicture = Bitmap.createBitmap(thePicture, 0, 0, thePicture.getWidth(), thePicture.getHeight(), m, true);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
thePicture.compress(CompressFormat.JPEG, 100, bos);
pictureBytes = bos.toByteArray();
FileOutputStream fs = new FileOutputStream(this.photo);
fs.write(pictureBytes);
fs.close();
Intent data = new Intent();
data.putExtra("picture_name", this.fname);
data.putExtra("byte_data", pictureBytes);
this.setResult(SAVED_TOOK_PICTURE, data);
this.finish();
Read the path from sd card and paste the following code...It'll Replace the existing photo after rotating it..
Note: Exif doesn't work on most of the devices, it returns incorrect data so it's good to hard code the rotation before saving to any degree you want to, Just change the angle value in postRotate.
String photopath = tempphoto.getPath().toString();
Bitmap bmp = BitmapFactory.decodeFile(photopath);
Matrix matrix = new Matrix();
matrix.postRotate(90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
FileOutputStream fOut;
try {
fOut = new FileOutputStream(tempphoto);
bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
fOut.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Before you create your FileOutputStream you can create a new Bitmap from the original that has been transformed using a Matrix. To do that you would use this method:
createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
Where the m defines a matrix that will transpose your original bitmap.
For an example on how to do this look at this question:
Android: How to rotate a bitmap on a center point
bitmap = RotateBitmap(bitmap, 90);
public static Bitmap RotateBitmap(Bitmap source, float angle)
{
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}

Categories

Resources