How to save image along with surface view in android? - android

Surface along with image when i click on button it's save only the surface for this i tried
following code
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
ShutterCallback shutterCallback = new ShutterCallback()
{
public void onShutter()
{
Log.d(TAG, "onShutter'd");
}
};
PictureCallback rawCallback = new PictureCallback()
{
public void onPictureTaken(byte[] data, Camera camera)
{
Log.d(TAG, "onPictureTaken - raw");
}
};
PictureCallback jpegCallback = new PictureCallback()
{
public void onPictureTaken(byte[] data, Camera camera)
{
try
{
File root = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),"Camera");
if (!root.exists())
{
root.mkdirs();
}
FileOutputStream f = new FileOutputStream(new File(root,System.currentTimeMillis()+".jpg"));
int len1 = data.length;
f.write(data,0, len1);
f.close();
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
}
}
};
by this code getting only surface, is there any possible to save surface along with image ?
if any one knows please help me

You try using this example . Such as
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class FingerpaintView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "FingerpaintView";
private Paint foregroundPaint;
private Paint backgroundPaint;
private int width, height;
private int lastTouchX, lastTouchY;
private Bitmap pictureBitmap;
private Canvas pictureCanvas;
private final Context context;
public FingerpaintView(Context context) {
super(context);
this.context=context;
init();
}
public FingerpaintView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
init();
}
private void init() {
setFocusableInTouchMode(true);
getHolder().addCallback(this);
foregroundPaint = new Paint();
foregroundPaint.setColor(Color.WHITE);
foregroundPaint.setStrokeWidth(4);
backgroundPaint = new Paint();
backgroundPaint.setColor(Color.BLACK);
lastTouchX = -1;
lastTouchY = -1;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
if ((event.getAction() == MotionEvent.ACTION_DOWN) || (event.getAction() == MotionEvent.ACTION_MOVE)) {
Log.d(TAG, "Touched " + x + "," + y);
if ((lastTouchX != -1) && (lastTouchY != -1)) {
pictureCanvas.drawLine(lastTouchX, lastTouchY, x, y, foregroundPaint);
draw();
}
lastTouchX = x;
lastTouchY = y;
} else {
lastTouchX = -1;
lastTouchY = -1;
}
return true;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU){
clear();
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
this.width = width;
this.height = height;
if (pictureBitmap != null) {
pictureBitmap.recycle();
}
pictureBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
pictureCanvas = new Canvas(pictureBitmap);
clear();
draw();
}
public void draw() {
final Canvas c = getHolder().lockCanvas();
if (c != null) {
c.drawBitmap(pictureBitmap, 0, 0, null);
getHolder().unlockCanvasAndPost(c);
}
}
public void clear() {
pictureCanvas.drawRect(0, 0, width, height, backgroundPaint);
draw();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (pictureBitmap != null) {
saveFile(pictureBitmap,"MyImage");
pictureBitmap.recycle();
}
pictureBitmap = null;
}
private void saveFile(Bitmap bitmap, String name) {
// String filename = String.valueOf(System.currentTimeMillis()) ;
String extStorageDirectory;
extStorageDirectory = Environment.getExternalStorageDirectory().toString();
OutputStream outStream = null;
final File file = new File(extStorageDirectory, name);
try {
outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
Toast.makeText(context, "Saved", Toast.LENGTH_LONG).show();
} catch (final FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();
}
}
}
I expected you will be helpful.

Related

"RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap" trying to pass Bitmap from Activity to a Service

