• javacv 图片合成


    /**
     * 图片组合
     */
    @Slf4j
    public class ComposeImageUtil {
    
        /**
         * 合成商品链接
         *
         * @param composeGoodsImageCmd
         * @param oSSUtil
         * @return
         */
        public static String handleComposeGoodsImage(ComposeGoodsImageCmd composeGoodsImageCmd, OSSUtil oSSUtil) {
            //图片上传路径
            String keyName = composeGoodsImageCmd.getKeyName();
            //合成图宽高
            Long imgWidth = composeGoodsImageCmd.getImgWidth();
            Long imgHigh = composeGoodsImageCmd.getImgHigh();
            //修正规则
            String amendmentRules = composeGoodsImageCmd.getAmendmentRules();
            //主商品有效面积(英文逗号隔开)
            String effectiveArea = composeGoodsImageCmd.getEffectiveArea();
            //主商品中心点坐标(x_y,x_y,x_y)
            String centralPoint = composeGoodsImageCmd.getCentralPoint();
            //主商品合成顺序(英文逗号隔开)
            String order = composeGoodsImageCmd.getOrder();
            //前置商品数
            Integer frontGoodsNum = composeGoodsImageCmd.getFrontGoodsNum() == null ? 0 : composeGoodsImageCmd.getFrontGoodsNum();
            List<DubboWeimobCollocationGoodsBaseDTO> collocationGoodsBaseList = composeGoodsImageCmd.getCollocationGoodsBaseDTOList();
            if (
                    ObjectUtils.isEmpty(imgWidth) || imgWidth < 1 ||
                            ObjectUtils.isEmpty(imgHigh) || imgHigh < 1 ||
                            StringUtils.isBlank(amendmentRules) || StringUtils.isBlank(effectiveArea) ||
                            StringUtils.isBlank(centralPoint) || StringUtils.isBlank(order) ||
                            ObjectUtils.isEmpty(collocationGoodsBaseList) || StringUtils.isBlank(keyName)
            ) {
                log.error("handleComposeGoodsImage attribute is null. imgWidth ={},imgHigh ={},amendmentRules ={},EffectiveArea ={},CentralPoint ={},Order ={},collocationGoodsBaseList size={}",
                        imgWidth, imgHigh, amendmentRules, effectiveArea, centralPoint, order, collocationGoodsBaseList.size());
                return null;
            }
            //修正规则
            Map<Integer, List<AmendmentRule>> aidaCollocateAmendmentRuleMap = JSONObject.parseObject(amendmentRules, HashMap.class);
            //主商品有效面积转换
            String[] EffectiveAreaStr = effectiveArea.split(",");
            long[] EffectiveAreaArray = new long[EffectiveAreaStr.length];
            for (int EffectiveAreaindex = 0; EffectiveAreaindex < EffectiveAreaStr.length; EffectiveAreaindex++) {
                EffectiveAreaArray[EffectiveAreaindex] = Integer.parseInt(EffectiveAreaStr[EffectiveAreaindex]);
            }
            //主商品中心点坐标(x_y,x_y,x_y)转换
            String[] CentralPointStr = centralPoint.split(",");
            int[][] CentralPointArray = new int[CentralPointStr.length][2];
            for (int CentralPointindex = 0; CentralPointindex < CentralPointStr.length; CentralPointindex++) {
                String[] point = CentralPointStr[CentralPointindex].split("_");
                CentralPointArray[CentralPointindex] = new int[]{Integer.parseInt(point[0]), Integer.parseInt(point[1])};
            }
            //组合顺序转换
            String[] orderStr = order.split(",");
            int[] orderArray = new int[orderStr.length];
            for (int Orderindex = 0; Orderindex < orderStr.length; Orderindex++) {
                orderArray[Orderindex] = Integer.parseInt(orderStr[Orderindex]);
            }
            if (
                    collocationGoodsBaseList.size() != EffectiveAreaArray.length ||
                            collocationGoodsBaseList.size() != CentralPointArray.length || collocationGoodsBaseList.size() != orderArray.length
            ) {
                log.error("handleComposeGoodsImage data Num fail. collocationGoodsBaseList size={},EffectiveAreaArray size ={},aidaCollocateAmendmentRuleMap size ={},CentralPointArray size ={},orderArray size={}",
                        collocationGoodsBaseList.size(), EffectiveAreaArray.length, aidaCollocateAmendmentRuleMap.size(), CentralPointArray.length, orderArray.length);
                //素材数量不足退出
                return null;
            }
            //时间统计
            StopWatch clock = new StopWatch();
            clock.start(" <=== 图片【" + keyName + "】初始化png透明背景时间 ");
            //初始化png透明背景
            BufferedImage bufferedImage = createPng(imgWidth.intValue(), imgHigh.intValue());
            clock.stop();
            //遍历组合顺序下标
            for (int orderIndex : orderArray) {
                int position = orderIndex - 1;
                //获取修正规则
                List<AmendmentRule> amendmentRulesList = aidaCollocateAmendmentRuleMap.get(position);
                position = position - frontGoodsNum;
                clock.start(" <=== 图片【" + keyName + "】商品下标【" + position + "】时间 ");
                //得到商品
                DubboWeimobCollocationGoodsBaseDTO collocationGoodsBase = collocationGoodsBaseList.get(position);
                //得到商品理应的有限
                Long meffectiveArea = EffectiveAreaArray[position];
                //得到中心点坐标
                int[] point = CentralPointArray[position];
                //旋转角度
                int angle = 0;
                //计算
                int[] calculate = AmendmentRuleUtil.calculate(amendmentRulesList, meffectiveArea.intValue(),
                        angle,
                        collocationGoodsBase.getWidth(), collocationGoodsBase.getHigh(),
                        point[0], point[1]);
                //计算出缩放比
                double scale = Math.sqrt(((double) calculate[0]) / collocationGoodsBase.getEffectiveArea());
                //角度
                angle = calculate[1];
    
    
                //宽高计算、压缩
                int width = (int) (collocationGoodsBase.getWidth() * scale);
                int high = (int) (collocationGoodsBase.getHigh() * scale);
                //旋转后
                int[] calcRotatedSize = calcRotatedSize(width, high, angle);
                width = calcRotatedSize[0];
                high = calcRotatedSize[1];
                //计算中心点
                int centerPointX = (width / 2);
                int centerPointY = (high / 2);
                //计算左上角坐标
                int x = calculate[2] - centerPointX;
                int y = calculate[3] - centerPointY;
                //图片Url处理
    
                String imgUrl = collocationGoodsBase.getCuttingDiagramImageIntranetUrl();
                imgUrl = OSSUrlUtil.rotate(imgUrl, angle);
                imgUrl = OSSUrlUtil.specifyWidthAndHeight(imgUrl, width, high);
                try {
                    stickImg(bufferedImage, ImgUtil.read(new URL(imgUrl)), x, y);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                clock.stop();
            }
            clock.start(" <=== 图片【" + keyName + "】bufferedImage转InputStream时间 ");
            //上传
            InputStream inputStream = BufferedImageCollocateUtil.bufferedImageInputStreamBGRA(bufferedImage);
            clock.stop();
            //上传云存储
            clock.start(" <=== 图片【" + keyName + "】上传云存储时间 ");
            oSSUtil.internalPutFileByInputStream(keyName, inputStream);
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            clock.stop();
            log.debug("图片【" + keyName + "】耗时统计:{}", clock.prettyPrint());
            //获取云存储地址
            return oSSUtil.getURLOfTheFileInternalCheck(keyName);
    
        }
    
    
        /**
         * 贴按顺序贴图返回整图
         *
         * @param stickImgOrderCmd 配饰参数
         */
        public static BufferedImage stickImgOrderToBufferedImage(StickImgOrderCmd stickImgOrderCmd) {
            if (ObjectUtils.isEmpty(stickImgOrderCmd)) {
                return null;
            }
            Long width = stickImgOrderCmd.getWidth();
            Long heigh = stickImgOrderCmd.getHeigh();
            if (ObjectUtils.isEmpty(width) || ObjectUtils.isEmpty(heigh)) {
                return null;
            }
            //贴图顺序
            Byte[] layerOrderArray = {0, 1, 2};
            if (StringUtils.isNotBlank(stickImgOrderCmd.getLayerOrder())) {
                String[] layerOrderSplit = stickImgOrderCmd.getLayerOrder().split(",");
                layerOrderArray = new Byte[layerOrderSplit.length];
                for (int layerOrderIndex = 0; layerOrderIndex < layerOrderSplit.length; layerOrderIndex++) {
                    layerOrderArray[layerOrderIndex] = Byte.parseByte(layerOrderSplit[layerOrderIndex]);
                }
            }
            //图片的图片地址
            Map<Byte, String> imageUrlMap = new HashMap<>();
            imageUrlMap.put(AidaCompositeConstant.AIDACOMPOSE_LAYERORDER_0, stickImgOrderCmd.getBackGroundUrl());
            imageUrlMap.put(AidaCompositeConstant.AIDACOMPOSE_LAYERORDER_1, stickImgOrderCmd.getGoodsImageMasterUrl());
            imageUrlMap.put(AidaCompositeConstant.AIDACOMPOSE_LAYERORDER_2, stickImgOrderCmd.getGoodsImageSlaveUrl());
            //合成图片
            BufferedImage bufferedImage = ComposeImageUtil.createPng(width.intValue(), heigh.intValue());
            for (Byte layer : layerOrderArray) {
                String imageUrl = imageUrlMap.get(layer);
                if (StringUtils.isNotBlank(imageUrl)) {
                    try {
                        stickImg(bufferedImage, ImgUtil.read(new URL(imageUrl)), 0, 0);
                    } catch (Exception e) {
                    }
                }
            }
            return bufferedImage;
        }
    
    
        /**
         * 贴按顺序贴图返回组装对象
         *
         * @param stickImgOrderCmd 配饰参数
         */
        public static List<ComposeImageCoordinateDTO> stickImgOrderToJson(StickImgOrderCmd stickImgOrderCmd) {
            if (ObjectUtils.isEmpty(stickImgOrderCmd)) {
                return null;
            }
            Long width = stickImgOrderCmd.getWidth();
            Long heigh = stickImgOrderCmd.getHeigh();
            //贴图顺序
            Byte[] layerOrderArray = {0, 1, 2};
            if (StringUtils.isNotBlank(stickImgOrderCmd.getLayerOrder())) {
                String[] layerOrderSplit = stickImgOrderCmd.getLayerOrder().split(",");
                layerOrderArray = new Byte[layerOrderSplit.length];
                for (int layerOrderIndex = 0; layerOrderIndex < layerOrderSplit.length; layerOrderIndex++) {
                    layerOrderArray[layerOrderIndex] = Byte.parseByte(layerOrderSplit[layerOrderIndex]);
                }
            }
            //图片的图片地址
            Map<Byte, String> imageUrlMap = new HashMap<>();
            imageUrlMap.put(AidaCompositeConstant.AIDACOMPOSE_LAYERORDER_0, stickImgOrderCmd.getBackGroundUrl());
            imageUrlMap.put(AidaCompositeConstant.AIDACOMPOSE_LAYERORDER_1, stickImgOrderCmd.getGoodsImageMasterUrl());
            imageUrlMap.put(AidaCompositeConstant.AIDACOMPOSE_LAYERORDER_2, stickImgOrderCmd.getGoodsImageSlaveUrl());
            //合成图片
            //中心点坐标x
            Long centerPointX = width / 2;
            //中心点坐标y
            Long centerPointY = heigh / 2;
            //数据组装
            List<ComposeImageCoordinateDTO> coordinateList = new ArrayList<>();
            for (int layerOrder = 0; layerOrder < layerOrderArray.length; layerOrder++) {
                Byte layer = layerOrderArray[layerOrder];
                String imageUrl = imageUrlMap.get(layer);
                if (StringUtils.isNotBlank(imageUrl)) {
                    ComposeImageCoordinateDTO composeImageCoordinate = new ComposeImageCoordinateDTO();
                    composeImageCoordinate.setWidth(width);
                    composeImageCoordinate.setHeigh(heigh);
                    composeImageCoordinate.setCenterPointX(centerPointX.intValue());
                    composeImageCoordinate.setCenterPointY(centerPointY.intValue());
                    composeImageCoordinate.setImageUrl(OSSUrlUtil.specifyWidthAndHeight(imageUrl, width.intValue(), heigh.intValue()));
                    composeImageCoordinate.setLayer(layerOrder);
                    coordinateList.add(composeImageCoordinate);
                }
            }
            return coordinateList;
        }
    
    
        /**
         * 创建透明图
         *
         * @param width
         * @param height
         * @return
         */
        public static BufferedImage createPng(int width, int height) {
            // 创建BufferedImage对象
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            // 获取Graphics2D
            Graphics2D g2d = image.createGraphics();
            // ----------  背景透明开始  -----------------
            image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
            g2d.dispose();
            // ----------  背景透明代码结束  -----------------
            return image;
        }
    
        /**
         * 计算转换后目标矩形的宽高
         *
         * @param width
         * @param height
         * @param angle  角度
         * @return 目标矩形
         */
        private static int[] calcRotatedSize(int width, int height, int angle) {
            if (angle == 0 || angle % 360 == 0) {
                return new int[]{width, height};
            }
            double cos = Math.abs(Math.cos(Math.toRadians(angle)));
            double sin = Math.abs(Math.sin(Math.toRadians(angle)));
            int des_width = (int) (width * cos) + (int) (height * sin);
            int des_height = (int) (height * cos) + (int) (width * sin);
            return new int[]{des_width, des_height};
        }
    
    
        /**
         * 贴图片
         *
         * @param srcImage 底图
         * @param pressImg 贴图
         * @param x        坐标x(必填)
         * @param y        坐标y(必填)
         */
        public static void stickImg(BufferedImage srcImage, BufferedImage pressImg, int x, int y) {
            if (ObjectUtils.isEmpty(srcImage) || ObjectUtils.isEmpty(pressImg)) {
                return;
            }
            //将图片放到指定位置
            Graphics2D graphics2D = srcImage.createGraphics();
            graphics2D.drawImage(pressImg, x, y, null);
            graphics2D.dispose();
        }
    
        /**
         * 贴文字
         *
         * @param srcImage 底图
         * @param color    颜色
         * @param font     字体
         * @param text     文本
         * @param x        坐标x(必填)
         * @param y        坐标y(必填)
         */
        public static void stickText(BufferedImage srcImage, Color color, Font font, String text, int x, int y) {
            if (ObjectUtils.isEmpty(srcImage) || ObjectUtils.isEmpty(font) || StringUtils.isBlank(text)) {
                return;
            }
            // 创建画笔
            Graphics2D graphics2D = srcImage.createGraphics();
            // 设置画笔颜色为白色
            // pen.setColor(Color.WHITE);
            graphics2D.setColor(color);
            // 设置画笔字体样式为微软雅黑,斜体,文字大小为20px
            graphics2D.setFont(font);
            // 写上水印文字和坐标
            graphics2D.drawString(text, x, y);
            graphics2D.dispose();
    
        }
    
    }
    

      

  • 相关阅读:
    jquery使用
    网站重构?
    WEB应用从服务器主动推送Data到客户端有那些方式?
    异步加载和延迟加载?
    平时如何管理你的项目?
    对前端界面工程师这个职位是怎么样理解的?它的前景会怎么样?
    约定优于配置(convention over configuration)
    JavaEE的13种核心技术
    The Spring Framework ConfigurableListableBeanFactory.java
    mySQL的boolean类型为tinyint(1)
  • 原文地址:https://www.cnblogs.com/zxf330301/p/16409482.html
Copyright © 2020-2023  润新知