精华内容
下载资源
问答
  • 主要介绍了微信小程序实现的canvas合成图片功能,结合实例形式分析了微信小程序canvas合成图片相关组件使用、操作步骤与注意事项,需要的朋友可以参考下
  • php 合成图片 微信公众号合成海报

    千次阅读 2018-07-13 14:46:22
    php合成图片<?php header("content-type:image/png"); date_default_timezone_set('Asia/Shanghai'); $text1="第10000名";//此处是你要往图片上加的字 //创建画布 默认为黑色 宽高为px $...

    php合成图片

    <?php
    header("content-type:image/png");
    date_default_timezone_set('Asia/Shanghai');
    $text1="第10000名";//此处是你要往图片上加的字
    //创建画布   默认为黑色 宽高为px
    $im = imagecreatetruecolor(750, 1334);
    //选择一张图片  注意:此图片必须是绝对路径    不能是相对路径    因为是直接访问到本地或者是服务器上的文件
    $bg = imagecreatefrompng('beijing.png');
    //图2
    $hua = imagecreatefrompng('hua.png');
    
    /**********此处为我要缩放的图片************/
    $src_img = "fang.jpg";//目标图片
    $dst_w = 380;//你要缩放之后的图的宽
    $dst_h = 528;//你要缩放之后的图的高
    list($src_w,$src_h)=getimagesize($src_img);//获取你原图的宽高
    $dst_scale = $dst_h/$dst_w; //目标图像长宽比
    $src_scale = $src_h/$src_w; // 原图长宽比
    if ($src_scale>=$dst_scale){  // 过高
        $w = intval($src_w);
        $h = intval($dst_scale*$w);
     
        $x = 0;
        $y = ($src_h - $h)/3;
    } else { // 过宽
        $h = intval($src_h);
        $w = intval($h/$dst_scale);
     
        $x = ($src_w - $w)/2;
        $y = 0;
    }
    
    $source=imagecreatefromjpeg($src_img);
    $croped=imagecreatetruecolor($w, $h);
    imagecopy($croped, $source, 0, 0, $x, $y, $src_w, $src_h);
    
    
    $scale = $dst_w / $w;
    $target = imagecreatetruecolor($dst_w, $dst_h);
    $final_w = intval($w * $scale);
    $final_h = intval($h * $scale);
    imagecopyresampled($target, $croped, 0, 0, 0, 0, $final_w,$final_h, $w, $h);//为了不让图片模糊做平滑处理
    /******************/
    
    
    imagecopy($im,$bg,0,0,0,0,750,1334);//背景放入画布中  具体参数上网搜  因为我上边要用到png的图像 imagecopy这个函数不会将png图像的隐藏部分显示出来  imagecopymerge这个函数png会变不透明
    imagecopy($im,$target,215,425,0,0,326,528);//缩放过后的图放在背景上
    imagecopy($im,$hua,138,822,0,0,468,406);//图2最后放
    
    imagedestroy($bg);
    $black = imagecolorallocate($im, 255, 255, 255);//字体颜色rgb
    $font = 'fanzhengsong.ttf';//要引入的字体文件  没有的话字体不会显示   也是绝对路径
    imagettftext($im, 22, 3, 310, 335, $black, $font, $text1);//字体的大小   所放置的位置
    imagejpeg($im);
    imagedestroy($im);
    //最后创建图像输出就ok
    
    ?>
    imagecreatefromjpeg函数  创建jpg图片
    imagecreatefrompng函数   创建png图片

    前台显示:

    如果需要前台显示这个图像

    <img src="....index.php">

    直接访问到你的php地址就可以

    唯一的坑也就是个访问路径的问题  必须是绝对路径

    这个就可以实现微信生成海报放头像和名称这样类似的功能了

    哪里有问题还请大家指出   及时更正

    展开全文
  • 这个需求是邀请好友功能,可以下载当前的海报图,分享给好友,好友通过扫描二维码跳转至小程序。 如果二维码是不变的,那就可以直接下载,不用做任何处理,例如: wx.saveImageToPhotosAlbum({ filePath: /pages/...

    这个需求是邀请好友功能,可以下载当前的海报图,分享给好友,好友通过扫描二维码跳转至小程序。
    如果整张图是不变的,就在本地项目中,那就可以直接下载,不用做任何处理,例如:

        wx.saveImageToPhotosAlbum({
          filePath: /pages/imgs/qrcode_bg.png,//这里是要下载图片的地址
          success(res) {
            console.log(res)
          }
        })
    

    但需求是邀请好友,肯定是根据当前登录者的信息去生成二维码,不然邀请到的好友怎么绑定到该用户下,所以会将二维码嵌入背景海报中,合成一张图后,生成一个临时地址,再去下载图片,代码如下:

    html部分:

    <view class="borrow-poster-page">
      <view class="image-box">
        <canvas type="2d" id="myCanvas" style="width:100%;height:1060rpx;"></canvas>
        <view class="footButton">
          <button style="width:160px;height:40px;" class="button-share" open-type="share">分享微信好友</button>
          <button style="width:160px;height:40px;" class="button-share" bindtap="saveImg">保存图片</button>
        </view>
      </view>
    </view>
    

    js部分:

    //生成二维码的js库,下载地址:( https://pan.baidu.com/s/1iEHNl-_F8kGwRDV-enMz5Q 密码: c4hm)
    import Qr from "../../../utils/wxqrcode.js"
    Page({
      data: {
        img: '' // 合成后图片的临时路径
      },
      getQRcode() {
        let codeUrl = Qr.createQrCodeImg('https://www.baidu.com/')
        this.toQrcode(codeUrl)
      },
      toQrcode(codeUrl) {
        var self = this;
        var imgsrcArray = ['/pages/component/photo/borrow_qrcode_bg.png', codeUrl]; //第一个路径为海报图的本地路径,codeUrl为生成的二维码路径
        wx.createSelectorQuery()
          .select('#myCanvas')
          .fields({
            node: true,
            size: true,
          })
          .exec(res => {
            const canvas = res[0].node
            var ctx = canvas.getContext('2d');
            canvas.width = 750;
            canvas.height = 1100;
            var imglen = imgsrcArray.length;
            var drawimg = (function f(n) {
              if (n < imglen) {
                var img = canvas.createImage()
                img.crossOrigin = 'Anonymous'; //解决跨域问题
                img.onload = function () {
                  ctx.save();
                  if (n == 0) {
                    ctx.drawImage(img, 0, 0, 750, 1210);
                  } else {
                    ctx.drawImage(img, 220, 500, 300, 300);
                  }
                  f(n + 1);
                };
                img.src = imgsrcArray[n];
              } else {
                **//以下代码是在页面添加文字,修改文字样式,根据业务删减**
                // let userData = wx.getStorageSync('userData') || {};
                // let text = userData.companyName || 'wwwwwwwwwwww';
                // let text2 = '';
                // const MAXLEN = 16;
                // if (text.length > MAXLEN) {
                //   text2 = text.slice(MAXLEN);
                //   text = text.substr(0, MAXLEN);
                // }
                // ctx.font = '32px bold 黑体';
                // ctx.fillStyle = '#1B44D5';
                // ctx.textAlign = 'center';
                // ctx.textBaseline = 'middle';
                // ctx.fillText(text, 375, 180);
                // text2 && ctx.fillText(text2, 375, 220);
    
             **//方法一:这种打印出的img是一个base64格式,直接下载是不行的**
                // let downloadUrl = canvas.toDataURL('image/jpeg');
                // self.setData({
                //   img: downloadUrl
                // })
                
              **//方法二:根据此方法获取合成后图片的临时路径**
                wx.canvasToTempFilePath({
                  canvasId: 'myCanvas',
                  canvas: canvas,
                  success: function (res) {
                    let tempFilePath = res.tempFilePath;
                    self.setData({
                      img: tempFilePath
                    })
                  },
                  fail: function (res) {
                    console.log(res);
                  }
                }, this);
              }
            })(0);
          })
      },
     //下载图片
      saveImg() {
      //调用微信内部方法,下载图片
        wx.saveImageToPhotosAlbum({
          filePath: this.data.img,
          success(res) {
            console.log(res)
          }
        })
      },
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        this.getQRcode()
      },
    

    最终效果图:
    在这里插入图片描述

    展开全文
  • Android 仿微信裁剪图片

    千次阅读 2019-12-03 14:49:35
    头像无非就是方形 或者 圆形,那么就诞生了这样一个需求: 从相册中选择一张图片 中间区域是圆形 或者方形的透明...但是最后还是找到了一个可以参考模仿的例子《Android开发技巧——定制仿微信图片裁剪控件》。...

    在很多App 中,需要注册登录,那么就免不了 设置用户的头像。头像无非就是方形 或者 圆形,那么就诞生了这样一个需求:

    • 从相册中选择一张图片
    • 中间区域是圆形 或者 方形的透明裁剪框
    • 裁剪框周围是阴影
    • 图片可以移动、缩放

    网上有很多,包括Github上,但是绝大多数都是 移动裁剪框,而不是移动图片。但是最后还是找到了一个可以参考模仿的例子《Android开发技巧——定制仿微信图片裁剪控件》。这篇博客详细讲述了自定义裁剪控件的过程。以前我也是直接拿过来用的。直到某一天,产品跑过来说:“裁剪中间这个矩形框能不能改成圆的,因为我们的头像是圆的”。 于是我就开始改这个代码了,说不上优化,只是换一种思路去解决问题。

    有图有真相

              

    原作者定制内容

    • 合并裁剪框的内容到ImageView中
    • 裁剪框可以是任意长宽比的矩形
    • 裁剪框的左右外边距可以设置
    • 遮罩层颜色可以设置
    • 裁剪框下有提示文字
    • 后面产品又加入了一条裁剪图片的最大大小

    我的修改:

    • 去掉了底部提示文字(有需要可以自己加
    • 画遮罩和中间的裁剪框是 用到了 PorterDuffXfermode 方法
    • 在最后裁剪成头像时 也用到了上述方法
    • 圆形框或者矩形框 可以自由选择
    • 图片的边框可以滑倒裁剪框内部,松开手指时,会有一个回弹效果

    自定义属相修改

     <attr name="civHeight" format="integer" />
            <attr name="civWidth" format="integer" />
            <attr name="civMaskColor" format="color" />
            <attr name="civClipPadding" format="dimension" />
            <attr name="civClipCircle" format="boolean" />
    1. civHegiht 和 civWidth 是中间矩形裁剪框的比值
    2. civMaskColor  是裁剪框外围的颜色,也成遮罩颜色
    3. civPadding  是裁剪框距离我们控件的边距

     

    其他内容像 参数变量,构造方法等等,原作者都做了详细的描述,我这里就不再一一赘述了,接下来我们就重点讲讲 绘制裁剪框和遮罩 图片拖动双击缩放 以及绘制头像

    绘制裁剪框

    基本思路:在一个新建的 Canvas 上画一个 遮罩(bitmap),再用一个透明的画笔 设置 PorterDuffXfermode 为PorterDuff.Mode.CLEAR,在遮罩上画一个 矩形或圆形,这样一个中间为空的裁剪框 的遮罩就形成了。将遮罩画在所选图片上之上,别忘了 还要画一个 圆形框或者矩形框

    /**
         * 画中间的边框(方形或是圆形)
         */
        public void drawRectangleOrCircle(Canvas canvas) {
            float cx = mClipBorder.left + mClipBorder.width() / 2f;
            float cy = mClipBorder.top + mClipBorder.height() / 2f;
            float radius = mClipBorder.height() / 2f;
            RectF rectF = new RectF(mClipBorder.left, mClipBorder.top, mClipBorder.right, mClipBorder.bottom);
            Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas temp = new Canvas(bitmap);
            Paint transparentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            PorterDuffXfermode porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
            transparentPaint.setColor(Color.TRANSPARENT);
            temp.drawRect(0, 0, temp.getWidth(), temp.getHeight(), mPaint);
            transparentPaint.setXfermode(porterDuffXfermode);
            if (mDrawCircleFlag) { // 画圆
    
                temp.drawCircle(cx, cy, radius, transparentPaint);
            } else { // 画矩形(可以设置矩形的圆角)
    
                temp.drawRect(rectF, transparentPaint);
            }
            canvas.drawBitmap(bitmap, 0, 0, null);
    
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(Color.WHITE);
            mPaint.setStrokeWidth(DeviceUtil.dip2px(2));
            if (mDrawCircleFlag) {
                canvas.drawCircle(cx, cy, radius, mPaint);
            } else {
                canvas.drawRect(rectF, mPaint);
            }
        }

    底部的遮罩层是目标图像,上面的裁剪形状是源图像,PorterDuff.Mode.CLEAR 起到了清空源图像所在区域图像的作用。

    双击缩放

    说到双击,我们必要要检测到手指检测,当然啦,我们不会傻到自己写一塌逻辑去检测用户是否是双击了屏幕。这里我们用到了这个GestureDetector 来监听用户手势,如果是双击,自然会走双击的回掉方法 public boolean onDoubleTap(MotionEvent e)

    手势监听

    setScaleType(ScaleType.MATRIX);
            mGestureDetector = new GestureDetector(context,
                    new SimpleOnGestureListener() {
                        @Override
                        public boolean onDoubleTap(MotionEvent e) {
                            if (isAutoScale)
                                return true;
    
                            float x = e.getX();
                            float y = e.getY();
                            if (getScale() < mScaleMin) { //如果当前的缩放倍数小于一开始适配裁剪框缩放倍数的两倍
                                ClipImageView.this.postDelayed(new AutoScaleRunnable(mScaleMin, x, y), 16);
                            } else {
                                ClipImageView.this.postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16);
                            }
                            isAutoScale = true;
    
                            return true;
                        }
                    });

    大家有没有注意到 这个 setScaleType(ScaleType.MATRIX) ,该方法就是设置 imageview 可以根据 矩阵去缩放。

    缩放操作

     private class AutoScaleRunnable implements Runnable {
            static final float BIGGER = 1.07f;
            static final float SMALLER = 0.93f;
            private final float mTargetScale;
            private final float tmpScale;
    
            /**
             * 缩放的中心
             */
            private final float x;
            private final float y;
    
            /**
             * 传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小
             */
            AutoScaleRunnable(float targetScale, float x, float y) {
                this.mTargetScale = targetScale;
                this.x = x;
                this.y = y;
                if (getScale() < mTargetScale) {
                    tmpScale = BIGGER;
                } else {
                    tmpScale = SMALLER;
                }
    
            }
    
            @Override
            public void run() {
                // 进行缩放
                mScaleMatrix.postScale(tmpScale, tmpScale, x, y);
                checkBorder();
                setImageMatrix(mScaleMatrix);
    
                final float currentScale = getScale();
                // 如果值在合法范围内,继续缩放
                if (((tmpScale > 1f) && (currentScale < mTargetScale))
                        || ((tmpScale < 1f) && (mTargetScale < currentScale))) {
                    ClipImageView.this.postDelayed(this, 16);
                } else {
                    // 设置为目标的缩放比例
                    final float deltaScale = mTargetScale / currentScale;
                    mScaleMatrix.postScale(deltaScale, deltaScale, x, y);
                    checkBorder();
                    setImageMatrix(mScaleMatrix);
                    isAutoScale = false;
                }
    
            }
        }

    这边是根据 放大倍数(1.07) 和缩小倍数(0.93) 去缩放的,是慢慢缩放,而不是一下子缩放,这样会很突兀。注意缩放完了以后记得去检查边界,因为在缩放后,图片的边界在裁剪框里面,所以需要再去移动图片 以达到适配裁剪框的目的

    两个手指缩放

    通过多指操作 来检测缩放,我们用到了这个监听类 ScaleGestureDetector

     @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float scale = getScale();
            float scaleFactor = detector.getScaleFactor();
    
            if (getDrawable() == null)
                return true;
            //缩放的范围控制
            if ((scale < mScaleMax && scaleFactor > 1.0f)
                    || (scale > mInitScale && scaleFactor < 1.0f)) {
                //缩放阙值最小值判断
                if (scaleFactor * scale < mInitScale) {
                    scaleFactor = mInitScale / scale;
                }
                if (scaleFactor * scale > mScaleMax) {
                    scaleFactor = mScaleMax / scale;
                }
                //设置缩放比例
                mScaleMatrix.postScale(scaleFactor, scaleFactor,
                        detector.getFocusX(), detector.getFocusY());
                checkBorder();
                setImageMatrix(mScaleMatrix);
            }
            return true;
        }

    我们在控制缩放的时候,还是需要计算一下在不在我们的缩放倍数范围里。

    移动图片

    这边的设计是:

    • 如果图片的宽 或 高正好等于裁剪框的宽 或高,那么久移动不了图片
    • 放大后,移动图片,图片的边界可以移动到裁剪框里面,手指松开后,图片自动校正适配裁剪框
     @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (mGestureDetector.onTouchEvent(event))
                return true;
            mScaleGestureDetector.onTouchEvent(event);
    
            float x = 0, y = 0;
            // 拿到触摸点的个数
            final int pointerCount = event.getPointerCount();
    
            // 得到多个触摸点的x与y均值
            for (int i = 0; i < pointerCount; i++) {
                x += event.getX(i);
                y += event.getY(i);
            }
            x /= pointerCount;
            y /= pointerCount;
    
            //每当触摸点发生变化时,重置mLasX , mLastY
            if (pointerCount != lastPointerCount) {
                isCanDrag = false;
                mLastX = x;
                mLastY = y;
            }
    
            lastPointerCount = pointerCount;
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    float dx = x - mLastX;
                    float dy = y - mLastY;
    
                    if (!isCanDrag) {
                        isCanDrag = isCanDrag(dx, dy);
                    }
                    if (isCanDrag) {
                        if (getDrawable() != null) {
    
                            RectF rectF = getMatrixRectF();
                            // 如果宽度小于屏幕宽度,则禁止左右移动
                            if ((int) rectF.width() <= mClipBorder.width()) {
                                dx = 0;
                            }
    
                            // 如果高度小于屏幕高度,则禁止上下移动
                            if ((int) rectF.height() <= mClipBorder.height()) {
                                dy = 0;
                            }
    
                            // 这里主要是 当宽或者高 大于 裁剪框的高或宽时,移动到与裁剪框边重合时,可以继续移动
                            if (rectF.left > mClipBorder.left + 1 || rectF.top > mClipBorder.top + 1 || rectF.right < mClipBorder.right - 1 || rectF.bottom < mClipBorder.bottom - 1) {
                                dx = dx * 0.25f;
                                dy = dy * 0.25f;
                            }
                            mScaleMatrix.postTranslate(dx, dy);
                            setImageMatrix(mScaleMatrix);
                        }
                    }
                    mLastX = x;
                    mLastY = y;
                    break;
    
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    lastPointerCount = 0;
    
                    // 当抬起手指时,如果划过了,没有填满裁剪框,就要自动弹回
                    checkBorder();
                    setImageMatrix(mScaleMatrix);
    
                    break;
            }
    
            return true;
        }

    裁剪头像

    原著作者的思路:在矩阵中获取 图片的 缩放倍数,移动距离,进行相除和相加减,最后在原图上进行裁剪,这样有一个不好的地方,float 和 int 相互转换,会有1 px 的误差,而这个误差很有可能在裁剪时 崩溃,因为超出了图片的宽度,这是在实践中验证过了。

    作为新时代的青年,我们当然要换一种想法,那就是 PorterDuffXfermode,只不过这里的model 是PorterDuff.Mode.SRC_IN。看上去还不错哦,与开头画裁剪框和遮罩 形成了 首尾呼应。

    先在 新建的Canvas 上 画一个 透明的 Bitmap,中间画一个 填充型矩形,设置画笔 的Xfermode ,接着将变化后的bitmap 画上去,这样两个Bitmap 一合成,就在画布上形成了 周围是透明,只有中间矩形里 是图片,最后将矩形图片截图出来。

    /**
         * 截图操作
         */
        public Bitmap clip() {
            final Drawable drawable = getDrawable();
            final Bitmap originalBitmap = ((BitmapDrawable) drawable).getBitmap();
            Bitmap bottomBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
            Canvas canvas = new Canvas(bottomBitmap);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            canvas.drawRect(mClipBorder, paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(originalBitmap, mScaleMatrix, paint);
            return Bitmap.createBitmap(bottomBitmap, (int) mClipBorder.left, (int) mClipBorder.top, (int) mClipBorder.width(), (int) mClipBorder.height());
    
        }
    

    效果演示

    截图控件

     

    Android 仿微信 头像裁剪

    1. Android开发技巧——定制仿微信图片裁剪控件
    展开全文
  • 微信群头像合成

    千次阅读 2017-04-25 21:45:28
    微信头像合成,用于将n长图片拼成一张图片为了达到最好的效果,建议图片数量最好是平方数,否则为了效果最好,会舍弃一些图片最终效果Java代码import java.awt.Color; import java.awt.Graphics; import java.awt....

    微信头像合成,用于将n长图片拼成一张图片

    为了达到最好的效果,建议图片数量最好是平方数,否则为了效果最好,会舍弃一些图片

    最终效果

    这里写图片描述

    Java代码

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.geom.AffineTransform;
    import java.awt.image.AffineTransformOp;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import javax.imageio.ImageIO;
    
    //图片合成工具类,用于将n个头像合并成一个头像
    public class ImageCombine {
    
    
        public static void main(String[] args) throws IOException {
            File file = new File("C:\\Users\\Macbook\\Desktop\\img\\");//图片文件目录
            List<String> path = new LinkedList<String>();
            for(File f : file.listFiles()){ //为了效果最好,图片数量最好是平方数
                path.add(f.getAbsolutePath());
            }
            combineImages(path);
        }
        public static void combineImages(List<String> paths)
                throws IOException {
            List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();
    
            int imgNumber = paths.size(); // 头像数量,为了效果最好,图片数量最好是平方数
    
            int PicHeightAndWidth = 1600; // 画板的宽高
    
            int gap = 5;//头像之间缝隙的宽度
    
            int numPerEdge = (int)Math.sqrt(imgNumber);//每条边头像的数量
    
            int heightOrWidth = (PicHeightAndWidth - gap * (numPerEdge + 1)) / numPerEdge;// 单个头像的长和宽
    
            for (int i = 0; i < paths.size(); i++) {
                bufferedImages.add(ImageCombine.resize(paths.get(i), heightOrWidth, heightOrWidth, true));
            }
    
            BufferedImage outImage = new BufferedImage(PicHeightAndWidth, PicHeightAndWidth,
                    BufferedImage.TYPE_INT_RGB);
    
            Graphics g = outImage.getGraphics();// 生成画布
    
            Graphics2D g2d = (Graphics2D) g;
    
            g2d.setBackground(new Color(255,255,255)); // 设置背景色
    
            g2d.clearRect(0, 0, PicHeightAndWidth, PicHeightAndWidth);// 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
    
            //逐一绘制头像
            for(int i = 0; i < numPerEdge; i++){
                for(int j = 0; j < numPerEdge; j++){
                    g2d.drawImage(bufferedImages.get(i * 10 + j),gap * (j+1) + heightOrWidth * j, gap * (i+1) +heightOrWidth * i, null);
                }
            }
    
            String outPath = "C:\\Users\\Macbook\\Desktop\\combine.jpg";
    
            String format = "JPG";
    
            ImageIO.write(outImage, format, new File(outPath));
        }
    
        /**
         * 图片缩放
         * @param filePath 图片路径
         * @param height 高度
         * @param width 宽度
         * @param bb 比例不对时是否需要补白
         */
        public static BufferedImage resize(String filePath, int height, int width,
                                            boolean bb) {
            try {
                double ratio = 0; // 缩放比例
                File f = new File(filePath);
                BufferedImage bi = ImageIO.read(f);
                Image itemp = bi.getScaledInstance(width, height,
                        Image.SCALE_SMOOTH);
                // 计算比例
                if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
                    if (bi.getHeight() > bi.getWidth()) {
                        ratio = (new Integer(height)).doubleValue()
                                / bi.getHeight();
                    } else {
                        ratio = (new Integer(width)).doubleValue() / bi.getWidth();
                    }
                    AffineTransformOp op = new AffineTransformOp(
                            AffineTransform.getScaleInstance(ratio, ratio), null);
                    itemp = op.filter(bi, null);
                }
                if (bb) {
                    BufferedImage image = new BufferedImage(width, height,
                            BufferedImage.TYPE_INT_RGB);
                    Graphics2D g = image.createGraphics();
                    g.setColor(Color.white);
                    g.fillRect(0, 0, width, height);
                    if (width == itemp.getWidth(null))
                        g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
                                itemp.getWidth(null), itemp.getHeight(null),
                                Color.white, null);
                    else
                        g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
                                itemp.getWidth(null), itemp.getHeight(null),
                                Color.white, null);
                    g.dispose();
                    itemp = image;
                }
                return (BufferedImage) itemp;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    }
    展开全文
  • 我目前参与小程序的产品研发,为了方便产品的转发和推广,会对课提供生成海报转发或者分享的功能,前期海报合成这个功能是由项目组的老同事负责开发,后来小程序海报这块功能需要单独做一个功能用于专门根据不同的...
  • 最近项目需要,写了一个和微信图片编辑功能类似的图片编辑库,除去问题操作上摈弃掉不方便的手势操作外,其余微信中的核心功能全部一致,保留了微信中涂鸦、马赛克、文字等随时随着图片缩放的功能,这点是我所找的...
  • 或者微信头像下载的速度太慢了,需要十几秒钟,用户体验极差,虽然功能实现了,但是做不到用户体验优化; 之前有过类似的经历,网上找了很多都没有找到特别满意的解决方案.最终找到了一个能高效处理微信头像下载的...
  • 导语 | 2021年1月, 微信发布了微信8.0, 这次更新支持图片文字提取的功能。用户在聊天界面和朋友圈中长按图片就可以提取图片中文字,然后一键转发、复制或收藏。图片文字提取功能基于微信...
  • 所以只能通过生成图片,携带小程序二维码,保存到手机相册,让用户自己选择发到朋友圈。然后可以通过在小程序中识别二维码来进入小程序的指定页面。参考市面上支持分享的应用,基本都是这种实现方式。 准备阶段 1....
  • 微信小程序图片缩放 拖动,亲测可用(别人写的,拿来分享下)。因为小程序程序包大小有限制,把两个gif图片删除就行了,删除不影响使用
  • 微信小程序分享功能知识点

    千次阅读 2019-08-15 15:21:26
    微信小程序分享功能知识点微信小程序分享功能知识点概览小程序与普通网页开发的区别小程序运行机制启动前台/后台状态小程序销毁WXS响应事件的动机微信分享需求描述程序流程FAQs同类小程序分享功能调研&...
  • 主要介绍了小程序使用canvas自适应屏幕画海报并保存图片功能,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 仿照微信,朋友圈分享图片功能 。可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 。很不错的源码,大家有需要可以下载看看 。 微信 微信 ...
  • python调用mssql存储过程,生成图表,合成图片,定时发送到企业微信群 -----------------------实用主义的非典型IT搬运工----------------------- 之前用python写过一段脚本,实现从数据库提取数据,然后定时调用...
  • 微信小程序之保存动态图片功能

    千次阅读 2019-04-29 14:47:41
    1.调用wx.downloadFile方法下载图片到本地。 wx.downloadFile({ url: path, success: function(res) { } }) 2.调用wx.saveImageToPhotosAlbum方法,将本地图片保存到系统相册。 wx.downloadFile({ ...
  • 我们的需求是动态生成一个含有微信头像的图片作为分享图片。 我们在页面中添加cancas &lt;view style='position:absolute;left:400rpx;'&gt;&lt;canvas canvas-id='ttcanvas' style='height:240px;...
  • 9月24日,微信头像合成爆红,公司为了趁热点,也要做一个类似的功能,于是利用canvas也做了一个 ,其实很简单直接上代码
  • 微信用户头像合成新图并推送

    千次阅读 2018-01-19 13:17:31
    然后返回一张有意思的图片给客户图片的内容包含有用户头像图、用户名称、一张有意思的图片合成从一个新用户角度去看这个动作的完成,用户首先需要关注公众号,再发送数字,服务器合成并响应这一个过程比较耗费时间...
  • 微信小程序绘制海报,或者把多张图片合成一张,例子 <image style='height:{{mabgh}}px;width:{{mabgw}}px;' class="savepng" show-menu-by-longpress='true' src="{{sharepath}}"></image> <view wx...
  • egret微信小游戏项目图片管理 工具—Egret Launcher中下载 egret Texture Merger 图一 工具达到的效果— 每次看到assets文件夹下面那么多图片就头疼,通过这个管理工具对所有需要用到的图片进行归类,方便将来对...
  • 仿照微信,朋友圈分享图片功能 。可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 。很不错的源码,大家有需要可以下载看看 。 如果不知道...
  • 本文介绍使用微信小程序API+canvas来实现图片的可拖动、放大、缩小和旋转,并可对选中的图片进行不同效果的滤镜和不同形状的切图,且可对最终效果进行保存到本地。 最终效果: 实现过程 1. 文件index.wxml和...
  • 也是蛮遗憾的,一直想独立做个微信小程序或者微信小游戏,可是每次都草草收场,无意间看到朋友圈有个朋友给他的头像上加了一个牛气冲天的头像,我立马突发奇想,想着做一个给图片打水印,或者融合图片这样一个小程序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,734
精华内容 1,893
关键字:

微信合成图片功能