I'm writing a small Android program in Android Studio that uses MediaProjection to grab a screenshot of the whole screen and then I want to pass that screenshot as a Bitmap to my System Overlay (based on the chatheads example). When the MediaProjection runs and the Imagereader creates the bitmaps, I'm passing the bitmap into a class global variable so I can pass it into my System Overlay service and display it. I'm running into an issue where when the Imageview inside the service tries to read the bmp, I get an error as follows:
java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap#347a4d5
From my understanding, the garbage collector quickly eats up the passed Bitmap and when the System Overlay tries to grab it, the data is gone. Could someone point me in the right direction on how to keep the bitmap?
Main Activity
package com.example.chatheads;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.media.ImageReader;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
public class MainActivity extends Activity {
Button startService,stopService;
private static final String TAG = MainActivity.class.getName();
private static final int REQUEST_CODE = 100;
private static String STORE_DIRECTORY;
private static int IMAGES_PRODUCED;
private static final String SCREENCAP_NAME = "screencap";
private static final int VIRTUAL_DISPLAY_FLAGS = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
private static MediaProjection sMediaProjection;
private MediaProjectionManager mProjectionManager;
private ImageReader mImageReader;
private Handler mHandler;
private Display mDisplay;
private VirtualDisplay mVirtualDisplay;
private int mDensity;
private int mWidth;
private int mHeight;
private int mRotation;
private OrientationChangeCallback mOrientationChangeCallback;
private Image image = null;
private Bitmap bitmap = null;
Globals sharedData = Globals.getInstance();
public Bitmap getObjectContainer() {
return bitmap;
}
private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
#Override
public void onImageAvailable(ImageReader reader) {
FileOutputStream fos = null;
try {
image = mImageReader.acquireLatestImage();
if (image != null) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
// create bitmap
bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
sharedData.setScreenshot(bitmap);
// write bitmap to a file
// fos = new FileOutputStream(STORE_DIRECTORY + "/myscreen_" + IMAGES_PRODUCED + ".png");
//bitmap.compress(CompressFormat.JPEG, 100, fos);
IMAGES_PRODUCED++;
//Log.e(TAG, "captured image: " + IMAGES_PRODUCED);
String s = ("captured image: " + String.valueOf(IMAGES_PRODUCED));
Toast toast1 = Toast.makeText(getBaseContext(),s, Toast.LENGTH_SHORT);
toast1.show();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos!=null) {
try {
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (bitmap!=null) {
bitmap.recycle();
}
if (image!=null) {
image.close();
}
}
}
}
private class OrientationChangeCallback extends OrientationEventListener {
public OrientationChangeCallback(Context context) {
super(context);
}
#Override
public void onOrientationChanged(int orientation) {
synchronized (this) {
final int rotation = mDisplay.getRotation();
if (rotation != mRotation) {
mRotation = rotation;
try {
// clean up
if(mVirtualDisplay != null) mVirtualDisplay.release();
if(mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);
// re-create virtual display depending on device width / height
createVirtualDisplay();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
private class MediaProjectionStopCallback extends MediaProjection.Callback {
#Override
public void onStop() {
Log.e("ScreenCapture", "stopping projection.");
mHandler.post(new Runnable() {
#Override
public void run() {
if(mVirtualDisplay != null) mVirtualDisplay.release();
if(mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);
if(mOrientationChangeCallback != null) mOrientationChangeCallback.disable();
sMediaProjection.unregisterCallback(MediaProjectionStopCallback.this);
}
});
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sharedData.setValue(1);
// call for the projection manager
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
// start projection
Button startButton = (Button)findViewById(R.id.startButton);
startButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startProjection();
}
});
// stop projection
Button stopButton = (Button)findViewById(R.id.stopButton);
stopButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
stopProjection();
}
});
// start capture handling thread
new Thread() {
#Override
public void run() {
Looper.prepare();
mHandler = new Handler();
Looper.loop();
}
}.start();
startService=(Button)findViewById(R.id.startService);
stopService=(Button)findViewById(R.id.stopService);
startService.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startService(new Intent(getApplication(), ChatHeadService.class));
}
});
stopService.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
stopService(new Intent(getApplication(), ChatHeadService.class));
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
sMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
if (sMediaProjection != null) {
File externalFilesDir = getExternalFilesDir(null);
if (externalFilesDir != null) {
STORE_DIRECTORY = externalFilesDir.getAbsolutePath() + "/screenshots/";
File storeDirectory = new File(STORE_DIRECTORY);
if (!storeDirectory.exists()) {
boolean success = storeDirectory.mkdirs();
if (!success) {
Log.e(TAG, "failed to create file storage directory.");
return;
}
}
} else {
Log.e(TAG, "failed to create file storage directory, getExternalFilesDir is null.");
return;
}
// display metrics
DisplayMetrics metrics = getResources().getDisplayMetrics();
mDensity = metrics.densityDpi;
mDisplay = getWindowManager().getDefaultDisplay();
// create virtual display depending on device width / height
createVirtualDisplay();
// register orientation change callback
mOrientationChangeCallback = new OrientationChangeCallback(this);
if (mOrientationChangeCallback.canDetectOrientation()) {
mOrientationChangeCallback.enable();
}
// register media projection stop callback
sMediaProjection.registerCallback(new MediaProjectionStopCallback(), mHandler);
}
}
}
/****************************************** UI Widget Callbacks *******************************/
private void startProjection() {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
}
private void stopProjection() {
mHandler.post(new Runnable() {
#Override
public void run() {
if (sMediaProjection != null) {
sMediaProjection.stop();
}
}
});
}
/****************************************** Factoring Virtual Display creation ****************/
private void createVirtualDisplay() {
// get width and height
Point size = new Point();
mDisplay.getSize(size);
mWidth = size.x;
mHeight = size.y;
// start capture reader
mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);
mVirtualDisplay = sMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight, mDensity, VIRTUAL_DISPLAY_FLAGS, mImageReader.getSurface(), null, mHandler);
mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler);
}
}
Service
package com.example.chatheads;
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.View;
import android.widget.Toast;
public class ChatHeadService extends Service {
private WindowManager windowManager;
private ImageView chatHead;
WindowManager.LayoutParams params;
Globals sharedData = Globals.getInstance();
#Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
int h = displayMetrics.heightPixels, w = displayMetrics.widthPixels;
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
final Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(5);
paint.setAlpha(60);
Rect rect=new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
canvas.drawRect(rect,paint);
paint.setColor(Color.GREEN);
canvas.drawLine(0, 0, 0, h, paint);
canvas.drawLine(0, 0, w, 0, paint);
canvas.drawLine(w, 0, h, w, paint);
canvas.drawLine(0, 0, 0, w, paint);
chatHead = new ImageView(this);
chatHead.setImageResource(R.drawable.face1);
params= new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 1000;
//this code is for dragging the chat head
chatHead.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
boolean isExpanded = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
int n = sharedData.getValue();
//Toast toast1 = Toast.makeText(getBaseContext(),String.valueOf(n), Toast.LENGTH_SHORT);
//toast1.show();
if (isExpanded == true){
chatHead.setImageResource(R.drawable.face1);
isExpanded=false;
params.x = 0;
params.y = 1000;
windowManager.updateViewLayout(chatHead, params);
}
else{
//chatHead.setImageResource(R.drawable.clear);
Bitmap bmp2 = sharedData.getScreenshot();
chatHead.setImageBitmap(bmp2);
isExpanded = true;
params.x = 0;
params.y = 0;
windowManager.updateViewLayout(chatHead, params);
}
return true;
case MotionEvent.ACTION_UP:
//chatHead.setImageResource(R.drawable.test);
return true;
/*case MotionEvent.ACTION_MOVE:
params.x = initialX
+ (int) (event.getRawX() - initialTouchX);
params.y = initialY
+ (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(chatHead, params);
return true;*/
}
return false;
}
});
windowManager.addView(chatHead, params);
}
#Override
public void onDestroy() {
super.onDestroy();
if (chatHead != null)
windowManager.removeView(chatHead);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Globals
package com.example.chatheads;
import android.graphics.Bitmap;
public class Globals {
private static Globals instance = new Globals();
// Getter-Setters
public static Globals getInstance() {
return instance;
}
public static void setInstance(Globals instance) {
Globals.instance = instance;
}
private Globals() {
}
private int testi;
private Bitmap bmpscreenshot;
public Bitmap getScreenshot(){
return bmpscreenshot;
}
public void setScreenshot(Bitmap bmp){
this.bmpscreenshot = bmp;
}
public int getValue() {
return testi;
}
public void setValue(int testi) {
this.testi = testi;
}
}
You seem to be calling bitmap.recycle() too soon. Call it after the service has actually processed the data.
If you want a pass a Bitmap from Activity to service means, convert the bitmap into ByteArray
Intent i = new Intent(this, YourService.class);
Bitmap b; // your bitmap
ByteArrayOutputStream bs = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 50, bs);
i.putExtra("byteArray", bs.toByteArray());
startService(i);
Override onStartCommand in your service
public int onStartCommand (Intent intent, int flags, int startId) {
Bitmap b = BitmapFactory.decodeByteArray(
getIntent().getByteArrayExtra("byteArray"),0,getIntent()
.getByteArrayExtra("byteArray").length);
return null;
}

