Bitmap not saved correctly (from Android's Canvas) - android

I changed my question a bit.
EDIT:
// make textures from text
public static void createTextureFromText(GL10 gl, String text, String texName) {
Paint p = new Paint();
p.setColor(Color.GREEN);
p.setTextSize(32 * getResources().getDisplayMetrics().density);
// get width and height the text takes (in px)
int width = (int) p.measureText(text);
int height = (int) p.descent();
// Create an empty, mutable bitmap based on textsize
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
// get a canvas to paint over the bitmap
Canvas canvas = new Canvas(bmp);
bmp.eraseColor(Color.CYAN); //Cyan for debugging purposes
//draw the text
canvas.drawText(text, 0, 0, p);
// save image - for debugging purposes
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
// create a new file name "test.jpg" in sdcard
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.jpg");
try {
f.createNewFile();
// write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
.... make texture
}
I now have this code in use for creating textures from given text (this is just partially).
But I found the fault lies somewhere in the Bitmap creation. I now save the Bitmap on the sd-card, to see how it turns out and found I get a ALL Cyan bitmap (672B, 164x7 are the dimensions).
Does Anyone see why it doesn't create an Bitmap with text on it? What can I be doing wrong?
You'll be a hero if you could help me :)

Firstly, your text height calculation is wrong. The 'descent' measurement is just the portion of text below the baseline (i.e. the tails of 'g' and 'q' etc). The correct height is ascent+descent, except that since ascent is negative you want:
int height = (int) (p.descent() + -p.ascent());
Secondly, when you drawText() the y coordinate you give it is where the baseline goes, it is not the top or bottom edge. So if you want to fill a bitmap that's just big enough to hold the text, your y coordinate should also be -p.ascent().

Related

how can i get a high quality picture from a view’s screenshots

I want to get the picture of the view(not ImageView) inside,but the picture I got was not clear,Of course the original picture is clear ,here is my codes
public static Bitmap getDrawBitmap(View designView){
designView.destroyDrawingCache();
designView.setDrawingCacheEnabled(true);
designView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
return designView.getDrawingCache();
}
I have tried to scale the View,and then getDrawingCache(),but it didn't work,the view's size didn't change
Bitmap bitmap=ImgUtils.getDrawBitmap(testBtn);
float w=1260f;
float h=1660f;
float x= w/(bitmap.getWidth()/DrawAttribute.density);
float y= h/(bitmap.getHeight()/DrawAttribute.density);
Log.e("x-y",x+"-"+y);
Bitmap result=Bitmap.createBitmap(1260,1660,Bitmap.Config.ARGB_8888);
Canvas offScreen = new Canvas(result);
Matrix matrix=new Matrix();
matrix.setScale(x,y);
offScreen.drawBitmap(bitmap, matrix, null);
//存储路径
OutputStream stream = null;
try {
if (LiApplication.creatDir()) {
stream = new FileOutputStream(Environment.getExternalStorageDirectory()+ "/yc/img/"
+ "save.png");
}
} catch (FileNotFoundException e) {
}
Bitmap.CompressFormat format = Bitmap.CompressFormat.PNG;
result.compress(format, 100, stream);
This is a Demo code for taking screen shot of whole View.
View v = (View) findViewById(R.id.myView);
Bitmap mybitmap = Bitmap.createBitmap(
v.getChildAt(0).getWidth(),
v.getChildAt(0).getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(mybitmap);
iv.getChildAt(0).draw(c);
//remember here View may be any view including ScrollView or what ever it may be.
saveBitmap(bitmap);
Hope this will help. Thanks

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).

not able to extract the drawing cache with overlayed bitmap images

I am trying to save a canvas on an sdcard. Basically I am drawing two bitmaps (one on top of another) in the onDraw(Canvas canvas) method. But when I save the file, only the bottom layered Bitmap is stored. I am posting the code for the onDraw method here:
Paint paint = new Paint();
paint.setColor(Color.BLACK);
//rectangle for the first image
rct = new Rect(10, 10, canvas.getWidth(), canvas.getHeight());
// rectangle for the second image, the secong image is drawn where the user touches the screen
new_image = new RectF(touchX, touchY, touchX + secondBitmap.getWidth(),
touchY + secondBitmap.getHeight());
//this is the bitmap that is drawn first
canvas.drawBitmap(firstBitmap, null, rct, paint);
//this is the bitmap drawn on top of the first bitmap on user touch
canvas.drawBitmap(secondBitmap, null, new_image, paint);
canvas.save();
the code for saving the canvas on the SDcard written on the MainActivity is:
Bitmap bm = canvas.getDrawingCache() // canvas in an object of the class I extended from View
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath();
boolean exists = (new File(path)).exists();
OutputStream outStream = null;
File file = new File(path, "drawn_image" + ".jpg");
try {
outStream = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
The problem is that only the base image(firstBitmap of the onDraw() method) is saved on the SDCard instead of the entire canvas(with both the images). I am new to canvas...So any help would be very appreciated
when getDrawingcache() is called it invalidates the view to get the full cache. so debug your code and check if it is going through each and every line of your onDraw() method in view.

whole viewgroup to bitmap

Is it possible to get a full bitmap from a viewgroup-object?
This code takes a 'screenshot' off the view group that's currently on the screen, but I want the whole view, also what's not currently on the screen.
public void export(ViewGroup view){
view.setDrawingCacheEnabled(true);
view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap bitmap = view.getDrawingCache(true);
}
Here I used ScrollView to get the whole view to bitmap
so Here u can use instead of scrollview anyother view group like linerlayout etc..
Bitmap map = loadBitmapFromView(getApplicationContext(),scrollView);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
map.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
//you can create a new file name "test.jpg" in sdcard folder.
File f = new File("/sdcard" +"/" + "mainemailpdf.jpg");
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
bArray = bytes.toByteArray();
// remember close de FileOutput
fo.close();
and for loadBitmapFromView method is:
public static Bitmap loadBitmapFromView(Context context, View v) {
Toast.makeText(context,
v.getMeasuredHeight() + "::::::::::::" + v.getMeasuredWidth(),
Toast.LENGTH_LONG).show();
if (v.getMeasuredHeight() > 0) {
v.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getWidth(), v.getWidth());
v.draw(c);
return b;
}
return null;
}
I hope it helps :)
Any query let me know.
It is not possible since Android system scales down the bitmap.
For ex - if your bitmap size is 480*800 then its size is 480*800*4 = 1536000.
The multiplication with 4 is because each pixel is 4 bytes - RGBA.
Meaning more than a mega and a half for every unscaled image. If the Android won't scale down image you will probably get
OutOfMemoryException after a few image loadings.
as
you have 3 options:
1) view.draw(canvas) you'll get the visible portion of the image(only what is actually being drawn to the screen)
2) getDrawingCache() - will give you the scaled down image.
3) Create custom view which saves the bitmap to the disk and loads it from there when requested

