I have an image which a user can paint on in my android application. I decided to add an undo button to it so the user can cancel mistakes. I made it so that when the user draws on the screen, it saves the bitmap to an array. Then when the undo button is pressed, it changes the image to the last bitmap in the array. However, this just keeps setting the image to whatever the current image is (i.e. it doesn't change it at all).
public class edit extends AppCompatActivity implements View.OnClickListener {
float MoveX,MoveY,DownY,DownX,UpY=0,UpX ;
List<Bitmap> undos = new ArrayList<Bitmap>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit);
final ImageButton btn2 = (ImageButton) findViewById(R.id.imageButton2);
btn2.setOnClickListener(this);
final Button buttonchoose = (Button) findViewById(R.id.buttonchoose);
buttonchoose.setOnClickListener(this);
final RelativeLayout ViewX = (RelativeLayout) findViewById(R.id.RLXV);
ViewTreeObserver vto = ViewX.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
ViewX.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Intent intent7 = getIntent();
String bitmapXY = (String) intent7.getExtras().get("BitmapImage");
GraphRequest request = GraphRequest.newGraphPathRequest(
AccessToken.getCurrentAccessToken(),
"/" + bitmapXY,
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
HttpURLConnection connection = null;
try {
int ViewWidth = ViewX.getMeasuredWidth();
JSONObject photos = response.getJSONObject();
JSONArray linkY = photos.optJSONArray("images");
final JSONObject linkO = linkY.optJSONObject(0);
final String link2 = linkO.optString("source");
URL LINKF = new URL(link2);
connection = (HttpURLConnection) LINKF.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
float HH = (float) bitmap.getHeight();
float WW = (float) bitmap.getWidth();
float ViewWidthX = (float) ViewWidth;
float height = (HH / WW) * ViewWidthX;
Bitmap bitmapF = Bitmap.createScaledBitmap(bitmap, ViewWidth, Math.round(height), false);
final ImageView image1 = (ImageView) findViewById(R.id.image1);
image1.setImageBitmap(bitmapF);
undos.add(bitmapF);
image1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Display d = getWindowManager().getDefaultDisplay();
float dw = d.getWidth();
float dh = d.getHeight();
float x = event.getX();
float y = event.getY();
float r = 2;
Bitmap BTX = ((BitmapDrawable)image1.getDrawable()).getBitmap();
Canvas canvas = new Canvas(BTX);
canvas.drawBitmap(BTX,0,0,null);
Paint paint1 = new Paint();
int bg1 = buttonchoose.getDrawingCacheBackgroundColor();
ColorDrawable buttonColor = (ColorDrawable) buttonchoose.getBackground();
int bg2 =buttonColor.getColor();
paint1.setColor(bg2);
paint1.setShadowLayer(5, 2, 2, bg2);
paint1.setStrokeWidth(20);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
DownY = event.getY();
DownX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
MoveY = event.getY();
MoveX = event.getX();
canvas.drawLine(DownX, DownY, MoveX, MoveY, paint1);
image1.invalidate();
DownX = MoveX;
DownY=MoveY;
break;
case MotionEvent.ACTION_UP:
UpY = event.getY();
UpX = event.getX();
canvas.drawLine(DownX, DownY, UpX, UpY, paint1);
image1.invalidate();
Bitmap BTXYZ = ((BitmapDrawable)image1.getDrawable()).getBitmap();
break;
}
return true;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "images");
request.setParameters(parameters);
request.executeAsync();
}
});
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.buttonchoose:
final ColorPicker cp = new ColorPicker(edit.this, 0, 0, 0);
/* Show color picker dialog */
cp.show();
/* On Click listener for the dialog, when the user select the color */
Button okColor = (Button) cp.findViewById(R.id.okColorButton);
okColor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/* You can get single channel (value 0-255) */
int selectedColorR = cp.getRed();
int selectedColorG = cp.getGreen();
int selectedColorB = cp.getBlue();
/* Or the android RGB Color (see the android Color class reference) */
int selectedColorRGB = cp.getColor();
Button buttonchoose = (Button) findViewById(R.id.buttonchoose);
buttonchoose.setText("");
buttonchoose.setBackgroundColor(selectedColorRGB);
cp.dismiss();
}
});
break;
case R.id.imageButton2:
int newImage = undos.size();
Log.e("Lenght of Array",""+newImage);
if(newImage >=1) {
Bitmap newImage2 = undos.get(newImage-2);
ImageView IMGXV = (ImageView) findViewById(R.id.image1);
IMGXV.setImageBitmap(newImage2);
undos.remove(newImage-1);
}
break;
}
}
}
Try this exact code -
case R.id.imageButton2:
if(undos.size() > 0) {
Bitmap newImage2 = undos.remove(undos.size() - 1);
ImageView IMGXV = (ImageView) findViewById(R.id.image1);
IMGXV.setImageBitmap(newImage2);
}
break;
EDIT Added an extra line in onGlobalLayout(), try this -
Bitmap bitmapF = Bitmap.createScaledBitmap(bitmap, ViewWidth, Math.round(height), false);
final ImageView image1 = (ImageView) findViewById(R.id.image1);
image1.setImageBitmap(bitmapF);
//The extra line before adding bitmap to arraylist.
Bitmap bitmapFcopy = bitmapFcopy.copy(bitmapFcopy.getConfig(), true);
undos.add(bitmapFcopy);
EDIT 2
public class edit extends AppCompatActivity implements View.OnClickListener {
//Declare the imageview here and access this everywhere.
ImageView image1;
float MoveX,MoveY,DownY,DownX,UpY=0,UpX ;
List<Bitmap> undos = new ArrayList<Bitmap>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit);
//Get the reference here
image1 = (ImageView) findViewById(R.id.image1);
final ImageButton btn2 = (ImageButton) findViewById(R.id.imageButton2);
btn2.setOnClickListener(this);
final Button buttonchoose = (Button) findViewById(R.id.buttonchoose);
buttonchoose.setOnClickListener(this);
final RelativeLayout ViewX = (RelativeLayout) findViewById(R.id.RLXV);
ViewTreeObserver vto = ViewX.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
ViewX.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Intent intent7 = getIntent();
String bitmapXY = (String) intent7.getExtras().get("BitmapImage");
GraphRequest request = GraphRequest.newGraphPathRequest(
AccessToken.getCurrentAccessToken(),
"/" + bitmapXY,
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
HttpURLConnection connection = null;
try {
int ViewWidth = ViewX.getMeasuredWidth();
JSONObject photos = response.getJSONObject();
JSONArray linkY = photos.optJSONArray("images");
final JSONObject linkO = linkY.optJSONObject(0);
final String link2 = linkO.optString("source");
URL LINKF = new URL(link2);
connection = (HttpURLConnection) LINKF.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
float HH = (float) bitmap.getHeight();
float WW = (float) bitmap.getWidth();
float ViewWidthX = (float) ViewWidth;
float height = (HH / WW) * ViewWidthX;
Bitmap bitmapF = Bitmap.createScaledBitmap(bitmap, ViewWidth, Math.round(height), false);
//Remove from here and declare this in onCreate() and don't make it final
//final ImageView image1 = (ImageView) findViewById(R.id.image1);
image1.setImageBitmap(bitmapF);
undos.add(bitmapF);
image1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Display d = getWindowManager().getDefaultDisplay();
float dw = d.getWidth();
float dh = d.getHeight();
float x = event.getX();
float y = event.getY();
float r = 2;
Bitmap BTX = ((BitmapDrawable)image1.getDrawable()).getBitmap();
Canvas canvas = new Canvas(BTX);
canvas.drawBitmap(BTX,0,0,null);
Paint paint1 = new Paint();
int bg1 = buttonchoose.getDrawingCacheBackgroundColor();
ColorDrawable buttonColor = (ColorDrawable) buttonchoose.getBackground();
int bg2 =buttonColor.getColor();
paint1.setColor(bg2);
paint1.setShadowLayer(5, 2, 2, bg2);
paint1.setStrokeWidth(20);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
DownY = event.getY();
DownX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
MoveY = event.getY();
MoveX = event.getX();
canvas.drawLine(DownX, DownY, MoveX, MoveY, paint1);
image1.invalidate();
DownX = MoveX;
DownY=MoveY;
break;
case MotionEvent.ACTION_UP:
UpY = event.getY();
UpX = event.getX();
canvas.drawLine(DownX, DownY, UpX, UpY, paint1);
image1.invalidate();
Bitmap BTXYZ = ((BitmapDrawable)image1.getDrawable()).getBitmap();
break;
}
return true;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "images");
request.setParameters(parameters);
request.executeAsync();
}
});
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.buttonchoose:
final ColorPicker cp = new ColorPicker(edit.this, 0, 0, 0);
/* Show color picker dialog */
cp.show();
/* On Click listener for the dialog, when the user select the color */
Button okColor = (Button) cp.findViewById(R.id.okColorButton);
okColor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/* You can get single channel (value 0-255) */
int selectedColorR = cp.getRed();
int selectedColorG = cp.getGreen();
int selectedColorB = cp.getBlue();
/* Or the android RGB Color (see the android Color class reference) */
int selectedColorRGB = cp.getColor();
Button buttonchoose = (Button) findViewById(R.id.buttonchoose);
buttonchoose.setText("");
buttonchoose.setBackgroundColor(selectedColorRGB);
cp.dismiss();
}
});
break;
case R.id.imageButton2:
int newImage = undos.size();
Log.e("Lenght of Array",""+newImage);
if(newImage >=1) {
Bitmap newImage2 = undos.get(newImage-2);
//Don't take reference again here
//ImageView IMGXV = (ImageView) findViewById(R.id.image1);
image1.setImageBitmap(newImage2);
undos.remove(newImage-1);
}
break;
}
}
}
Related
I am trying to create an object of fingerline(class) in drawline(activity).The fingerline takes the context of MainActivity(activity).I get ClassCastException showing that
Process: com.example.caddrawingtool, PID: 11405
java.lang.RuntimeException: Unable to instantiate application
com.example.caddrawingtool.MainActivity: java.lang.ClassCastException:
com.example.caddrawingtool.MainActivity cannot be cast to android.app.Application
at android.app.LoadedApk.makeApplication(LoadedApk.java:1226)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6504)
at android.app.ActivityThread.access$1400(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1892)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7436)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
I have changed getApplicationContext() in drawline where the fingerline object was created to Activity context by using
this
I am not able to use
MainActivity.this
though.
Is there a way to simplify all this?
My MainActivity code:
public class MainActivity extends AppCompatActivity {
fingerline dv;
private Paint mpaint;
private Context context;
MainActivity MainActivity(){
return MainActivity.this;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new fingerline(this);
setContentView(dv);
dv.setBackgroundColor(Color.BLACK);
mpaint = new Paint();
mpaint.setAntiAlias(true);
mpaint.setDither(true);
mpaint.setColor(Color.WHITE);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setStrokeJoin(Paint.Join.MITER);
mpaint.setStrokeCap(Paint.Cap.ROUND);
mpaint.setStrokeWidth(12);
getSupportActionBar().setTitle("3D TOOL");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.my_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.line:
Intent intent = new Intent(this, drawline2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
this.startActivity(intent);
break;
case R.id.circle:
Intent intent1=new Intent(this,drawcircle.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
this.startActivity(intent1);
break;
case R.id.rectangle:
Intent intent2=new Intent(this,drawrectangle.class);
intent2.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
this.startActivity(intent2);
break;
case R.id.offset:
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
My fingerline code:
public class fingerline extends View {
public int width, height;
private Bitmap mbitmap;
private Canvas mcanvas;
private Paint mpaint, mbitmappaint, circlepaint;
private float startx;
private float starty;
private float endx;
private float endy;
private Path path, circlepath;
Context c;
public fingerline(Context context) {
super(context);
// c = context;
path = new Path();
mpaint = new Paint();
mbitmappaint = new Paint(Paint.DITHER_FLAG);
circlepaint = new Paint();
circlepath = new Path();
circlepaint.setAntiAlias(true);
circlepaint.setColor(Color.WHITE);
circlepaint.setStyle(Paint.Style.STROKE);
circlepaint.setStrokeJoin(Paint.Join.MITER);
circlepaint.setStrokeWidth(4f);
}
#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) {
super.onDraw(canvas);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setColor(Color.WHITE);
mpaint.setStrokeWidth(12);
mpaint.setAntiAlias(true);
mpaint.setDither(true);
mpaint.setStrokeJoin(Paint.Join.MITER);
mpaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawBitmap(mbitmap, 0, 0, mbitmappaint);
canvas.drawPath(path, mpaint);
canvas.drawPath(circlepath, circlepaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
path.reset();
path.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) {
path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
path.lineTo(mX, mY);
circlepath.reset();
mcanvas.drawPath(path, mpaint);
path.reset();
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startx = event.getX();
starty = event.getY();
touch_start(startx, starty);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
startx = event.getX();
starty = event.getY();
touch_move(startx, starty);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
My drawline code:
public class drawline2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawline2);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
EditText editText, editText1;
editText = (EditText) findViewById(R.id.length);
editText1 = (EditText) findViewById(R.id.angle);
Canvas canvas;
Paint paint = new Paint();
Paint circlepaint = new Paint();
Path path = new Path();
Path cpath = new Path();
circlepaint.setAntiAlias(true);
circlepaint.setStrokeWidth(4f);
circlepaint.setColor(Color.WHITE);
circlepaint.setStyle(Paint.Style.STROKE);
circlepaint.setStrokeJoin(Paint.Join.MITER);
fingerline dv;
dv = new fingerline(this);
dv.setBackgroundColor(Color.BLACK);
setContentView(dv);
circlepaint.setAntiAlias(true);
circlepaint.setDither(true);
String value = editText.getText().toString();
int length =0;
double angle=0;
if(value!=null && value.length()>0){
try{
length = Integer.parseInt(value);
}
catch (NullPointerException e){
length=0;
}
}
String value1 = editText1.getText().toString();
if(value1!=null && value1.length()>0){
try{
angle = Double.parseDouble(value1);
}
catch (NullPointerException e){
angle=0;
}
}
int startX, startY, endX, endY, x, y;
x= 0;
y=0;
path.reset();
path.moveTo(x, y);
startX = (int) x;
startY = (int) y;
endY = (int) (x + length * Math.cos(angle));
endX = (int) (x + length * Math.sin(angle));
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
}
Thanks in advance.
In short:
MainActivity cannot be cast to android.app.Application
You could make this an awful lot more readable by calling it DrawlineActivity and FingerlineActivity. Then just use this or DrawlineActivity.this as the Context.
am developing a face recognition app. it gets the first bitman on a previous activity but it generates a new one with the faces labeled and i'd like to save that new bitmap. i've lost one day or two figuring it out but none of the answers i've tried helps.
this is the code for this activity, its supposed to save the bitmap into gallery when saveButton is pressed.
public class FaceRecognizeActivity extends AppCompatActivity {
Bitmap bmp, carasReconocidas;
ImageView imagen;
int contador;
Button guardarRostro, copiarRegistroRostro;
TextView descripcion;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setStatusBarColor(this.getResources().getColor(R.color.colorAccentLight));
setContentView(R.layout.activity_reconocer_rostros);
guardarRostro = (Button) findViewById(R.id.guardarRostros);
copiarRegistroRostro = (Button) findViewById(R.id.copiarRostros);
descripcion = (TextView) findViewById(R.id.descripcionRostros);
byte[] byteArray = getIntent().getByteArrayExtra("image");
bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
this.imagen = (ImageView) this.findViewById(R.id.caraReconocida);
imagen.setImageBitmap(bmp);
contador = 0;
final Paint boxPaint = new Paint();
carasReconocidas = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
final Canvas canvas = new Canvas (carasReconocidas);
canvas.drawBitmap(bmp, 0,0,null);
boxPaint.setStrokeWidth(8);
boxPaint.setColor(Color.GREEN);
boxPaint.setStyle(Paint.Style.STROKE);
procesar( canvas, boxPaint);
descripcion.setText(cantidad());
guardarRostro.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//TODO
}
})
;
copiarRegistroRostro.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Registro de rostros ", descripcion.getText().toString());
clipboard.setPrimaryClip(clip);
Toast.makeText(getApplicationContext(), "copiado", Toast.LENGTH_SHORT).show();
}
})
;
}
public void procesar(Canvas canvas, Paint boxPaint){
FaceDetector faceDetector = new FaceDetector.Builder(getApplicationContext())
.setTrackingEnabled(false)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setMode(FaceDetector.FAST_MODE)
.build();
if (!faceDetector.isOperational()){
Toast.makeText(getApplicationContext(), "Algo saliĆ³ mal", Toast.LENGTH_SHORT).show();
return;
}
Frame frame = new Frame.Builder().setBitmap(bmp).build();
SparseArray<Face> sparseArray = faceDetector.detect(frame);
for (int i = 0 ; i < sparseArray.size(); i++){
Face face = sparseArray.valueAt(i);
float x1= face.getPosition().x;
float y1= face.getPosition().y;
float x2= x1 + face.getWidth();
float y2= y1 + face.getHeight();
RectF rectF = new RectF(x1,y1,x2,y2);
canvas.drawRoundRect(rectF,2,2, boxPaint);
contador=contador + 1;
}
imagen.setImageBitmap(carasReconocidas);
}
public String cantidad(){
String texto;
if (contador == 0){
texto= "Parece que no hay personas en esta imagen.";
} else if (contador == 1) {
texto="Se reconociĆ³ una persona";
}else {
texto="Se reconocieron " + Integer.toString(contador) + " personas.";
}
return texto;
}
#Override
public void onBackPressed() {
Intent anotherIntent = new Intent(FaceRecognizeActivity.this, MenuActivity.class);
startActivity(anotherIntent);
}
}
I have a out of memory problem here in which i have full screen images being displayed. I want to show images in full screen and I have two buttons to cycle through them to the left or to the right. How can i have the past images be recycled before showing the next to prevent the out of memory exception? or is there an even better way to do so?
here is my class in which i view the image.
public class ImageViewActivity extends Activity
{
private Button btnHome;
private Button btnBack;
private ImageButton btnLeft;
private ImageButton btnRight;
ImageView imageView;
RelativeLayout layout;
int height;
int width;
Bitmap bitmap;
String[] imagesPath;
int position;
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
String savedItemClicked;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.imageview_activity);
btnHome = (Button) findViewById(R.id.btnHome);
btnBack = (Button) findViewById(R.id.btnBack);
btnLeft = (ImageButton) findViewById(R.id.leftArrow);
btnRight = (ImageButton) findViewById(R.id.rightArrow);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
height = displayMetrics.heightPixels;
width = displayMetrics.widthPixels;
imagesPath = getIntent().getStringExtra("IMAGES").split("\\|");
position = getIntent().getIntExtra("POSITION", 0);
bitmap = BitmapFactory.decodeFile(imagesPath[position]);
imageView = (ImageView)findViewById(R.id.displayImage);
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, width, height, false));
btnLeft.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
if (position == 0)
position = 5;
else
position--;
RectF imageRectF = new RectF(0, 0, width, height);
RectF viewRectF = new RectF(0, 0, width, height);
matrix.setRectToRect(imageRectF, viewRectF, Matrix.ScaleToFit.CENTER);
bitmap = BitmapFactory.decodeFile(imagesPath[position]);
ImageView imageView = (ImageView)findViewById(R.id.displayImage);
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, width, height, false));
imageView.setImageMatrix(matrix);
}
});
btnRight.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
if (position == 5)
position = 0;
else
position++;
RectF imageRectF = new RectF(0, 0, width, height);
RectF viewRectF = new RectF(0, 0, width, height);
matrix.setRectToRect(imageRectF, viewRectF, Matrix.ScaleToFit.CENTER);
bitmap = BitmapFactory.decodeFile(imagesPath[position]);
ImageView imageView = (ImageView)findViewById(R.id.displayImage);
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, width, height, false));
imageView.setImageMatrix(matrix);
}
});
btnHome.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
Intent ActivitySwitch = new Intent(getApplicationContext(), MainMenuActivity.class);
startActivity(ActivitySwitch);
}
});
btnBack.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
Intent ActivitySwitch = new Intent(getApplicationContext(), AddClientActivity.class);
startActivity(ActivitySwitch);
}
});
imageView.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
ImageView view = (ImageView) v;
dumpEvent(event);
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
// ...
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY()
- start.y);
} else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
});
}
private void dumpEvent(MotionEvent event) {
String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
"POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
StringBuilder sb = new StringBuilder();
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid ").append(
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")");
}
sb.append("[");
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if (i + 1 < event.getPointerCount())
sb.append(";");
}
sb.append("]");
}
/** Determine the space between the first two fingers */
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float)Math.sqrt(x * x + y * y);
}
/** Calculate the mid point of the first two fingers */
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
thank you for any input and if you need any additional information please feel free to ask!
I would either scale down the image or consider using the Picasso image loading library: http://square.github.io/picasso/
It is also really simply to use and prevents a lot Out of Memory Exceptions.
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
it was a lot simpler then i first imagined. i simply added this
bitmap.recycle();
before i declared my bitmap to the new image.
I have created simple app with pinch zoom, panning and rotation. They are working very well but not the rotation in your position.
I have used Matrix class.
My Activity code
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
Matrix saveMatrix = new Matrix();
private ImageView viewImage;
private Button btnCapture;
private static final int RESULT_LOAD_IMAGE = 1;
private static final int REQUEST_IMAGE_CAPTURE = 2;
Matrix matrix = new Matrix();
private Uri mCapturedImageURI;
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
private float d = 0f;
private float newRot = 0f;
private float[] lastEvent = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnCapture = (Button) findViewById(R.id.btnCapture);
viewImage = (ImageView) findViewById(R.id.viewImage);
viewImage.setOnTouchListener(MainActivity.this);
initListerner();
}
public void initListerner() {
btnCapture.setVisibility(View.VISIBLE);
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btnCapture.setVisibility(View.GONE);
final Dialog dialog = new Dialog(MainActivity.this);
dialog.setContentView(R.layout.custom_dialog_box);
dialog.setTitle("Title...");
Button dialogButton = (Button) dialog.findViewById(R.id.btnExit);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
Button btnChoosePath = (Button) dialog.findViewById(R.id.btnChoosePath);
btnChoosePath.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
activeGallery();
dialog.dismiss();
}
});
Button btnTakePhoto = (Button) dialog.findViewById(R.id.btnTakePhoto);
btnTakePhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
activeTakePhoto();
dialog.dismiss();
}
});
dialog.show();
}
});
}
#Override
public void onBackPressed() {
super.onBackPressed();
btnCapture.setVisibility(View.VISIBLE);
}
private void activeTakePhoto() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
String fileName = "temp.jpg";
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
mCapturedImageURI = getContentResolver()
.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
takePictureIntent
.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
private void activeGallery() {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RESULT_LOAD_IMAGE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_LOAD_IMAGE:
if (requestCode == RESULT_LOAD_IMAGE &&
resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver()
.query(selectedImage, filePathColumn, null, null,
null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
viewImage.setImageBitmap(BitmapFactory.decodeFile(picturePath));
}
case REQUEST_IMAGE_CAPTURE:
if (requestCode == REQUEST_IMAGE_CAPTURE &&
resultCode == RESULT_OK) {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor =
getContentResolver().query(mCapturedImageURI, projection, null,
null, null);
int column_index_data = cursor.getColumnIndexOrThrow(
MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String picturePath = cursor.getString(column_index_data);
cursor.close();
viewImage.setImageBitmap(BitmapFactory.decodeFile(picturePath));
}
}
}
#Override
public boolean onTouch(View v, MotionEvent motionEvent) {
ImageView view = (ImageView) v;
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
saveMatrix.set(matrix);
start.set(motionEvent.getX(), motionEvent.getY());
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(motionEvent);
if (oldDist > 10f) {
saveMatrix.set(matrix);
midPoint(mid, motionEvent);
mode = ZOOM;
}
lastEvent = new float[4];
lastEvent[0] = motionEvent.getX(0);
lastEvent[1] = motionEvent.getX(1);
lastEvent[2] = motionEvent.getY(0);
lastEvent[3] = motionEvent.getY(1);
d = rotation(motionEvent);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(saveMatrix);
float dx = motionEvent.getX() - start.x;
float dy = motionEvent.getY() - start.y;
matrix.postTranslate(dx, dy);
} else if (mode == ZOOM) {
float newDist = spacing(motionEvent);
if (newDist > 10f) {
matrix.set(saveMatrix);
float scale = (newDist / oldDist);
matrix.postScale(scale, scale, mid.x, mid.y);
}
if (lastEvent != null && motionEvent.getPointerCount() == 2) {
newRot = rotation(motionEvent);
float r = newRot - d;
float[] values = new float[9];
matrix.getValues(values);
float tx = values[2];
float ty = values[5];
float sx = values[0];
float xc = (view.getWidth() / 2) * sx;
float yc = (view.getHeight() / 2) * sx;
matrix.postRotate(r, tx + xc, ty + yc);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
private float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
}
I have this class and I want to save my drawing to a jpeg file when the actionbar is clicked.
public class SingleTouchActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SingleTouchEventView(this, null));
// Create ActionBar
ActionBar actionBar = getActionBar();
actionBar.show();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// ActionBar is clicked
switch (item.getItemId()) {
case R.id.sig_reset:
finish();
Intent sigIntent = new Intent(this, SingleTouchActivity.class);
startActivity(sigIntent);
break;
case R.id.sig_save:
//Save to image
break;
}
return true;
}
I searched the web and I found this code snippet:
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
b.compress(CompressFormat.JPEG, 95, new FileOutputStream("/some/location/image.jpg"));
And this one:
//createBitmap(int width, int height, Bitmap.Config config)
// Returns a mutable bitmap with the specified width and height.
Bitmap image = Bitmap.createBitmap(mapRelativeView.getWidth(), mapRelativeView.getHeight(), Bitmap.Config.RGB_565);
//draw(Canvas canvas) -- Manually render this view
//(and all of its children) to the given Canvas.
yourView.draw(new Canvas(image));
//insertImage(ContentResolver cr, Bitmap source, String title, String description)
// Insert an image and create a thumbnail for it.
//uri is the path after the image has been saved.
String uri = Images.Media.insertImage(getContentResolver(), image, "title", null);
The problem is that my SingleTouchActivity set's SingleTouchEventView as content, and I don't know how I have to define my view.
This is Free Hand Draw Example where you can draw anything and save as image in SD Card.
DownLoad Full Source Form Here
This is main OnCreate() method where that perform some specific task.
Like :
Check path is Exist if no then Set Image Path .
Set Image Name as per current Date & Time.
prepare Screen View.
Draw Signature.
Store in SD Card.
Return to Activity with Bitmap Image so it can be set on Image View.
Clear Drawable Signature.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.signature);
// tempDir = Environment.getExternalStorageDirectory() + "/" + getResources().getString(R.string.external_dir) + "/";
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// File directory = cw.getDir(getResources().getString(R.string.external_dir), Context.MODE_PRIVATE);
File directory = new File(Environment.getExternalStorageDirectory() + "/Your_Floder_Name");
Check path is Exist if no then Set Image Path .
if(!directory.exists())
directory.mkdir(); //directory is created;
//prepareDirectory();
Set Image Name as per current Date & Time.
uniqueId = getTodaysDate() + "_" + getCurrentTime();
current = uniqueId + ".png";
mypath= new File(directory,current);
mContent = (LinearLayout) findViewById(R.id.linearLayout);
Draw Signature
mSignature = new signature(this, null);
mSignature.setBackgroundColor(Color.WHITE);
prepare Screen View.
mContent.addView(mSignature, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
Clear Drawable Signature.
mClear = (Button)findViewById(R.id.clear);
mGetSign = (Button)findViewById(R.id.getsign);
mGetSign.setEnabled(false);
mCancel = (Button)findViewById(R.id.cancel);
mView = mContent;
Clear Drawable Signature.
mClear.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Log.v("log_tag", "Panel Cleared");
mSignature.clear();
mGetSign.setEnabled(false);
}
});
Draw Signature
mGetSign.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Log.v("log_tag", "Panel Saved");
// boolean error = captureSignature();
// if(error){
mView.setDrawingCacheEnabled(true);
mSignature.save(mView);
//Bundle b = new Bundle();
// b.putString("status", "done");
Intent intent = new Intent(Capture.this,SigntuareCaptureActivity.class);
// intent.putExtra("imagePath",mypath);
startActivity(intent);
//intent.putExtra("status", "done");
//setResult(RESULT_OK,intent);
finish();
// }
}
});
Cancel if Don't want to Draw Signature.
mCancel.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Log.v("log_tag", "Panel Canceled");
Bundle b = new Bundle();
b.putString("status", "cancel");
Intent intent = new Intent();
intent.putExtras(b);
setResult(RESULT_OK,intent);
finish();
}
});
}
Set Image Name With Current Date & Time.
private String getTodaysDate()
{
final Calendar c = Calendar.getInstance();
int todaysDate = (c.get(Calendar.YEAR) * 10000) +
((c.get(Calendar.MONTH) + 1) * 100) +
(c.get(Calendar.DAY_OF_MONTH));
Log.w("DATE:",String.valueOf(todaysDate));
return(String.valueOf(todaysDate));
}
private String getCurrentTime()
{
final Calendar c = Calendar.getInstance();
int currentTime = (c.get(Calendar.HOUR_OF_DAY) * 10000) +
(c.get(Calendar.MINUTE) * 100) +
(c.get(Calendar.SECOND));
Log.w("TIME:",String.valueOf(currentTime));
return(String.valueOf(currentTime));
}
Check Your Directory if Not Exist then Create New
private boolean prepareDirectory()
{
try
{
if (makedirs())
{
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
e.printStackTrace();
Toast.makeText(this, "Could not initiate File System.. Is Sdcard mounted properly?", 1000).show();
return false;
}
}
private boolean makedirs()
{
File tempdir = new File(tempDir);
if (!tempdir.exists())
tempdir.mkdirs();
if (tempdir.isDirectory())
{
File[] files = tempdir.listFiles();
for (File file : files)
{
if (!file.delete())
{
System.out.println("Failed to delete " + file);
}
}
}
return (tempdir.isDirectory());
}
Draw your Signature
public class signature extends View
{
private static final float STROKE_WIDTH = 5f;
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
private Paint paint = new Paint();
private Path path = new Path();
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();
public signature(Context context, AttributeSet attrs)
{
super(context, attrs);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
public void save(View v)
{
Log.v("log_tag", "Width: " + v.getWidth());
Log.v("log_tag", "Height: " + v.getHeight());
if(mBitmap == null)
{
mBitmap = Bitmap.createBitmap (mContent.getWidth(), mContent.getHeight(), Bitmap.Config.RGB_565);
}
Canvas canvas = new Canvas(mBitmap);
try
{
FileOutputStream mFileOutStream = new FileOutputStream(mypath);
v.draw(canvas);
mBitmap.compress(Bitmap.CompressFormat.PNG, 90, mFileOutStream);
mFileOutStream.flush();
mFileOutStream.close();
String url = Images.Media.insertImage(getContentResolver(), mBitmap, "title", null);
//Log.v("log_tag","url: " + url);
// //In case you want to delete the file
// boolean deleted = mypath.delete();
// Log.v("log_tag","deleted: " + mypath.toString() + deleted);
// //If you want to convert the image to string use base64 converter
}
catch(Exception e)
{
Log.v("log_tag", e.toString());
}
}
public void clear()
{
path.reset();
invalidate();
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawPath(path, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
float eventY = event.getY();
mGetSign.setEnabled(true);
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
lastTouchX = eventX;
lastTouchY = eventY;
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
resetDirtyRect(eventX, eventY);
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++)
{
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
}
path.lineTo(eventX, eventY);
break;
default:
debug("Ignored touch event: " + event.toString());
return false;
}
invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH),
(int) (dirtyRect.top - HALF_STROKE_WIDTH),
(int) (dirtyRect.right + HALF_STROKE_WIDTH),
(int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
lastTouchX = eventX;
lastTouchY = eventY;
return true;
}
private void debug(String string)
{
}
private void expandDirtyRect(float historicalX, float historicalY)
{
if (historicalX < dirtyRect.left)
{
dirtyRect.left = historicalX;
}
else if (historicalX > dirtyRect.right)
{
dirtyRect.right = historicalX;
}
if (historicalY < dirtyRect.top)
{
dirtyRect.top = historicalY;
}
else if (historicalY > dirtyRect.bottom)
{
dirtyRect.bottom = historicalY;
}
}
private void resetDirtyRect(float eventX, float eventY)
{
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
}
How to call this class ?
on Click of button in main Activity ,
your_button.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
Intent intent = new Intent(SigntuareCaptureActivity.this, Capture.class);
startActivity(intent);
finish();
}
});