Display an image taken by own Camera in the same Activity - android

In my code I have my own camera and it works and saves the pictures properly.
First I call:
myCamera.takePicture(null, null, jpegCallBack);
Then I want to save the picture and display it in the same activity I'm now.
So in the jpegCallBack I have (fullPic is my ImageView):
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Media.getBitmap(getContentResolver(), Uri.fromFile(pictureFile) );
String image_string = Uri.fromFile(pictureFile).toString();
bm = BitmapFactory.decodeFile(image_string);
fullPic.setImageBitmap(bm);
} catch ...
But it doesn't work, the first time I press the Shot Button, it saves the file and continues displaying the camera. Sometimes when I take the second one app stops.
I've also tried with this:
fullPic.setImageURI(Uri.fromFile(pictureFile));
and it says: "Bitmap too large to be uploaded into a texture (4608x2592, max=4096x4096)"
I can reduce the size of the displayed image if it is necessary (but not the saved one), but I don't know how to do it.
In the AndroidManifest I have permission for both WRITE and READ.
My XML is like this:
<LL>
<RL>
<FrameLayout></FL> for the Camera Preview
<Button></> To shot the picture
<ImageView></> Here I want to show the picture taken
</RL>
</LL>
Why doesn't it work? Any ideas to display it? I have been looking another stackoverflow links but I don't find the solution. If you need more data/code, please, let me know, I tried to summarize to make it the clearest possible.
Thank you!
Edit:
This is the call of jpegCallBack:
private PictureCallback jpegCallBack = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera)
Maybe I can so the image directly from that data in some way. Can I?
I tried this way but it breaks:
bm = BitmapFactory.decodeByteArray(data, 0, data.length);
fullPic.setImageBitmap(bm);
LogCat: On the blue line I press the shot button
NullPointerException, is it possible that it occurs because I'm using a Samsung? In this thread they say that Samsung has problems with this: Capture Image from Camera and Display in Activity

You're not getting NullPointerException, but out of memory error.
There is a series of very helpful articles on how to load bitmap efficiently. The only thing you need to know is the target display size so you will know to which size to scale down.
If the app is crashing on a 5MB allocation it means you are already at the peek of your memory usage. Please check this Android presentation on memory management.

Related

Take photo of given size Android

I'm developing an application that takes a photo and saves it in Android/data/package/files. I would like to reduce storage used, so I would like to resize the photo before saving it. For the moment I'm calling new intent passing as extra the output path. Is possible to pass also the size wanted or is possible to have the bitmap before saving it?
public void takePicture(View view){
Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(getPath(nameEdit.getText().toString()));
path = f.getAbsolutePath();
pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
if (pictureIntent.resolveActivity(getPackageManager())!=null){
startActivityForResult(pictureIntent,REQUEST_IMAGE_CAPTURE);
}
}
Is possible to pass also the size wanted
No.
is possible to have the bitmap before saving it?
Not really. You could write your own ContentProvider and use a Uri for that, rather than a file. When the camera app tries saving the content, you would get that information in memory first. However, you will then crash with an OutOfMemoryError, as you will not have enough heap space to hold a full-resolution photo, in all likelihood.
You can use BitmapFactory with inSampleSize set in the BitmapFactory.Options to read in the file once it has been written by the camera, save the resized image as you see fit, then delete the full-resolution image. Or, skip EXTRA_OUTPUT, and you will get a thumbnail image returned to you, obtained by calling getExtra("data") on the Intent passed into onHandleIntent().

How to have the camera take a picture and not show you the preview?

I just want to launch the camera activity and have it return to the calling activity. Basically I don't care about seeing the preview image where you "tap to select".
The reason for this is I'm trying to inject tap events, so I cannot get past this screen because you can't inject events into the Camera application.
Have you tried to capture the image using Camera.takePicture()? The last parameter is a callback with the bytes of the image captured. You can then create a bitmap with the byte array and save it to a file:
Bitmap image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
FilenameOutputStream fos = new FileOutputStream(filename);
image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
I haven't used this without a preview, but you might be able to open the camera and call takePicture() without having to use the preview.

High resolution screen shot in Android