Crop screenshot in android programmatically

for taking screen shot i have am using below code
public void takeScreenShot(){
File wallpaperDirectory = new File("/sdcard/Hello Kitty/");
if(!wallpaperDirectory.isDirectory()) {
// have the object build the directory structure, if needed.
wallpaperDirectory.mkdirs();
// create a File object for the output file
}
File outputFile = new File(wallpaperDirectory, "Hello_Kitty.png");
// now attach the OutputStream to the file object, instead of a String representation
// create bitmap screen capture
Bitmap bitmap;
View v1 = mDragLayer.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache(),0,0,v1.getWidth(),v1.getHeight());
v1.setDrawingCacheEnabled(false);
OutputStream fout = null;
try {
fout = new FileOutputStream(outputFile);
// Bitmap bitMap = Bitmap.createBitmap(src)
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
and now i want a cropped bitmap in that i want to crop some portion from left and some portion from bottom so i have used code like this
Bitmap.createBitmap(v1.getDrawingCache(),v1.getWidth()/10,v1.getHeight()/10,v1.getWidth(),v1.getHeight());
but i got an error
08-29 23:41:49.819: E/AndroidRuntime(3486): java.lang.IllegalArgumentException: x + width must be <= bitmap.width()
08-29 23:41:49.819: E/AndroidRuntime(3486): at android.graphics.Bitmap.createBitmap(Bitmap.java:410)
08-29 23:41:49.819: E/AndroidRuntime(3486): at android.graphics.Bitmap.createBitmap(Bitmap.java:383)
can anybody tell me how to crop portion of an bitmap from left and bottom thanks...
It appears you misunderstood the usage of that specific Bitmap.create(...) function. Rather than supplying the source's width and height as the last two parameters, you should specificy the width and height the cropped result should end up with.
The error explains that since you specified an offset from the left and top, but passed in the source's dimensions, the cropped result would exceed the bounds of the original image.
If all you want to do is crop a tenth off the left and top, simply subtract the offsets from the original width/height:
Bitmap source = v1.getDrawingCache();
int x = v1.getWidth()/10;
int y = v1.getHeight()/10
int width = source.getWidth() - x;
int height = source.getHeight() - y;
Bitmap.createBitmap(source, x, y, width, height);
Instead of using
Bitmap.createBitmap(v1.getDrawingCache(),v1.getWidth()/10,v1.getHeight()/10,v1.getWidth(),v1.getHeight());
You can use bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Refer here for some more methods Bitmap

Categories

Resources