I am doing a Face Recognition project for my final year. I have to do face Recognition on Android using Local Binary Pattern(LBP).
I searched a lot on the internet for codes for face recognition using LBP in java, but couldn't find anything implementable on android. So now I am forced to writing it all, and I am a kind of a newbie to android as well as image processing.
I have found out a way to capture images from the camera.
public class CameraCapture extends Activity {
protected boolean _taken = true;
File sdImageMainDirectory;
protected static final String PHOTO_TAKEN = "photo_taken";
#Override
public void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
File root = new File(Environment
.getExternalStorageDirectory()
+ File.separator + "myDir" + File.separator);
root.mkdirs();
sdImageMainDirectory = new File(root, "myPicName");
startCameraActivity();
}
catch (Exception e) {
finish();
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
}
protected void startCameraActivity() {
Uri outputFileUri = Uri.fromFile(sdImageMainDirectory);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 0);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (resultCode) {
case 0:
finish();
break;
case -1:
try {
StoreImage(this, Uri.parse(data.toURI()),
sdImageMainDirectory);
} catch (Exception e) {
e.printStackTrace();
}
finish();
startActivity(new Intent("com.piit.lbp.form.LBPFORMADD"));
}
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.getBoolean(CameraCapture.PHOTO_TAKEN)) {
_taken = true;
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(CameraCapture.PHOTO_TAKEN, _taken);
}
public static void StoreImage(Context mContext, Uri imageLoc, File imageDir) {
Bitmap bm = null;
try {
bm = Media.getBitmap(mContext.getContentResolver(), imageLoc);
bmGray = toGrayScale(bm);
FileOutputStream out = new FileOutputStream(imageDir);
bm.compress(Bitmap.CompressFormat.JPEG, 100, out);
bm.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Question : What is the "Bitmap bm" - like RGB_565, or something else ?? and how many bits.
Before compressing bitmap to jpeg I call a RGB to Grayscale method with the following code
public static Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
And then I wish to use bmGray for applying LBP operator.
Question : When you convert to Grayscale using ColorMatrix, is it 8bits per pixel ??
Cos I want to convert bmGray to Byte Array and want to extract only 1 byte at a time. And also I want to know if can convert the grayscale image to a 2d matrix of pixel values, I know that it is already a 2d matrix of pixel values, but how can i work on it.. like selecting the pixel above and below the current pixel. ??
for the CameraPicture this applies:
If setPreviewFormat(int) is never called, the default will be the
YCbCr_420_SP (NV21) format.
http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFormat%28int%29
Bitmap bmp you can configure like:
Bitmap bmp = Bitmap.createBitmap(frameWidth, frameHeight, Bitmap.Config.ARGB_8888); //or RGB_565 if you prefer.
for accessing bmp data I only found something like this: http://upload.wikimedia.org/wikipedia/commons/c/c4/BMPfileFormat.png
hope it helps
Related
[Edit: I've made a minimal project to try to narrow down what's going on. The code at the bottom still generates the same artifacts when saved]
I have an app that draws simple 2D geometry using Paths. The shapes are all solid colors, sometimes with alpha < 255, and may be decorated with lines. In the View that draws the geometry, there has never been an issue with how things get drawn. However, when I use the same code to draw to a Bitmap, and then save it as either a JPEG (with 100 quality) or PNG, there is always the same artifacting in the solid-colored areas of the output files. It's a sort of mottling that is usually associated with JPEG compression.
Screenshot of View:
Saved image:
Zoom in on artifacts:
I have tried the following
Saving to either PNG and JPEG
Turning dithering and antialiasing on and off
Increasing the DPI of the Bitmap, and also allowed the Bitmap to use its default API
Applying the matrix I use as a camera to the geometric representation, instead of applying it to the Canvas for the bitmap
Turning HW Acceleration on and off app-wide
Using a 3rd party library to save the Bitmap to a .bmp file
All yield the same artifacts, neither making it worse nor better.
public class MainActivity extends AppCompatActivity {
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.context = getApplicationContext();
}
// button OnClick listener
public void saveImage(View view) {
new saveBitmapToDisk().execute(false);
}
public Bitmap getBitmap() {
final int bitmapHeight = 600, bitmapWidth = 600;
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(bitmap);
float[] triangle = new float[6];
triangle[0] = bitmapWidth / 2;
triangle[1] = 0;
triangle[2] = 0;
triangle[3] = bitmapHeight / 2;
triangle[4] = bitmapWidth / 2;
triangle[5] = bitmapHeight / 2;
Path solidPath = new Path();
Paint solidPaint = new Paint();
solidPaint.setStyle(Paint.Style.FILL);
solidPath.moveTo(triangle[0], triangle[1]);
for(int i = 2; i < triangle.length; i += 2)
solidPath.lineTo(triangle[i], triangle[i+1]);
solidPath.close();
solidPaint.setColor(Color.GREEN);
bitmapCanvas.drawPath(solidPath, solidPaint);
return bitmap;
}
private class saveBitmapToDisk extends AsyncTask<Boolean, Integer, Uri> {
Boolean toShare;
#Override
protected Uri doInBackground(Boolean... shareFile) {
this.toShare = shareFile[0];
final String appName = context.getResources().getString(R.string.app_name);
final String IMAGE_SAVE_DIRECTORY = String.format("/%s/", appName);
final String fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() + IMAGE_SAVE_DIRECTORY;
File dir, file;
try {
dir = new File(fullPath);
if (!dir.exists())
dir.mkdirs();
OutputStream fOut;
file = new File(fullPath, String.format("%s.png", appName));
for (int suffix = 0; file.exists(); suffix++)
file = new File(fullPath, String.format("%s%03d.png", appName, suffix));
file.createNewFile();
fOut = new FileOutputStream(file);
Bitmap saveBitmap = getBitmap();
saveBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} catch (OutOfMemoryError e) {
Log.e("MainActivity", "Out of Memory saving bitmap; bitmap is too large");
return null;
} catch (Exception e) {
Log.e("MainActivity", e.getMessage());
return null;
}
return Uri.fromFile(file);
}
#Override
protected void onPostExecute(Uri uri) {
super.onPostExecute(uri);
Toast.makeText(context, "Image saved", Toast.LENGTH_SHORT).show();
}
}
}
I tested your program with PNG and the file has no artifacts
These artifacts are a result of JPEG compression
Edit:
The line
MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
was causing the conversion to jpeg.
The proper way to save the image is
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/png");
values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
context.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
Here is my simplified test program that sends the generated file directly
public class Test2Activity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new saveBitmapToDisk().execute();
}
public Bitmap getBitmap() {
final int bitmapHeight = 600, bitmapWidth = 600;
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(bitmap);
Paint solidPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
solidPaint.setStyle(Paint.Style.FILL);
solidPaint.setColor(Color.RED);
bitmapCanvas.drawCircle(300, 300, 200, solidPaint);
return bitmap;
}
private class saveBitmapToDisk extends AsyncTask<Void, Void, Uri> {
Boolean toShare;
#Override
protected Uri doInBackground(Void... shareFile) {
Context context = Test2Activity.this;
try {
File file = new File(context.getExternalFilesDir(null), "test.png");
FileOutputStream fOut = new FileOutputStream(file);
Bitmap saveBitmap = getBitmap();
saveBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
return Uri.fromFile(file);
} catch (OutOfMemoryError e) {
Log.e("MainActivity", "Out of Memory saving bitmap; bitmap is too large");
return null;
} catch (Exception e) {
Log.e("MainActivity", e.getMessage());
return null;
}
}
#Override
protected void onPostExecute(Uri uri) {
Context context = Test2Activity.this;
Toast.makeText(context, "Image saved", Toast.LENGTH_SHORT).show();
final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/png");
Test2Activity.this.startActivity(intent);
}
}
}
Artifacts like this are natural and unavoidable consequence of JPEG compression.
They should not crop up in PNG compression. If you are getting such artifacts when you create a PNG file, I'd wager that you are not creating a PNG stream at all, but rather a JPEG stream in a file with a PNG extension. No decent decoder relies on the file extension.
I noticed two things in your code:
1) The filename you save to is String.format("%s.jpg", appName) or String.format("%s%03d.png", appName, suffix) independent of the actual encoding.
2) The bitmap you save has its density determined by prefs.saveImageDensity().get() so it may not be the same as the actual density of the bitmap you see on the screen.
Maybe you confused yourself with 1) or perhaps 2) causes the compression-artefacts you're seeing?
Can anyone tell me how to convert imageview to bitmap? In my app, i'm accessing the gallery and getting a bitmap of a picture into an imageview, then using picasso, i'm resizing the images that are too big to directly uploaded to parse. I can resize the image in the image view using picasso but how do i get the bitmap from the image view to upload to parse? this is my code..
public static final int IMAGE_GALLERY_REQUEST = 20;
private ImageView imgPicture;
public Bitmap image;
public void openGallery(View view){
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);//
startActivityForResult(Intent.createChooser(intent, "Select Picture"),IMAGE_GALLERY_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
// if we are here, everything processed successfully.
if (requestCode == IMAGE_GALLERY_REQUEST) {
Uri imageUri = data.getData();
InputStream inputStream;
try {
inputStream = getContentResolver().openInputStream(imageUri);
image = BitmapFactory.decodeStream(inputStream);
height= image.getHeight();
h= String.valueOf(height);
width= image.getWidth();
w= String.valueOf(width);
if (width>800 || height>600)
{
Picasso.with(this)
.load(imageUri)
.resize(800,600)
.centerCrop()
.into(imgPicture);
// imgPicture.setImageBitmap(image);
//what should i write here to convert this imageview to bitmap? and then later use that bitmap to upload the image to parse?
}
else
{
//do nothing
imgPicture.setImageBitmap(image);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
// show a message to the user indictating that the image is unavailable.
Toast.makeText(this, "Unable to open image", Toast.LENGTH_LONG).show();
}
}
}
}
You only can generate the bitmap from imageview but not in real image size, this generate the bitmap with imageview size
Bitmap bitmap;
try {
bitmap = Bitmap.createBitmap(YOUR_VIEW.getWidth(), YOUR_VIEW.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
YOUR_VIEW.draw(canvas);
File root = Environment.getExternalStoragePublicDirectory(Environment.PICTURES);
String fname = "NAME_OF_FILE.jpg";
file = new File(root, fname);
try {
if (!root.exists()) {
root.mkdir();
}
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
YOUR_VIEW.destroyDrawingCache();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
If you don't wanna save to a file, use this code:
public static Bitmap getScreenViewBitmap(View v) {
v.setDrawingCacheEnabled(true);
// this is the important code :)
// Without it the view will have a dimension of 0,0 and the bitmap will be null
v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false); // clear drawing cache
return b;
}
I have an app that I want to be able to capture a screenshot
Here is my code :
public class Screenshot {
private final View view;
/** Create snapshots based on the view and its children. */
public Screenshot(View root) {
this.view = root;
}
/** Create snapshot handler that captures the root of the whole activity. */
public Screenshot(Activity activity) {
final View contentView = activity.findViewById(android.R.id.content);
this.view = contentView.getRootView();
}
/** Take a snapshot of the view. */
public Bitmap snap() {
Bitmap bitmap = Bitmap.createBitmap(this.view.getWidth(), this.view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
}
but the contents of the surfaceView is saved as black.!!!
Please help me, Thanks...
I hope you have used this solution which was posted here Get screenshot of surfaceView in Android
this thing is explained here Take Screenshot of SurfaceView
The SurfaceView's surface is independent of the surface on which View elements are drawn. So capturing the View contents won't include the SurfaceView.........
I hope this Taking screenshot programmatically doesnt capture the contents of surfaceVIew code can help you out more
public class Cam_View extends Activity implements SurfaceHolder.Callback {
protected static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;
private SurfaceView SurView;
private SurfaceHolder camHolder;
private boolean previewRunning;
final Context context = this;
public static Camera camera = null;
private RelativeLayout CamView;
private Bitmap inputBMP = null, bmp, bmp1;
private ImageView mImage;
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
CamView = (RelativeLayout) findViewById(R.id.camview);//RELATIVELAYOUT OR
//ANY LAYOUT OF YOUR XML
SurView = (SurfaceView)findViewById(R.id.sview);//SURFACEVIEW FOR THE PREVIEW
//OF THE CAMERA FEED
camHolder = SurView.getHolder(); //NEEDED FOR THE PREVIEW
camHolder.addCallback(this); //NEEDED FOR THE PREVIEW
camHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//NEEDED FOR THE PREVIEW
camera_image = (ImageView) findViewById(R.id.camera_image);//NEEDED FOR THE PREVIEW
Button btn = (Button) findViewById(R.id.button1); //THE BUTTON FOR TAKING PICTURE
btn.setOnClickListener(new OnClickListener() { //THE BUTTON CODE
public void onClick(View v) {
camera.takePicture(null, null, mPicture);//TAKING THE PICTURE
//THE mPicture IS CALLED
//WHICH IS THE LAST METHOD(SEE BELOW)
}
});
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,//NEEDED FOR THE PREVIEW
int height) {
if(previewRunning) {
camera.stopPreview();
}
Camera.Parameters camParams = camera.getParameters();
Camera.Size size = camParams.getSupportedPreviewSizes().get(0);
camParams.setPreviewSize(size.width, size.height);
camera.setParameters(camParams);
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning=true;
} catch(IOException e) {
e.printStackTrace();
}
}
public void surfaceCreated(SurfaceHolder holder) { //NEEDED FOR THE PREVIEW
try {
camera=Camera.open();
} catch(Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
finish();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) { //NEEDED FOR THE PREVIEW
camera.stopPreview();
camera.release();
camera=null;
}
public void TakeScreenshot(){ //THIS METHOD TAKES A SCREENSHOT AND SAVES IT AS .jpg
Random num = new Random();
int nu=num.nextInt(1000); //PRODUCING A RANDOM NUMBER FOR FILE NAME
CamView.setDrawingCacheEnabled(true); //CamView OR THE NAME OF YOUR LAYOUR
CamView.buildDrawingCache(true);
Bitmap bmp = Bitmap.createBitmap(CamView.getDrawingCache());
CamView.setDrawingCacheEnabled(false); // clear drawing cache
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata);
String picId=String.valueOf(nu);
String myfile="Ghost"+picId+".jpeg";
File dir_image = new File(Environment.getExternalStorageDirectory()+//<---
File.separator+"Ultimate Entity Detector"); //<---
dir_image.mkdirs(); //<---
//^IN THESE 3 LINES YOU SET THE FOLDER PATH/NAME . HERE I CHOOSE TO SAVE
//THE FILE IN THE SD CARD IN THE FOLDER "Ultimate Entity Detector"
try {
File tmpFile = new File(dir_image,myfile);
FileOutputStream fos = new FileOutputStream(tmpFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
Toast.makeText(getApplicationContext(),
"The file is saved at :SD/Ultimate Entity Detector",Toast.LENGTH_LONG).show();
bmp1 = null;
camera_image.setImageBitmap(bmp1); //RESETING THE PREVIEW
camera.startPreview(); //RESETING THE PREVIEW
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private PictureCallback mPicture = new PictureCallback() { //THIS METHOD AND THE METHOD BELOW
//CONVERT THE CAPTURED IMAGE IN A JPG FILE AND SAVE IT
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File dir_image2 = new File(Environment.getExternalStorageDirectory()+
File.separator+"Ultimate Entity Detector");
dir_image2.mkdirs(); //AGAIN CHOOSING FOLDER FOR THE PICTURE(WHICH IS LIKE A SURFACEVIEW
//SCREENSHOT)
File tmpFile = new File(dir_image2,"TempGhost.jpg"); //MAKING A FILE IN THE PATH
//dir_image2(SEE RIGHT ABOVE) AND NAMING IT "TempGhost.jpg" OR ANYTHING ELSE
try { //SAVING
FileOutputStream fos = new FileOutputStream(tmpFile);
fos.write(data);
fos.close();
//grabImage();
} catch (FileNotFoundException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
}
String path = (Environment.getExternalStorageDirectory()+
File.separator+"Ultimate EntityDetector"+
File.separator+"TempGhost.jpg");//<---
BitmapFactory.Options options = new BitmapFactory.Options();//<---
options.inPreferredConfig = Bitmap.Config.ARGB_8888;//<---
bmp1 = BitmapFactory.decodeFile(path, options);//<--- *********(SEE BELOW)
//THE LINES ABOVE READ THE FILE WE SAVED BEFORE AND CONVERT IT INTO A BitMap
camera_image.setImageBitmap(bmp1); //SETTING THE BitMap AS IMAGE IN AN IMAGEVIEW(SOMETHING
//LIKE A BACKGROUNG FOR THE LAYOUT)
tmpFile.delete();
TakeScreenshot();//CALLING THIS METHOD TO TAKE A SCREENSHOT
//********* THAT LINE MIGHT CAUSE A CRASH ON SOME PHONES (LIKE XPERIA T)<----(SEE HERE)
//IF THAT HAPPENDS USE THE LINE "bmp1 =decodeFile(tmpFile);" WITH THE METHOD BELOW
}
};
public Bitmap decodeFile(File f) { //FUNCTION BY Arshad Parwez
Bitmap b = null;
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int IMAGE_MAX_SIZE = 1000;
int scale = 1;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = (int) Math.pow(
2,
(int) Math.round(Math.log(IMAGE_MAX_SIZE
/ (double) Math.max(o.outHeight, o.outWidth))
/ Math.log(0.5)));
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return b;
}
}
try out this also
public static Bitmap overlay(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);
Log.i("bmOverlay.......",""+bmOverlay);
bmp3=bmOverlay;
return bmOverlay;
}
private void getScreen() {
Toast.makeText(BookType1.this, "saved", Toast.LENGTH_SHORT).show();
File myDir=new File("/sdcard/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".png";
File file = new File (myDir, fname);
try
{
FileOutputStream ostream = new FileOutputStream(file);
bmp3.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
and you can also go through these references which gives you more idea
How to capture screenshot of surfaceview with background
Taking screen shot of a SurfaceView in android
How to take a screenshot of Android's Surface View?
How to programmatically take a screenshot in Android?
I use below code to convert, but it seems can only get the content in the display screen and can not get the content not in the display screen.
Is there a way to get all the content even out of scroll?
Bitmap viewBitmap = Bitmap.createBitmap(mScrollView.getWidth(),mScrollView.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(viewBitmap);
mScrollView.draw(canvas);
We can convert all the contents of a scrollView to a bitmap image using the code shown below
private void takeScreenShot()
{
View u = ((Activity) mContext).findViewById(R.id.scroll);
HorizontalScrollView z = (HorizontalScrollView) ((Activity) mContext).findViewById(R.id.scroll);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
Bitmap b = getBitmapFromView(u,totalHeight,totalWidth);
//Save bitmap
String extr = Environment.getExternalStorageDirectory()+"/Folder/";
String fileName = "report.jpg";
File myPath = new File(extr, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
MediaStore.Images.Media.insertImage(mContext.getContentResolver(), b, "Screen", "screen");
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Bitmap getBitmapFromView(View view, int totalHeight, int totalWidth) {
Bitmap returnedBitmap = Bitmap.createBitmap(totalWidth,totalHeight , Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return returnedBitmap;
}
The Pops answer is really good, but in some case you could have to create a really big bitmap which could trigger a OutOfMemoryException when you create the bitmap.
So I made a little optimization to be gently with the memory :)
public static Bitmap getBitmapFromView(View view, int totalHeight, int totalWidth) {
int height = Math.min(MAX_HEIGHT, totalHeight);
float percent = height / (float)totalHeight;
Bitmap canvasBitmap = Bitmap.createBitmap((int)(totalWidth*percent),(int)(totalHeight*percent), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(canvasBitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
canvas.save();
canvas.scale(percent, percent);
view.draw(canvas);
canvas.restore();
return canvasBitmap;
}
This one works for me
To save the bitmap check runtime permission first
#OnClick(R.id.donload_arrow)
public void DownloadBitMap()
{
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
{
downloadData();
Log.e("callPhone: ", "permission" );
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
Toast.makeText(this, "need permission", Toast.LENGTH_SHORT).show();
}
}
To get bitmap
private void downloadData() {
ScrollView iv = (ScrollView) findViewById(R.id.scrollView);
Bitmap bitmap = Bitmap.createBitmap(
iv.getChildAt(0).getWidth()*2,
iv.getChildAt(0).getHeight()*2,
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
c.scale(2.0f, 2.0f);
c.drawColor(getResources().getColor(R.color.colorPrimary));
iv.getChildAt(0).draw(c);
// Do whatever you want with your bitmap
saveBitmap(bitmap);
}
To save the bitmap
public void saveBitmap(Bitmap bitmap) {
File folder = new File(Environment.getExternalStorageDirectory() +
File.separator + "SidduInvoices");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
// Do something on success
} else {
// Do something else on failure
}
File imagePath = new File(Environment.getExternalStorageDirectory() + "/SidduInvoices/Siddus.png");
if(imagePath.exists())
{
imagePath=new File(Environment.getExternalStorageDirectory() + "/SidduInvoices/Siddus"+custamername.getText().toString()+".png");
}
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
progressBar.cancel();
final File finalImagePath = imagePath;
new SweetAlertDialog(this, SweetAlertDialog.SUCCESS_TYPE)
.setTitleText("Saved")
.setContentText("Do you want to share this with whatsapp")
.setCancelText("No,cancel !")
.setConfirmText("Yes,share it!")
.showCancelButton(true)
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sweetAlertDialog) {
sweetAlertDialog.cancel();
shareImage(finalImagePath);
}
})
.setCancelClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sDialog) {
sDialog.cancel();
}
})
.show();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
You need get the total width and height of the scrollview, or you created viewBitmap is too small to contain the full content of the scrollview.
check this link
Android: Total height of ScrollView
The issue here is that the only actual pixel content that ever exists is that which is visible on the display screen. Android and other mobile platforms are very careful about memory use and one of the ways a scrolling view can maintain performance is to not draw anything that is offscreen. So there is no "full" bitmap anywhere -- the memory containing the content that moves offscreen is recycled.
I have an android app where I'm using the android camera in order to take photos.And after struglling a little bit I managed to have my picture where I want and how I want.The final problem is the quality of the image.
When my preview starts everything looks very clear and great but after taking the photo and showing the final result the image is not looking good at all.
Here is how my surfaceChanged() method looks like-where I'm setting some parameters:
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged");
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
List<Size> sizes = p.getSupportedPictureSizes();
System.out.println("Lista de parametrii este urmatoarea:"+sizes);
Size size = sizes.get(7);
p.setPictureSize(size.width,size.height);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
Coudl someone tell what's the way to increase the quality of my photo.Thanks!
EDIT:
In activity A where the picture is taken I use a bundle to send the image to another activity B where I store it on the SDCARD.Here is how I do it:
Activity A:
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback(){
public void onPictureTaken(byte[] imageData, Camera c) {
if (imageData != null) {
Intent mIntent = new Intent();
Bundle b = new Bundle();
b.putByteArray("imageData", imageData);
Intent i = new Intent(mContext,ImageDisplayActivity.class);
i.putExtras(b);
startActivity(i);
setResult(FOTO_MODE, mIntent);
finish();
}
}
};
in activity B:
Bundle extras = getIntent().getExtras();
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 5;
byte[] imageData = extras.getByteArray("imageData");
Bitmap myImage = BitmapFactory.decodeByteArray(imageData , 0, imageData.length,options);
Matrix mat=new Matrix();
mat.postRotate(90);
bitmapResult = Bitmap.createBitmap(myImage, 0, 0, myImage.getWidth(),myImage.getHeight(), mat, true);
Canvas c = new Canvas(bitmapResult);
drawTextImage(bitmapResult);
I receive the picture I put it in a bitmap, I rotate it and draw a text on it in the method drawTextImage() .
After all this I store the bitmapResult on sdcard using this:
public static boolean StoreByteImage(Context mContext, Bitmap bitmap, int quality, String expName) {
FileOutputStream fileOutputStream = null;
String extStorageDirectory=Environment.getExternalStorageDirectory().toString();
File myNewFolder = new File(extStorageDirectory + newFolder);
if(myNewFolder.mkdirs())
{
myNewFolder.mkdir();
}
try {
//fileOutputStream = new FileOutputStream(sdImageMainDirectory.toString() +"/image.jpg");
fileOutputStream = new FileOutputStream(myNewFolder +"/"+expName+".jpg");
BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
bitmap.compress(CompressFormat.JPEG, quality, bos);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
I ussually call it like this: StoreByteImage(getBaseContext(),bitmapResult,100,String.valueOf(value));
Thanks
I had this issue because auto-focus was disabled.
Try adding this permission to your Android Manifest:
<uses-feature android:name="android.hardware.camera.autofocus" />