Texture with alpha channel not working on 3ds model in JPCT

About my problem: What is the way to get textures with alpha channel to work?
I use a png texture with alpha channel, but the result is black color on transparent area.
Android program result:
enter image description here
3ds model in cheetah3d:
enter image description here
This is my code:
package testoc.biz.testproject;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Loader;
import com.threed.jpct.Logger;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;
import java.io.InputStream;
import java.lang.reflect.Field;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
public class FullscreenActivity extends Activity {
// Used to handle pause and resume...
private static FullscreenActivity master = null;
private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private RGBColor back = new RGBColor(50, 50, 100);
private float touchTurn = 0;
private float touchTurnUp = 0;
private float xpos = -1;
private float ypos = -1;
private Object3D cube = null;
private int fps = 0;
private boolean gl2 = true;
private Light sun = null;
protected void onCreate(Bundle savedInstanceState) {
if (master != null) {
copy(master);
}
super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());
if (gl2) {
mGLView.setEGLContextClientVersion(2);
} else {
mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
EGLConfig[] configs = new EGLConfig[1];
int[] result = new int[1];
egl.eglChooseConfig(display, attributes, configs, 1, result);
return configs[0];
}
});
}
renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
}
#Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
#Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
#Override
protected void onStop() {
super.onStop();
}
private void copy(Object src) {
try {
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs) {
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}
if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}
if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
return true;
}
try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}
return super.onTouchEvent(me);
}
protected boolean isFullscreenOpaque() {
return true;
}
class MyRenderer implements GLSurfaceView.Renderer {
private long time = System.currentTimeMillis();
public MyRenderer() {
}
private Object3D loadModel( float scale){
InputStream stream = getResources().openRawResource(R.raw.cube);
Object3D[] model = Loader.load3DS(stream, scale);
Object3D o3d = new Object3D(0);
Object3D temp = null;
for (int i = 0; i < model.length; i++) {
temp = model[i];
temp.setCenter(SimpleVector.ORIGIN);
temp.rotateX((float)( -0.5*Math.PI));
temp.rotateMesh();
temp.setRotationMatrix(new Matrix());
o3d = Object3D.mergeObjects(o3d, temp);
o3d.build();
}
return o3d;
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
if (fb != null) {
fb.dispose();
}
if (gl2) {
fb = new FrameBuffer(w, h); // OpenGL ES 2.0 constructor
} else {
fb = new FrameBuffer(gl, w, h); // OpenGL ES 1.x constructor
}
if (master == null) {
world = new World();
world.setAmbientLight(20, 20, 20);
sun = new Light(world);
sun.setIntensity(250, 250, 250);
Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.gradient)), 256, 256),true);
TextureManager.getInstance().addTexture("gradient.png", texture);
cube = loadModel(20);
cube.strip();
cube.build();
world.addObject(cube);
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cube.getTransformedCenter());
SimpleVector sv = new SimpleVector();
sv.set(cube.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();
if (master == null) {
Logger.log("Saving master Activity!");
master = FullscreenActivity.this;
}
}
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
public void onDrawFrame(GL10 gl) {
if (touchTurn != 0) {
cube.rotateY(touchTurn);
touchTurn = 0;
}
if (touchTurnUp != 0) {
cube.rotateX(touchTurnUp);
touchTurnUp = 0;
}
fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();
if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
}
}
I am used the jpct library for Android.
I've nailed it with adding glEnable as wes suggested by #Reigertje:
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
}

Camera portrait not fullsize when preview with surfaceview

