Reputation: 338
I am doing a photo editing function that kinda works like a water mark.
The user selects the image A. After the image is selected, the user can select another image B to populate on top of the image A and they can move the image B around while image A is still static at the back.
After the placement of image B is done, the user can merge both image into one and save it as a single image.
I got the movement of image B function done but i am not sure how to actually combine the two images together.
Edit 1: I want them to be either taken from the camera or gallery then combine the two images, B over A and save it to SD Card
Edit 2: This is what i did to make the image B to move around my view. Now all i need is to connect the image b to the main image (which is in the background) and save it as a SD card. Is there a way to actually integrate both imageviews and its custom position (image B) and create a bitmap that can be saved to the sd card.
private ImageView img_additionalImage;
float x, y = 0.0f;
boolean isImageMoving = false;
img_additionalImage = (ImageView) findViewById(R.id.img_additionalImage);
img_additionalImage.setOnTouchListener(new OnTouchListener()
{
@SuppressLint("NewApi")
@Override
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
isImageMoving = true;
break;
case MotionEvent.ACTION_MOVE:
if (isImageMoving)
{
x = event.getRawX() - img_additionalImage.getWidth() / 2;
y = event.getRawY() - img_additionalImage.getHeight() / 2;
img_additionalImage.setX(x);
img_additionalImage.setY(y);
}
break;
case MotionEvent.ACTION_UP:
isImageMoving = false;
break;
}
return true;
}
});
Edit 3: This is the code that gives me nullpointer when i call this.
MainActivity
CombineImages combineImages = new CombineImages(MainActivity.this);
img_additionalImage = (ImageView) findViewById(R.id.img_additionalImage);
combineImages.combine(img_additionalImage);
The CombineImages class is what you have provided.
12-31 20:54:33.470: E/AndroidRuntime(6330): FATAL EXCEPTION: main
12-31 20:54:33.470: E/AndroidRuntime(6330): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.photosharingtest2/com.example.photosharingtest2.MainActivity}: java.lang.NullPointerException
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2024)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.app.ActivityThread.access$600(ActivityThread.java:140)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.os.Handler.dispatchMessage(Handler.java:99)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.os.Looper.loop(Looper.java:137)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.app.ActivityThread.main(ActivityThread.java:4898)
12-31 20:54:33.470: E/AndroidRuntime(6330): at java.lang.reflect.Method.invokeNative(Native Method)
12-31 20:54:33.470: E/AndroidRuntime(6330): at java.lang.reflect.Method.invoke(Method.java:511)
12-31 20:54:33.470: E/AndroidRuntime(6330): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
12-31 20:54:33.470: E/AndroidRuntime(6330): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
12-31 20:54:33.470: E/AndroidRuntime(6330): at dalvik.system.NativeStart.main(Native Method)
12-31 20:54:33.470: E/AndroidRuntime(6330): Caused by: java.lang.NullPointerException
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.content.ContextWrapper.getResources(ContextWrapper.java:81)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.view.View.<init>(View.java:3314)
12-31 20:54:33.470: E/AndroidRuntime(6330): at com.example.photosharingtest2.CombineImages.<init>(CombineImages.java:27)
12-31 20:54:33.470: E/AndroidRuntime(6330): at com.example.photosharingtest2.MainActivity.<init>(MainActivity.java:39)
12-31 20:54:33.470: E/AndroidRuntime(6330): at java.lang.Class.newInstanceImpl(Native Method)
12-31 20:54:33.470: E/AndroidRuntime(6330): at java.lang.Class.newInstance(Class.java:1319)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.app.Instrumentation.newActivity(Instrumentation.java:1057)
12-31 20:54:33.470: E/AndroidRuntime(6330): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2015)
12-31 20:54:33.470: E/AndroidRuntime(6330): ... 11 more
Upvotes: 0
Views: 1915
Reputation: 32221
I wrote some thing simple for you. It is a view with canvas buffer, that have combine method. It draw images on buffer and display them. Your application need to have two views, CombineImages
and the view your user is currently moving. Once he set it's position you call the CombineImages.combine to add that image to your view and than you can delete that image, you are ready now to add another image.
Currently I place all the images to top left, you should edit my code a bit to make this work with costume positions.
Also note that it is safe to call CombineImages.combine
not from UI-Thread
public class CombineImages extends View{
private Bitmap buffer;
private Canvas canvas;
private Matrix matrix = new Matrix();
public CombineImages(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CombineImages(Context context) {
super(context);
}
public void combine(ImageView imageView){
Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
combine(bitmap);
}
public void combine(Bitmap bitmap) {
updateBuffer(bitmap);
draw(canvas);
postInvalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(buffer, matrix , null);
}
private void updateBuffer(Bitmap bitmap) {
if(buffer == null){
createBuffer(bitmap);
}
else{
if(bitmap.getWidth() > buffer.getWidth() || bitmap.getHeight() > buffer.getHeight()){
Bitmap oldBuffer = buffer;
createBuffer(bitmap);
drawBitmnapToBuffer(oldBuffer);
oldBuffer.recycle();
}
drawBitmnapToBuffer(bitmap);
}
getLayoutParams().height = buffer.getHeight();
getLayoutParams().width = buffer.getWidth();
}
private void drawBitmnapToBuffer(Bitmap bitmap) {
canvas.save();
// add your translation logic here using canvas.translate(dx, dy);
canvas.drawBitmap(bitmap, matrix, null);
canvas.restore();
}
private void createBuffer(Bitmap bitmap) {
buffer = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
canvas = new Canvas(buffer);
}
}
Upvotes: 1
Reputation: 23638
The simplest way to capture the image which you have rendered is to make the layout of your ImageView
as setDrawingCacheEnabled
to true which will allow you to capture the image of the imageview and convert it into the Bitmap
and save it into sdcard.
ImageView imageView = (ImageView)findViewById(R.id.imageview_here);
imageView.setDrawingCacheEnabled(true);
imageView.buildDrawingCache(true);
Bitmap bitmap = Bitmap.createBitmap(imageView.getDrawingCache());
imageView.setDrawingCacheEnabled(false);
Save the image as below into sdcard.
String root = Environment.getExternalStorageDirectory().toString();
File newDir = new File(root + "/saved_images");
newDir.mkdirs();
Random gen = new Random();
int n = 10000;
n = gen.nextInt(n);
String fotoname = "photo-" + n + ".jpg";
File file = new File(newDir, fotoname);
String s = file.getAbsolutePath();
System.err.print("******************" + s);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) { }
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
}
Upvotes: 2
Reputation: 10856
if you have use RealtiveLayout or LinearLayout than you can capture that view by this way..
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
b.compress(CompressFormat.JPEG, 95, new FileOutputStream("/some/location/image.jpg"));
Where view is your View. The 95 is the quality of the JPG compression. And the file output stream is just that.
Upvotes: 0