Pages

Tuesday, April 5, 2016

Open image free draw something on bitmap and save bitmap to ExternalStorage

Example to load image with intent of Intent.ACTION_PICK, free draw something on the image, and save the bitmap to storage.


I have a series example of "Something about processing images in Android", but have show how to save the result bitmap to SD Card. This example modify from one of the example "Detect touch and free draw on Bitmap", add the function to save the result bitmap to External Storage, with file name "test.jpg".


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
android_orientation="vertical"
tools_context="com.blogspot.android_er.androiddrawbitmap.MainActivity">

<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_gravity="center_horizontal"
android_autoLink="web"
android_text="http://android-er.blogspot.com/"
android_textStyle="bold" />

<Button
android_id="@+id/loadimage"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="Load Image" />

<Button
android_id="@+id/saveimage"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="Save Image" />

<ImageView
android_id="@+id/result"
android_scaleType="centerInside"
android_adjustViewBounds="true"
android_layout_gravity="center"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_background="@android:color/background_dark" />
</LinearLayout>


MainActivity.java
package com.blogspot.android_er.androiddrawbitmap;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {

Button btnLoadImage, btnSaveImage;
ImageView imageResult;

final int RQS_IMAGE1 = 1;

Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;

int prvX, prvY;

Paint paintDraw;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnLoadImage = (Button)findViewById(R.id.loadimage);
btnSaveImage = (Button)findViewById(R.id.saveimage);
imageResult = (ImageView)findViewById(R.id.result);

paintDraw = new Paint();
paintDraw.setStyle(Paint.Style.FILL);
paintDraw.setColor(Color.WHITE);
paintDraw.setStrokeWidth(10);

btnLoadImage.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

btnSaveImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(bitmapMaster != null){
saveBitmap(bitmapMaster);
}
}
});

imageResult.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {

int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
prvX = x;
prvY = y;
drawOnProjectedBitMap((ImageView) v, bitmapMaster, prvX, prvY, x, y);
break;
case MotionEvent.ACTION_MOVE:
drawOnProjectedBitMap((ImageView) v, bitmapMaster, prvX, prvY, x, y);
prvX = x;
prvY = y;
break;
case MotionEvent.ACTION_UP:
drawOnProjectedBitMap((ImageView) v, bitmapMaster, prvX, prvY, x, y);
break;
}
/*
* Return true to indicate that the event have been consumed.
* If auto-generated false, your code can detect ACTION_DOWN only,
* cannot detect ACTION_MOVE and ACTION_UP.
*/
return true;
}
});
}

/*
Project position on ImageView to position on Bitmap draw on it
*/

private void drawOnProjectedBitMap(ImageView iv, Bitmap bm,
float x0, float y0, float x, float y){
if(x<0 || y<0 || x > iv.getWidth() || y > iv.getHeight()){
//outside ImageView
return;
}else{

float ratioWidth = (float)bm.getWidth()/(float)iv.getWidth();
float ratioHeight = (float)bm.getHeight()/(float)iv.getHeight();

canvasMaster.drawLine(
x0 * ratioWidth,
y0 * ratioHeight,
x * ratioWidth,
y * ratioHeight,
paintDraw);
imageResult.invalidate();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

Bitmap tempBitmap;

if(resultCode == RESULT_OK){
switch (requestCode){
case RQS_IMAGE1:
source = data.getData();

try {
//tempBitmap is Immutable bitmap,
//cannot be passed to Canvas constructor
tempBitmap = BitmapFactory.decodeStream(
getContentResolver().openInputStream(source));

Bitmap.Config config;
if(tempBitmap.getConfig() != null){
config = tempBitmap.getConfig();
}else{
config = Bitmap.Config.ARGB_8888;
}

//bitmapMaster is Mutable bitmap
bitmapMaster = Bitmap.createBitmap(
tempBitmap.getWidth(),
tempBitmap.getHeight(),
config);

canvasMaster = new Canvas(bitmapMaster);
canvasMaster.drawBitmap(tempBitmap, 0, 0, null);

imageResult.setImageBitmap(bitmapMaster);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

break;
}
}
}

private void saveBitmap(Bitmap bm){
File file = Environment.getExternalStorageDirectory();
File newFile = new File(file, "test.jpg");

try {
FileOutputStream fileOutputStream = new FileOutputStream(newFile);
bm.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
Toast.makeText(MainActivity.this,
"Save Bitmap: " + fileOutputStream.toString(),
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this,
"Something wrong: " + e.getMessage(),
Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this,
"Something wrong: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
}


"android.permission.WRITE_EXTERNAL_STORAGE" is needed in AndroidManifest.xml. Also I add android_largeHeap="true" to require more heap for the app. But if you have a really big image, it still will closed, caused by Out Of Memory!
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.blogspot.android_er.androiddrawbitmap">

<uses-permission android_name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android_largeHeap="true"
android_allowBackup="true"
android_icon="@mipmap/ic_launcher"
android_label="@string/app_name"
android_supportsRtl="true"
android_theme="@style/AppTheme">
<activity android_name=".MainActivity">
<intent-filter>
<action android_name="android.intent.action.MAIN" />

<category android_name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


download filesDownload the files (Android Studio Format) .

more: Something about processing images in Android

Related Posts by Categories

0 comments:

Post a Comment