please help me
i'm create app camera with orientation portrait, but the preview camera is not full size to screen, what's wrong?
this is my class:
CameraPreview.class
package com.dm.zbar.android.scanner;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import java.io.IOException;
import java.util.List;
class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "CameraPreview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize, mPictureSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
PreviewCallback mPreviewCallback;
AutoFocusCallback mAutoFocusCallback;
CameraPreview(Context context, PreviewCallback previewCallback, AutoFocusCallback autoFocusCb) {
super(context);
mPreviewCallback = previewCallback;
mAutoFocusCallback = autoFocusCb;
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
// Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void hideSurfaceView() {
mSurfaceView.setVisibility(View.INVISIBLE);
}
public void showSurfaceView() {
mSurfaceView.setVisibility(View.VISIBLE);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.cancelAutoFocus();
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (holder.getSurface() == null){
// preview surface does not exist
return;
}
if (mCamera != null) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
if(getResources().getConfiguration().orientation== getResources().getConfiguration().ORIENTATION_LANDSCAPE){
mCamera.setDisplayOrientation(0);
}else{
mCamera.setDisplayOrientation(90);
}
requestLayout();
mCamera.setParameters(parameters);
mCamera.setPreviewCallback(mPreviewCallback);
mCamera.startPreview();
mCamera.autoFocus(mAutoFocusCallback);
}
}
}
and this my capture:
http://postimg.org/image/hrrmrto3f/
http://postimg.org/image/obgq3g9vp/
I guess your .xml is incorrect:Replace your xml with this one:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/dashboard_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:gravity="center"
android:textSize="16sp"
android:text="Front of the card"
android:textColor="#8f928c" />
</RelativeLayout>
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/btn_area"
android:layout_below="#+id/top_bar" />
<LinearLayout
android:id="#+id/btn_area"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
android:paddingBottom="3.5dp"
android:layout_alignParentBottom="true" >
<Button
android:id="#+id/button_preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:enabled="false"
android:textSize="18sp"
android:text="Refresh" />
<Button
android:id="#+id/button_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:enabled="false"
android:textSize="18sp"
android:text="Capture" />
<Button
android:id="#+id/button_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
android:textSize="18sp"
android:text="Ok" />
</LinearLayout>
</RelativeLayout>
Your CameraActivity.java
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.TextView;
public class CameraActivity extends Activity {
private Camera mCamera;
private CustomizeCameraPreview mPreview;
public static final int MEDIA_TYPE_IMAGE = 1;
Button captureButton;
Button previewButton;
Button viewButton;
String pictureFilePath = null;
FrameLayout preview;
TextView tvheader;
//addition for free-hand drawing
Drawing mv = null;
int color_code = 0xFFFF2525;
ImageView colorButton;
ImageView undo;
boolean startDraw = false;
String str="";
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
// TODO Auto-generated method stub
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("CameraActivity", "Error creating media file, check storage permissions");
return;
}
initDrawing(scale_and_rotateImage(data,480));
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.customcamera);
//str=getIntent().getExtras().getString("cardimage");
try{
str=getIntent().getStringExtra("cardimage");
System.out.println("str==="+str);
tvheader=(TextView)findViewById(R.id.dashboard_logo);
if(str.equals("front"))
tvheader.setText("Front of the card");
else
tvheader.setText("Back of the card");
}catch(Exception e)
{
e.printStackTrace();
}
startDraw = true;
}
#Override
public void onResume() {
// 31-Jul-2013 ///////////////////
preview = (FrameLayout) findViewById(R.id.camera_preview);
// Add a listener to the Preview button
previewButton = (Button) findViewById(R.id.button_preview);
captureButton = (Button) findViewById(R.id.button_capture);
viewButton = (Button) findViewById(R.id.button_view);
if(checkCameraHardware(getApplicationContext())) {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
mCamera = getCameraInstance();
flashLightOn(mCamera);
// Create our Preview view and set it as the content of our activity.
mPreview = new CustomizeCameraPreview(getApplicationContext(), mCamera);
preview.addView(mPreview);
previewButton.setEnabled(false);
captureButton.setEnabled(true);
viewButton.setEnabled(false);
}
previewButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
startDraw = true;
// release previous camera instance
if (mCamera != null) {
mCamera.stopPreview();
preview.removeView(mPreview);
mCamera.release();
mCamera = null;
}
if(mPreview != null) mPreview = null;
// Create an instance of Camera
mCamera = getCameraInstance();
flashLightOn(mCamera);
// Create our Preview view and set it as the content of our activity.
mPreview = new CustomizeCameraPreview(getApplicationContext(), mCamera);
preview.addView(mPreview);
v.setEnabled(false);
captureButton.setEnabled(true);
viewButton.setEnabled(false);
}
}
);
// Add a listener to the Capture button
captureButton.setOnClickListener (
new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
try {
mCamera.takePicture(null, null, mPicture);
previewButton.setEnabled(true);
v.setEnabled(false);
viewButton.setEnabled(true);
}catch(Exception e) {
//mCamera not instantiated
}
}
}
);
// Add a listener to the View button
viewButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// return image path to calling activity
pictureFilePath = saveImage();
if(pictureFilePath != null) {
Intent data = new Intent();
//---set the data to pass back---
data.setData(Uri.parse(pictureFilePath));
setResult(RESULT_OK, data);
//---closes the activity---
finish();
}
previewButton.setEnabled(true);
captureButton.setEnabled(false);
//v.setEnabled(false);
}
}
);
//////////////////////////////////
super.onResume();
}
public String saveImage() {
pictureFilePath = null;
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("CameraActivity", "Error creating media file, check storage permissions");
return null;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
Bitmap tmp = mv.getDrawingCache();
tmp.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
pictureFilePath = pictureFile.getAbsolutePath();
} catch (Exception e) {
Log.d("CameraActivity", "Error accessing file: " + e.getMessage());
}
return pictureFilePath;
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
public void flashLightOn(Camera cam) {
try {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_AUTO);
cam.setParameters(p);
}
} catch (Exception e) {
e.printStackTrace();
//Toast.makeText(getBaseContext(), "Exception flashLightOn()", Toast.LENGTH_SHORT).show();
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
c.setDisplayOrientation(90);
//context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
/*
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
*/
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "canberra trailpass");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("canberra trailpass", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
private Bitmap scale_and_rotateImage(byte[] input, int dstWidth)
{
// code to free some memory
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
// create the blank bitmap
Bitmap inputImage = BitmapFactory.decodeByteArray(input, 0, input.length, opts); // java.lang.OutOfMemoryError error
// create the smaller bitmap
inputImage = null;
opts.inJustDecodeBounds = false;
opts.inSampleSize = (int) opts.outWidth / dstWidth;
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
inputImage = BitmapFactory.decodeByteArray(input, 0, input.length, opts);
// create a matrix for the manipulation
Matrix m = new Matrix();
//int width = inputImage.getWidth();
//int height = inputImage.getHeight();
int width = opts.outWidth;
int height = opts.outHeight;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) dstWidth) / width;
//float scaleHeight = ((float) dstHeight) / height;
// resize the bit map
m.postScale(scaleWidth, scaleWidth);
// rotate the Bitmap
m.postRotate(90);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(inputImage, 0, 0,
width, height, m, true);
inputImage.recycle();
inputImage = null;
/*
ByteArrayOutputStream blob = new ByteArrayOutputStream();
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, blob);
resizedBitmap.recycle();
resizedBitmap = null;
return blob.toByteArray();
*/
return resizedBitmap;
}
#Override
public void onBackPressed(){
Intent data = new Intent();
//---set the data to pass back---
//data.setData(null);
System.out.println("--> Back from camera activity");
setResult(RESULT_CANCELED, data);
finish();
super.onBackPressed();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
preview.removeView(mPreview);
super.onPause();
}
public void initDrawing(Bitmap resizedBitmap) {
int line_width = (int) this.getResources().getInteger(R.integer.line_width);
mv = new Drawing(this,line_width,color_code,1);
mv.setDrawingCacheEnabled(true);
//mv.setBackground(new BitmapDrawable(resizedBitmap));
mv.setBackgroundDrawable(new BitmapDrawable(getResources(), resizedBitmap));
preview.addView(mv);
LinearLayout bt_container = new LinearLayout(this);
bt_container.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
bt_container.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(5, 2, 5, 2);
undo = new ImageView(this);
undo.setImageResource(R.drawable.undo_icon);
bt_container.addView(undo,layoutParams);
undo.setVisibility(View.GONE);
undo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mv.onClickUndo();
}
});
/* colorButton = new ImageView(this);
//colorButton.setImageResource(R.drawable.pencil1); changed on 25-Nov-13
colorButton.setBackgroundColor(color_code);
colorButton.setImageResource(R.drawable.pencil2);
bt_container.addView(colorButton,layoutParams);
colorButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AmbilWarnaDialog dialog = new AmbilWarnaDialog(CameraActivity.this, color_code, new OnAmbilWarnaListener() {
#Override
public void onOk(AmbilWarnaDialog dialog, int color) {
startDraw = true;
color_code = color;
mv.setColor(color_code);
colorButton.setBackgroundColor(color_code);
colorButton.setImageResource(R.drawable.pencil2);
}
#Override
public void onCancel(AmbilWarnaDialog dialog) {
}
});
dialog.show();
}
});*/
FrameLayout.LayoutParams fParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.RIGHT | Gravity.TOP);
preview.addView(bt_container, fParams);
}
public class Drawing extends View {
private Paint mPaint, mBitmapPaint;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Context mContext;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private int color, size, state;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
private ArrayList<Integer> colors = new ArrayList<Integer>();
private ArrayList<Integer> sizes = new ArrayList<Integer>();
public Drawing(Context c) {
super(c);
mContext = c;
}
public Drawing(Context c, int size, int color, int state) {
super(c);
mContext = c;
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(color);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(size);
setColor(color);
setSize(size);
setState(state);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
if(!startDraw) return;
for (int i = 0; i < paths.size(); i++) {
mPaint.setColor(colors.get(i));
mPaint.setStrokeWidth(sizes.get(i));
canvas.drawPath(paths.get(i), mPaint);
}
mPaint.setColor(color);
canvas.drawPath(mPath, mPaint);
}
public void setColor(int color) {
this.color = color;
mPaint.setColor(color);
}
public void setSize(int size) {
this.size = size;
}
public void setState(int state) {
this.state = state;
paths.clear();
sizes.clear();
colors.clear();
invalidate();
mPaint.setXfermode(null);
//mPaint.setAlpha(0xFF);
mPaint.setStrokeWidth(size);
}
public void clearCanvas() {
mBitmap.eraseColor(Color.TRANSPARENT);
paths.clear();
sizes.clear();
colors.clear();
mPath.reset();
invalidate();
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
sizes.remove(sizes.size() - 1);
colors.remove(colors.size() - 1);
if(colors.size() > 0)
undo.setBackgroundColor(colors.get(colors.size() - 1));
else
undo.setVisibility(View.GONE);
invalidate();
}
}
private void touch_start(float x, float y) {
undo.setVisibility(View.VISIBLE);
undo.setBackgroundColor(color);
undonePaths.clear();
mPath.reset();
//colors.add(color);
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
if(state != 0) {
colors.add(color);
sizes.add(size);
paths.add(mPath);
mPath = new Path();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(!startDraw) return false;
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
}
and I cant find any mistake in your CameraPreview.java
The output will be like below:
It works fine for me. Add this into mainactivity:
mPreview = new CamLayer(this);
Splash.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
if (mPreview == null) {
mPreview = new CamLayer(MainActivity.this);
}
mPreview.setcameraparam(flash);
Intent i = new Intent(MainActivity.this, ShowingImage.class);
mPreview.getimage(MainActivity.this, i);
}
});
Then in your public classCamLayer extends SurfaceView implements SurfaceHolder.Callback class, add these methods:
public void getimage(final Context context,final Intent i) {
final File pictureFile = getOutputMediaFile();
PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
i.putExtra("file_path", pictureFile.getPath());
context.startActivity(i);
} catch (FileNotFoundException e) {
Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();
}
}
};
mCamera.takePicture(null, null, mPicture);
}
private static File getOutputMediaFile() {
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"Sunil2");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
public void setcameraparam(String param) {
Parameters parameter = mCamera.getParameters();
parameter.setFlashMode(param);
mCamera.setParameters(parameter);
}
and showing image class after intent:
public class ShowingImage extends Activity {
#SuppressLint("NewApi")
Bitmap myBitmap;
int width;
int height;
private float curScale = 1F;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.show_image);
Intent intent = getIntent();
String path = intent.getStringExtra("file_path");
Log.e("file store in ", "" + path);
File imgFile = new File(path);
if (imgFile.exists()) {
ImageView myImage = (ImageView) findViewById(R.id.imageView1);
myBitmap = BitmapFactory.decodeFile(path);
width = myBitmap.getWidth();
height = myBitmap.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(curScale, curScale);
matrix.postRotate(90);
Bitmap resizedBitmap = Bitmap.createBitmap(myBitmap, 0, 0, width,
height, matrix, true);
myImage.setImageBitmap(resizedBitmap);
} else {
Toast.makeText(getApplicationContext(), "file not exist", 1000)
.show();
}
}
}
xml:
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent" />