Is there any way to get a high resolution screen shot of a certain view in an activity.
I want to convert html content of my webview to PDF. For that I tried to take screen shot of the webview content and then converted it to PDF using itext. The resulted PDF is not in much more clarity.
My code:
protected void takeimg() {
Picture picture = mWebView.capturePicture();
Bitmap b = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
picture.draw(c);
// byte[] bt = b.getNinePatchChunk();
// Bitmap b;
// View v1 = mWebView.getRootView();
// v1.setDrawingCacheEnabled(true);
// b = Bitmap.createBitmap(v1.getDrawingCache());
// v1.setDrawingCacheEnabled(false);
FileOutputStream fos = null;
try {
File root = new File(Environment.getExternalStorageDirectory(),
"Sample");
if (!root.exists()) {
root.mkdir();
}
String sdcardhtmlpath = root.getPath().toString() + "/"
+ "temp_1.png";
fos = new FileOutputStream(sdcardhtmlpath);
// fos = openFileOutput("samsp_1.jpg", MODE_WORLD_WRITEABLE);
if (fos != null) {
b.compress(Bitmap.CompressFormat.PNG, 100, fos);
// fos.write(bt);
fos.close();
}
} catch (Exception e) {
Log.e("takeimg", e.toString());
e.printStackTrace();
}
}
protected void pdfimg() {
Document mydoc = new Document(PageSize.A3);
try {
File root = new File(Environment.getExternalStorageDirectory(),
"Sample");
if (!root.exists()) {
root.mkdir();
}
String sdcardhtmlpath = root.getPath().toString() + "/";
mydoc.setMargins(0, 0, 0, 0);
PdfWriter.getInstance(mydoc, new FileOutputStream(sdcardhtmlpath
+ PDFfilename));
mydoc.open();
Image image1 = Image.getInstance(sdcardhtmlpath + "temp_1.jpg");
image1.scalePercent(95f);
mydoc.add(image1);
// mydoc.newPage();
mydoc.close();
} catch (Exception e) {
Log.e("pdi name", e.toString());
}
}
Update: See Edit 3 for an answer to op's original question
There are two options:
Use a library to convert the HTML to PDF. This is by far the best option, since it will (probably) preserve text as vectors.
Get a high resolution render of the HTML and save it as a PNG (not PDF surely!).
For HTML to PDF, wkhtmltopdf looks like a good option, but it relies on Qt which you can't really use on Android. There are some other libraries but I doubt they do the PDF rendering very well.
For getting a high-res webview, you could try creating your own WebView and calling onMeasure(...) and onLayout(...) and pass appropriate parameters so the view is really big. Then call onDraw(myOwnCanvas) and the webview will draw itself to your canvas, which can be backed by a Bitmap using Canvas.setBitmap().
You can probably copy the state into the new WebView using something like
screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState());
Orrr it may even be possible to use the same WebView, just temporarily resize it to be large, onDraw() it to your canvas, and resize it back again. That's getting very hacky though!
You might run into memory issues if you make it too big.
Edit 1
I thought of a third, exactly-what-you-want option, but it's kind of hardcore. You can create a custom Canvas, that writes to a PDF. In fact, it is almost easy, because underlying Canvas is Skia, which actually includes a PDF backend. Unfortunately you don't get access to it on Android, so you'll basically have to build your own copy of it on Android (there are instructions), and duplicate/override all the Canvas methods to point to your Skia instead of Androids. Note that there is a tempting Picture.writeToStream() method which serializes the Skia data, but unfortunately this format is not forwards or backwards compatible so if you use it your code will probably only work on a few versions of Android.
I'll update if/when I have fully working code.
Edit 2
Actually it is impossible to make your own "intercepting" Canvas. I started doing it and went through the tedious process of serializing all function calls. A few you can't do because they are hidden, but those didn't look important. But right at the end I came to serializing Path only to discover that it is write-only. That seems like a killer to me, so the only option is to interpret the result of Picture.writeToStream(). Fortunately there are only two versions of that format in use, and they are nearly identical.
Edit 3 - Really simple way to get a high resolution Bitmap of a view
Ok, it turns out just getting a high res bitmap of a view (which can be the entire app) is trivial. Here is how to get double resolution. Obviously all the bitmaps look a bit crap, but the text is rendered at full resolution:
View window = activity.getWindow().getDecorView()
Canvas bitmapCanvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(window.getWidth()*2, window.getHeight()*2, Bitmap.Config.ARGB_8888);
bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.scale(2.0f, 2.0f);
window.draw(bitmapCanvas);
bitmap.compress(Bitmap.CompressFormat.PNG, 0, myOutputStream);
Works like a charm. I've now given up on getting a PDF screenshot with vector text. It's certainly possible, but very difficult. Instead I am working on getting a high-res PSD where each draw operation is a separate layer, which should be much easier.
Edit 4
Woa this is getting a bit long, but success! I've generated an .xcf (GIMP) and PDF where each layer is a different canvas drawing operation. It's not quite as fine-grained as I was expecting, but still, pretty useful!
Actually my code just outputs full-size PNGs and I used "Open as layers..." and "Autocrop layer" in GIMP to make these files, but of course you can do that in code if you like. I think I will turn this into a blog post.
Download the GIMP or Photoshop demo file (rendered at 3x resolution).
When you capture the view, just screen bound will capture ( due to control weight and android render pipeline ).
Capturing screenshot for converting to PDF is tricky way. I think two way is more reasonable solutions.
Solution #1
Write a parser ( it's simple ) to convert webview content ( that is HTML ) to iText format.
You can refer to this article for more information.
http://www.vogella.com/articles/JavaPDF/article.html
Also to write a parser you can use REGEX and provide your own methods like parseTable, parseImage, ...
Solution #2 Internet Required
Provide a URL ( or webservice ) to convert HTML to PDF using PHP or C# that has a lot of nice libraries. Next you can send download link to the Client ( Android Device ).
So you can also dynamically add some Tags, Banners, ... to the PDF from server side.
Screen Shot is nothing but picture of your device display which usually depend upon your phone absolute pixels, if your phone is 480x800 screen shot will be same and generally applicable for all scenarios.
Sure, Use this:
Bitmap bitmap;
View v1 = MyView.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
Here MyView is the View you need a screenshot of.

Android: load only detail of large image

I'm working on a project that needs to use a large image as a map. The image is about 95MB and has a resolution of 12100 x 8000 pixels.
I don't need the whole image at once, I just need a detail of 1000 x 1000 Pixel (it's not always the same detail, just grabbing the same part is not a solution I can use). So I can't just sample it down with the BitmapOptions.
I looked around and found the idea to create a FileInputStream (the image is on the SD-Card) and then I can just load the detail with decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts). That way I wouldn't load the whole thing into the memory. I tried it, but it's just crashing when I try to load the image. Here's my code:
FileInputStream stream = null;
try {
stream = new FileInputStream(path);
} catch(Exception e) {
Log.e("inputstream",e.toString());
}
Rect rect = new Rect(a,b,c,d);
return BitmapFactory.decodeStream(stream, rect, null);
When I try to load the image, the activity closes and LogCat tells me java.lang.outOfMemoryError. Why does it crash? I thought with the stream it should work on the image "on-the-fly", but the only explication I have for the Error is the it trys to load the hole image into the memory. Does anybody have an idea how I can load the detail out of the image, or why this idea doesn't work?
It crashed because all these 95M are sucked into memory for processing. This call will not ignore parts of the stream - it will put the whole thing to memory and then try to manipulate it. The only solution you can have is to have some sort of server side code that does the same sort of manipulation or if you don't want to do it on server - provide thumbnails of your large image. And I would strongly advise against pulling whole 95M at any time anyways
Does BitmapRegionDecoder not help (I realise its level 10)?

