0

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

用户选择图像A。选择图像后,用户可以选择另一个图像B来填充图像A的顶部,他们可以移动图像B,而图像A在后面仍然是静止的。

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

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

编辑1: 我希望它们是从相机或画廊中拍摄的,然后将两个图像组合在一起,B over 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: 这是当我调用它时给我空指针的代码。

主要活动

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
4

3 回答 3

2

捕获您渲染的图像的最简单方法是将您的布局设置为ImageViewtrue 这将允许您捕获 imageview 的图像并将其转换为并将其保存到 sdcard。setDrawingCacheEnabledBitmap

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

将如下图保存到 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) {

        }
于 2013-12-31T09:00:01.303 回答
1

我为你写了一些简单的东西。这是一个带有画布缓冲区的视图,具有组合方法。它在缓冲区上绘制图像并显示它们。您的应用程序需要有两个视图,CombineImages以及您的用户当前正在移动的视图。一旦他设置了它的位置,您调用 CombineImages.combine 将该图像添加到您的视图中,然后您可以删除该图像,您现在可以添加另一个图像。

目前我将所有图像放在左上角,您应该稍微编辑一下我的代码以使其适用于服装位置。

另请注意,CombineImages.combine不从 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);
            }
        }
于 2013-12-31T09:27:06.257 回答
0

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

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

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

于 2013-12-31T09:21:38.323 回答