Android Canvas - Save Image not working

I have used below example code to place image files onto a canvas in Android and I'm struggling getting it to save the entire image to SDCard. At the moment it only saves a strange close up of one of the images. Any idea on what is going wrong?
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;
public class ebpSeatingPlan extends Activity {
public Panel myPanel;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//requestWindowFeature(Window.FEATURE_NO_TITLE);
myPanel = new Panel(this);
setContentView(myPanel);
myPanel.setImageID(R.drawable.tableperson);
}
private static final int TYPE1 = 0;
private static final int TYPE2 = 1;
private static final int TYPE3 = 2;
private static final int EXIT = 3;
private static final int TYPE4 = 4;
public boolean onCreateOptionsMenu(Menu menu){
menu.add(0,TYPE1,0,"Guest Type 1").setIcon(R.drawable.tableperson);
menu.add(0,TYPE2,0,"Guest Type 2").setIcon(R.drawable.tableperson2);
menu.add(0,TYPE3,0,"Guest Type 3").setIcon(R.drawable.tableperson3);
menu.add(0,TYPE4,0,"Save Image").setIcon(R.drawable.frame);
menu.add(0,EXIT,0,"Back to Main Menu").setIcon(R.drawable.exit);
return true;
}
public boolean onOptionsItemSelected (MenuItem item){
switch (item.getItemId()){
case TYPE1:
myPanel.setImageID(R.drawable.tableperson);
return true;
case TYPE2:
myPanel.setImageID(R.drawable.tableperson2);
return true;
case TYPE3:
myPanel.setImageID( R.drawable.tableperson3);
return true;
case TYPE4:
File myDir = new File("/sdcard/saved_images");
myDir.mkdirs();
Date now = new Date();
String fname = "image"+now.getDate()+now.getSeconds()+".jpg";
File file = new File(myDir, fname);
myPanel.saveAsJpg(file, myPanel);
return true;
case EXIT:
finish();
return true;
}
return false;
}
}
class Panel extends SurfaceView implements SurfaceHolder.Callback {
public int chosenImageId;
//public Bitmap bitmap;
private TutorialThread _thread;
private ArrayList<GraphicObject> _graphics = new ArrayList<GraphicObject>();
private GraphicObject _currentGraphic = null;
public void setImageID(int i){
chosenImageId = i;
}
public void saveAsJpg(File f, View v){
String fname = f.getAbsolutePath();
FileOutputStream fos = null;
try{
fos = new FileOutputStream(fname);
Bitmap b = Bitmap.createBitmap(v.getWidth(),v.getHeight(),Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
//bitmap.compress(CompressFormat.JPEG, 100, fos);
b.compress(CompressFormat.JPEG, 100, fos);
Toast.makeText(super.getContext(),"Image Saved", Toast.LENGTH_LONG).show();
}catch (Exception ex){
Toast.makeText(super.getContext(),"Error Saving Image", Toast.LENGTH_LONG).show();
Log.i("DAVE","stacktrace is " + ex);
}
}
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this);
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (_thread.getSurfaceHolder()) {
GraphicObject graphic = null;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
graphic = new GraphicObject(BitmapFactory.decodeResource(getResources(), chosenImageId));
graphic.getCoordinates().setX((int) event.getX() - graphic.getGraphic().getWidth() / 2);
graphic.getCoordinates().setY((int) event.getY() - graphic.getGraphic().getHeight() / 2);
_currentGraphic = graphic;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
_currentGraphic.getCoordinates().setX((int) event.getX() - _currentGraphic.getGraphic().getWidth() / 2);
_currentGraphic.getCoordinates().setY((int) event.getY() - _currentGraphic.getGraphic().getHeight() / 2);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
_graphics.add(_currentGraphic);
_currentGraphic = null;
}
return true;
}
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.LTGRAY);
Bitmap bitmap=null;
GraphicObject.Coordinates coords;
for (GraphicObject graphic : _graphics) {
bitmap = graphic.getGraphic();
coords = graphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}
if (_currentGraphic != null) {
bitmap = _currentGraphic.getGraphic();
coords = _currentGraphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
_thread.setRunning(true);
_thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
class TutorialThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;
public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
public SurfaceHolder getSurfaceHolder() {
return _surfaceHolder;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
class GraphicObject {
public class Speed {
public static final int X_DIRECTION_RIGHT = 1;
public static final int X_DIRECTION_LEFT = -1;
public static final int Y_DIRECTION_DOWN = 1;
public static final int Y_DIRECTION_UP = -1;
private int _x = 1;
private int _y = 1;
private int _xDirection = X_DIRECTION_RIGHT;
private int _yDirection = Y_DIRECTION_DOWN;
public int getXDirection() {
return _xDirection;
}
public void setXDirection(int direction) {
_xDirection = direction;
}
public void toggleXDirection() {
if (_xDirection == X_DIRECTION_RIGHT) {
_xDirection = X_DIRECTION_LEFT;
} else {
_xDirection = X_DIRECTION_RIGHT;
}
}
public int getYDirection() {
return _yDirection;
}
public void setYDirection(int direction) {
_yDirection = direction;
}
public void toggleYDirection() {
if (_yDirection == Y_DIRECTION_DOWN) {
_yDirection = Y_DIRECTION_UP;
} else {
_yDirection = Y_DIRECTION_DOWN;
}
}
public int getX() {
return _x;
}
public void setX(int speed) {
_x = speed;
}
public int getY() {
return _y;
}
public void setY(int speed) {
_y = speed;
}
public String toString() {
String xDirection;
String yDirection;
if (_xDirection == X_DIRECTION_RIGHT) {
xDirection = "right";
} else {
xDirection = "left";
}
if (_yDirection == Y_DIRECTION_UP) {
yDirection = "up";
} else {
yDirection = "down";
}
return "Speed: x: " + _x + " | y: " + _y + " | xDirection: " + xDirection + " | yDirection: " + yDirection;
}
}
public class Coordinates {
private int _x = 100;
private int _y = 0;
public int getX() {
return _x + _bitmap.getWidth() / 2;
}
public void setX(int value) {
_x = value - _bitmap.getWidth() / 2;
}
public int getY() {
return _y + _bitmap.getHeight() / 2;
}
public void setY(int value) {
_y = value - _bitmap.getHeight() / 2;
}
public String toString() {
return "Coordinates: (" + _x + "/" + _y + ")";
}
}
private Bitmap _bitmap;
private Coordinates _coordinates;
public GraphicObject(Bitmap bitmap) {
_bitmap = bitmap;
_coordinates = new Coordinates();
}
public Bitmap getGraphic() {
return _bitmap;
}
public Coordinates getCoordinates() {
return _coordinates;
}
}
you can use drawing cache of view to save image
first enable drawingcache of you view by
myPanel.setDrawingCacheEnabled(true);
after that in your saveImage function write following code
Bitmap bitMap=v.getDrawingCache(true);
if (!APP_FILE_PATH.exists()) {
APP_FILE_PATH.mkdirs();
}
bitMap.compress(Bitmap.CompressFormat.PNG, 95, f);

Android and MJPEG

I need to get the mjpeg stream from an IP camera, anyone know the right way do it? I googled a bit and I find this example
http://www.anddev.org/mjpeg_on_android_anyone-t1871.html
but I've been stucked when I tried to get the stream from another activity called by the main activity. Here the code:
Main acitivity
package com.test;
public class IntentTest extends Activity {
/** Called when the activity is first created. */
ListView myListView = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myListView = (ListView)findViewById(R.id.listView);
final ArrayList<String> items = new ArrayList<String>();
items.add("00408C944B9A");
final ArrayAdapter<String> aa;
aa = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
items);
myListView.setAdapter(aa);
myListView.setOnItemClickListener(listClicked);
}
private OnItemClickListener listClicked = new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) {
// TODO Auto-generated method stub
Intent i = new Intent(IntentTest.this, OtherActivity.class);
i.putExtra("MAC", myListView.getItemAtPosition(position).toString());
startActivity(i);
}
};
}
Second activity
package com.test;
import com.test.mjpeg.mjpegsample.MjpegView.*;
import com.test.parser.JSONParse;
public class OtherActivity extends Activity {
/** Called when the activity is first created. */
private MjpegView mv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras != null){
String mac = (String)extras.get("MAC");
Log.i("Other", "---->" + mac);
TextView tv = (TextView)findViewById(R.id.textView);
tv.setText(mac);
String URL = "myurl";
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
mv = new MjpegView(this);
setContentView(mv);
mv.setSource(MjpegInputStream.read(URL));
mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);
mv.showFps(true);
}
}
public void onPause() {
super.onPause();
mv.stopPlayback();
}
}
I found this code over the internet some time ago, maybe it will be of some help to you.
MjpegSample Class
package de.mjpegsample;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import de.mjpegsample.MjpegView.MjpegInputStream;
import de.mjpegsample.MjpegView.MjpegView;
public class MjpegSample extends Activity {
private MjpegView mv;
private static final int MENU_QUIT = 1;
/* Creates the menu items */
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_QUIT, 0, "Quit");
return true;
}
/* Handles item selections */
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_QUIT:
finish();
return true;
}
return false;
}
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
//sample public cam
String URL = "http://gamic.dnsalias.net:7001/img/video.mjpeg";
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
mv = new MjpegView(this);
setContentView(mv);
mv.setSource(MjpegInputStream.read(URL));
mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);
mv.showFps(false);
}
public void onPause() {
super.onPause();
mv.stopPlayback();
}
}
MjpegView Class
package de.mjpegsample.MjpegView;
import java.io.IOException;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MjpegView extends SurfaceView implements SurfaceHolder.Callback {
public final static int POSITION_UPPER_LEFT = 9;
public final static int POSITION_UPPER_RIGHT = 3;
public final static int POSITION_LOWER_LEFT = 12;
public final static int POSITION_LOWER_RIGHT = 6;
public final static int SIZE_STANDARD = 1;
public final static int SIZE_BEST_FIT = 4;
public final static int SIZE_FULLSCREEN = 8;
private MjpegViewThread thread;
private MjpegInputStream mIn = null;
private boolean showFps = false;
private boolean mRun = false;
private boolean surfaceDone = false;
private Paint overlayPaint;
private int overlayTextColor;
private int overlayBackgroundColor;
private int ovlPos;
private int dispWidth;
private int dispHeight;
private int displayMode;
public class MjpegViewThread extends Thread {
private SurfaceHolder mSurfaceHolder;
private int frameCounter = 0;
private long start;
private Bitmap ovl;
public MjpegViewThread(SurfaceHolder surfaceHolder, Context context) { mSurfaceHolder = surfaceHolder; }
private Rect destRect(int bmw, int bmh) {
int tempx;
int tempy;
if (displayMode == MjpegView.SIZE_STANDARD) {
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_BEST_FIT) {
float bmasp = (float) bmw / (float) bmh;
bmw = dispWidth;
bmh = (int) (dispWidth / bmasp);
if (bmh > dispHeight) {
bmh = dispHeight;
bmw = (int) (dispHeight * bmasp);
}
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_FULLSCREEN) return new Rect(0, 0, dispWidth, dispHeight);
return null;
}
public void setSurfaceSize(int width, int height) {
synchronized(mSurfaceHolder) {
dispWidth = width;
dispHeight = height;
}
}
private Bitmap makeFpsOverlay(Paint p, String text) {
Rect b = new Rect();
p.getTextBounds(text, 0, text.length(), b);
int bwidth = b.width()+2;
int bheight = b.height()+2;
Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
p.setColor(overlayBackgroundColor);
c.drawRect(0, 0, bwidth, bheight, p);
p.setColor(overlayTextColor);
c.drawText(text, -b.left+1, (bheight/2)-((p.ascent()+p.descent())/2)+1, p);
return bm;
}
public void run() {
start = System.currentTimeMillis();
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
Bitmap bm;
int width;
int height;
Rect destRect;
Canvas c = null;
Paint p = new Paint();
String fps = "";
while (mRun) {
if(surfaceDone) {
try {
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
try {
bm = mIn.readMjpegFrame();
destRect = destRect(bm.getWidth(),bm.getHeight());
c.drawColor(Color.BLACK);
c.drawBitmap(bm, null, destRect, p);
if(showFps) {
p.setXfermode(mode);
if(ovl != null) {
height = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom-ovl.getHeight();
width = ((ovlPos & 8) == 8) ? destRect.left : destRect.right -ovl.getWidth();
c.drawBitmap(ovl, width, height, null);
}
p.setXfermode(null);
frameCounter++;
if((System.currentTimeMillis() - start) >= 1000) {
fps = String.valueOf(frameCounter)+"fps";
frameCounter = 0;
start = System.currentTimeMillis();
ovl = makeFpsOverlay(overlayPaint, fps);
}
}
} catch (IOException e) {}
}
} finally { if (c != null) mSurfaceHolder.unlockCanvasAndPost(c); }
}
}
}
}
private void init(Context context) {
SurfaceHolder holder = getHolder();
holder.addCallback(this);
thread = new MjpegViewThread(holder, context);
setFocusable(true);
overlayPaint = new Paint();
overlayPaint.setTextAlign(Paint.Align.LEFT);
overlayPaint.setTextSize(12);
overlayPaint.setTypeface(Typeface.DEFAULT);
overlayTextColor = Color.WHITE;
overlayBackgroundColor = Color.BLACK;
ovlPos = MjpegView.POSITION_LOWER_RIGHT;
displayMode = MjpegView.SIZE_STANDARD;
dispWidth = getWidth();
dispHeight = getHeight();
}
public void startPlayback() {
if(mIn != null) {
mRun = true;
thread.start();
}
}
public void stopPlayback() {
mRun = false;
boolean retry = true;
while(retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
public MjpegView(Context context, AttributeSet attrs) { super(context, attrs); init(context); }
public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { thread.setSurfaceSize(w, h); }
public void surfaceDestroyed(SurfaceHolder holder) {
surfaceDone = false;
stopPlayback();
}
public MjpegView(Context context) {
super(context);
init(context);
}
public void surfaceCreated(SurfaceHolder holder) {
surfaceDone = true;
}
public void showFps(boolean b) {
showFps = b;
}
public void setSource(MjpegInputStream source) {
mIn = source;
startPlayback();
}
public void setOverlayPaint(Paint p) {
overlayPaint = p;
}
public void setOverlayTextColor(int c) {
overlayTextColor = c;
}
public void setOverlayBackgroundColor(int c) {
overlayBackgroundColor = c;
}
public void setOverlayPosition(int p) {
ovlPos = p;
}
public void setDisplayMode(int s) {
displayMode = s;
}
}
MjpegInputStream Class
package de.mjpegsample.MjpegView;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Properties;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class MjpegInputStream extends DataInputStream {
private final byte[] SOI_MARKER = { (byte) 0xFF, (byte) 0xD8 };
private final byte[] EOF_MARKER = { (byte) 0xFF, (byte) 0xD9 };
private final String CONTENT_LENGTH = "Content-Length";
private final static int HEADER_MAX_LENGTH = 100;
private final static int FRAME_MAX_LENGTH = 40000 + HEADER_MAX_LENGTH;
private int mContentLength = -1;
public static MjpegInputStream read(String url) {
HttpResponse res;
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
res = httpclient.execute(new HttpGet(URI.create(url)));
return new MjpegInputStream(res.getEntity().getContent());
} catch (ClientProtocolException e) {
} catch (IOException e) {}
return null;
}
public MjpegInputStream(InputStream in) { super(new BufferedInputStream(in, FRAME_MAX_LENGTH)); }
private int getEndOfSeqeunce(DataInputStream in, byte[] sequence) throws IOException {
int seqIndex = 0;
byte c;
for(int i=0; i < FRAME_MAX_LENGTH; i++) {
c = (byte) in.readUnsignedByte();
if(c == sequence[seqIndex]) {
seqIndex++;
if(seqIndex == sequence.length) return i + 1;
} else seqIndex = 0;
}
return -1;
}
private int getStartOfSequence(DataInputStream in, byte[] sequence) throws IOException {
int end = getEndOfSeqeunce(in, sequence);
return (end < 0) ? (-1) : (end - sequence.length);
}
private int parseContentLength(byte[] headerBytes) throws IOException, NumberFormatException {
ByteArrayInputStream headerIn = new ByteArrayInputStream(headerBytes);
Properties props = new Properties();
props.load(headerIn);
return Integer.parseInt(props.getProperty(CONTENT_LENGTH));
}
public Bitmap readMjpegFrame() throws IOException {
mark(FRAME_MAX_LENGTH);
int headerLen = getStartOfSequence(this, SOI_MARKER);
reset();
byte[] header = new byte[headerLen];
readFully(header);
try {
mContentLength = parseContentLength(header);
} catch (NumberFormatException nfe) {
mContentLength = getEndOfSeqeunce(this, EOF_MARKER);
}
reset();
byte[] frameData = new byte[mContentLength];
skipBytes(headerLen);
readFully(frameData);
return BitmapFactory.decodeStream(new ByteArrayInputStream(frameData));
}
}
If you need any more info, let me know, I'll help in any way I can.
FYI: I did not write SimpleMjpegView, you can find more up to date code here
For those looking to get this working with AsyncTask (and thus working on Ice Cream Sandwich (ICS), 4.0.4) see Android ICS and MJPEG using AsyncTask.
I had the same problem and tried using custom Mjpeg viewers. While they worked, they proved unstable and clumsy for me.
I am simply using a WebView. On Android Studio, simply drag and drop a WebView. My WebView is not covering the entire screen, but half of it.
Then, to fit the video best, in your onCreate:
If using Kotlin:
webView.settings.loadWithOverviewMode = true;
webView.settings.useWideViewPort = true;
If using Java:
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
And then, on button click:
To start:
webView.loadUrl("http://$id:8081/cam.mjpeg") // start
To Stop:
webView.stopLoading()
webView.loadUrl("about:blank")
Hope this helps.

Categories

Resources