Photos captured from Android camera are completely black

I make a camera and try to capture a picture. Since the original data is YUV, I turn it into RGB using function:
static public void decodeYUV420SP(byte[] rgbBuf, byte[] yuv420sp,int width, int height)
However, the photo saved is completely black, there is no content in it.
I also found the following way:
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
but the project was shut down.
Are there any other effective ways to save a photo? Thank you!
An old post, but it speaks of a similar problem that I have so I might as well answer the part I know :)
You're probably doing it wrong. I suggest you use the JPEG callback to store the image:
mCamera.takePicture(null, null, callbackJPEG);
This way you will get JPEG data into the routine which you can store into a file unmodified:
final Camera.PictureCallback mCall = new Camera.PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
//Needs <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
File sdCard = Environment.getExternalStorageDirectory();
File file = new File(sdCard, "pic.jpg");
fil = new FileOutputStream(file);
fil.write(data);
fil.close();
}
}
As far as the black picture goes, I have found that placing a simple Thread.sleep(250) between camera.startPreview() and camera.takePicture() takes care of that particular problem on my Galaxy Nexus.
I have no idea why this delay is necessary. Even if I add camera.setOneShotPreviewCallback() and call camera.takePicture() from the callback, the image comes out black if I don't first delay...
Oh, and the delay is not just "some" delay. It has to be some pretty long value. For example, 250ms sometimes works, sometimes not on my phone.
The complete black photo is a result of immediate call to mCamera.takePicture() after calling mCamera.startPreview(). Android should be given appropriate time to process its autofocus activity before taking the actual picture. The blackness is result of erratic exposure caused due to interruption while the autofocus was happening.
I recommend calling mCamera.autoFocus() right after mCamera.startPreview().
The mCamera.takePicture() should be called in the callback function of the autofocus function call.
This flow ensures that the picture is taken after the autofocus is complete and removes blackness or exposure issues from the image taken.
The delay mentioned in Velis' answer works for some devices because those devices complete autofocus activity. Ensuring proper callback flow removes this arbitrary delay and would work on every device.
I solved this issue using following argument:
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
When I was using TEMPLATE_STILL_CAPTURE instead of TEMPLATE_PREVIEW, which was capturing my image as full black image. This thing works in my case.

Categories

Resources