在另一个图像上叠加图像

时间:2013-12-31 08:46:24

标签: android android-imageview android-bitmap

我正在做一个有点像水印的照片编辑功能。

用户选择图像A.在选择图像之后,用户可以选择另一图像B填充在图像A的顶部,并且他们可以移动图像B,而图像A在后面仍然是静止的。 / p>

完成图像B的放置后,用户可以将两个图像合并为一个并将其另存为单个图像

我完成了图像B功能的运动,但我不确定如何将两个图像实际组合在一起。

编辑1: 我希望它们可以从相机或画廊中取出然后合并两张图像,B在A上并将其保存到SD卡

编辑2: 这就是我让图像B在我的视野中移动的方法。现在我需要的是将图像b连接到主图像(在后台)并将其保存为SD卡。有没有办法实际集成图像视图及其自定义位置(图像B)并创建可以保存到SD卡的位图。

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;
        }
    });

编辑3: 当我调用它时,这是给我nullpointer的代码。

MainActivity

CombineImages combineImages = new CombineImages(MainActivity.this);
img_additionalImage = (ImageView) findViewById(R.id.img_additionalImage);
combineImages.combine(img_additionalImage);

您提供的是CombineImages类。

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

3 个答案:

答案 0 :(得分:2)

捕获已渲染图像的最简单方法是将ImageView的布局设为setDrawingCacheEnabled true ,这样您就可以捕获图像将imageview转换为Bitmap并将其保存到SD卡中。

ImageView imageView = (ImageView)findViewById(R.id.imageview_here);
imageView.setDrawingCacheEnabled(true);
imageView.buildDrawingCache(true);
Bitmap bitmap = Bitmap.createBitmap(imageView.getDrawingCache());
imageView.setDrawingCacheEnabled(false);

将图片如下所示保存到SD卡中。

           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) {

        }

答案 1 :(得分:1)

我为你写了一些简单的事情。它是一个带有画布缓冲区的视图,它具有组合方法。它在缓冲区上绘制图像并显示它们。您的应用需要有两个视图CombineImages和您的用户当前正在移动的视图。一旦他设置了它的位置,你就可以调用Combine说明书将该图像添加到视图中,而不是删除该图像,现在就可以添加另一个图像。

目前我将所有图片放在左上角,你应该稍微编辑我的代码,使其与服装位置一起工作。

另请注意,不能从UI-Thread

调用CombineImages.combine是安全的
    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);
            }
        }

答案 2 :(得分:0)

如果您使用RealtiveLayout或LinearLayout,则可以通过这种方式捕获该视图。

view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
b.compress(CompressFormat.JPEG, 95, new FileOutputStream("/some/location/image.jpg"));

视图是您的视图。 95是JPG压缩的质量。文件输出流就是那个。