安卓群头像-9宫格头像合成

38 阅读3分钟

上图

截屏2024-03-19 10.51.54.png

逻辑

当图片是2张时,整张图片是2*2的 正方形,第1.2张占满第1.5行

当图片是3张时,整张图片是2*2的 正方形,第1.2张占满第一行,第三张图片第二行居中

当图片是4张时,整张图片是2*2的 正方形

当图片是5张时,整张图片是3*3的 正方形,第1.2.3张占满第1.5行,第4.5 张图片第2.5行居中

当图片是6张时,整张图片是3*3的 正方形,第1.2.3张占满第1.5行,第4.5.6 张图片占满第2.5行

当图片是7张时,整张图片是3*3的 正方形,第1.2.3张占满第1行,第4.5.6 张图片占满第2行,第7张第3行居中

当图片是7张时,整张图片是3*3的 正方形,第1.2.3张占满第1行,第4.5.6 张图片占满第2行,第7.8张第3行居中

当图片是9张时,整张图片是3*3的 正方形

上代码

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import android.graphics.Paint;


public class GroupIconGenerator {

    private OkHttpClient client = new OkHttpClient();

    public void createGroupIcon(final Context context, List<String> imageUrls, final GroupIconCallback callback) {
        if(imageUrls.size()>9){
            imageUrls= imageUrls.subList(0,8);
        }
        final CountDownLatch latch = new CountDownLatch(imageUrls.size());
        final List<Bitmap> bitmaps = new ArrayList<>();

        for (String url : imageUrls) {
            Request request = new Request.Builder().url(url).build();
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    latch.countDown();
                    // Handle failure
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (response.isSuccessful()) {
                        InputStream inputStream = response.body().byteStream();
                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                        synchronized (bitmaps) {
                            bitmaps.add(bitmap);
                        }
                    }
                    latch.countDown();
                }
            });
        }

        new Thread(() -> {
            try {
                latch.await(); // Wait for all downloads to complete
                Bitmap groupIcon = combineImagesToGrid(bitmaps); // Combine images to grid
                String filePath = saveBitmapToFile(context, groupIcon); // Save bitmap to file
                callback.onGroupIconGenerated(filePath); // Callback with file path
            } catch (InterruptedException | IOException e) {
                callback.onError(e); // Handle errors
            }
        }).start();
    }

    public Bitmap combineImagesToGrid(List<Bitmap> images) {
        if (images == null || images.isEmpty()) {
            throw new IllegalArgumentException("Image list must not be null or empty");
        }

        int imageCount = images.size();
        if (imageCount > 9 || imageCount < 2) {
            throw new IllegalArgumentException("Image count should be between 2 and 9");
        }

        // 设置每张图的最大尺寸
        int maxImageSize = 640; // 这个值可以根据需要调整
        int gridSpacing = 10; // 网格间的间距

        // 根据图片数量计算网格的宽高
        int rows, cols, gridWidth, gridHeight;
        if (imageCount <= 4) {
            rows = cols = 2;
        } else {
            rows = cols = 3;
        }

        gridWidth = cols * maxImageSize + (cols - 1) * gridSpacing;
        gridHeight = rows * maxImageSize + (rows - 1) * gridSpacing;

        // 创建一个大的Bitmap作为底图
        Bitmap result = Bitmap.createBitmap(gridWidth, gridHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();

        // 绘制半透明黑色背景
        int backgroundColor = Color.WHITE;
        canvas.drawColor(backgroundColor);

        int left, top;
        for (int i = 0; i < images.size(); i++) {
            int colNum = i % cols; // 计算列位置
            int rowNum = i / cols; // 计算行位置

            // 根据不同的图片数量和索引计算left和top的值
            if (imageCount == 2) {
                left = colNum * (maxImageSize + gridSpacing);
                top = (gridHeight - maxImageSize) / 2; // 居中
            } else if (imageCount == 3 && i == 2) {
                left = (gridWidth - maxImageSize) / 2; // 居中
                top = maxImageSize + gridSpacing;
            } else if (imageCount == 5 ) {
                if (i < 3) {
                    // 前三张图片(第一行)
                    left = colNum * (maxImageSize + gridSpacing);
                    top = (gridHeight - 2 * maxImageSize - gridSpacing) / 2; // 垂直居中的起始位置
                } else {
                    // 后两张图片(第二行)
                    left = ((gridWidth - 2 * maxImageSize - gridSpacing) / 2) + (i - 3) * (maxImageSize + gridSpacing);
                    top = ((gridHeight - 2 * maxImageSize - gridSpacing) / 2) + maxImageSize + gridSpacing; // 垂直居中的第二行位置
                }
            } else if (imageCount == 6) {
                left = colNum * (maxImageSize + gridSpacing);
                if (i < 3) {
                    // 前三张图片(第一行)
                    top = (gridHeight - 2 * maxImageSize - gridSpacing) / 2; // 垂直居中的起始位置
                } else {
                    // 后三张图片(第二行)
                    top = ((gridHeight - 2 * maxImageSize - gridSpacing) / 2) + maxImageSize + gridSpacing; // 垂直居中的第二行位置
                }
            } else if (imageCount == 7 && i == 6) {
                left = (gridWidth - maxImageSize) / 2; // 居中
                top = 2 * (maxImageSize + gridSpacing);
            } else if (imageCount == 8 && i >= 6) {
                left = ((gridWidth - 2 * maxImageSize - gridSpacing) / 2) + (i - 6) * (maxImageSize + gridSpacing);
                top = 2 * (maxImageSize + gridSpacing);
            } else {
                left = colNum * (maxImageSize + gridSpacing);
                top = rowNum * (maxImageSize + gridSpacing);
            }

            // 缩放Bitmap
            Bitmap scaledBitmap = Bitmap.createScaledBitmap(images.get(i), maxImageSize, maxImageSize, true);

            // 将图片绘制到Canvas上
            canvas.drawBitmap(scaledBitmap, left, top, paint);

            // 如果你不再需要这个缩放后的bitmap, 请确保它被回收
            if (scaledBitmap != images.get(i)) {
                scaledBitmap.recycle();
            }
        }

        return result;
    }



    private String saveBitmapToFile(Context context, Bitmap bitmap) throws IOException {
        String fileName = "group_icon_" + System.currentTimeMillis() + ".png";
        File directory = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File file = new File(directory, fileName);

        FileOutputStream out = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        out.flush();
        out.close();

        return file.getAbsolutePath();
    }

    public interface GroupIconCallback {
        void onGroupIconGenerated(String filePath);
        void onError(Exception e);
    }
}