HarmonyOS 鸿蒙Next 多张string图片合并成一张

发布于 1周前 作者 caililin 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 多张string图片合并成一张

                                        

3 回复

可以试下这个demo:


import { image } from '[@kit](/user/kit).ImageKit';
import { ArrayList, util } from '[@kit](/user/kit).ArkTS';

[@Entry](/user/Entry)
[@Component](/user/Component)
struct Index {
 [@State](/user/State) message: string = 'Hello World';
 private signSettings: RenderingContextSettings = new RenderingContextSettings(true)
 private signContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.signSettings)
 [@State](/user/State) transcriptionMark: number = 0
 private copySettings: RenderingContextSettings = new RenderingContextSettings(true)
 private copyContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.copySettings)
 [@State](/user/State) copyImage: string[] = []
 private timerId: number = -1
 private lastX: number = 0;
 private lastY: number = 0;
 private isDown: Boolean = false;
 [@State](/user/State) copyContent: string = '本人已阅读保险条款'
 [@State](/user/State) imagePixelMap: image.PixelMap | undefined = undefined
 [@State](/user/State) orgImage: image.PixelMap | undefined = undefined
 [@State](/user/State) list: ArrayList<image.ImageSource> = new ArrayList<image.ImageSource>()

 aboutToAppear(): void {
   this.list.clear()
 }

 draw(context: CanvasRenderingContext2D, startX: number, startY: number, endX: number, endY: number) {
   // 起点
   context.moveTo(startX, startY);
   // 终点
   context.lineTo(endX, endY);
   // 调用 stroke,即可看到绘制的线条
   context.stroke();
 }

 build() {
   Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
     Column({ space: '10vp' }) {
       Row({ space: '9vp' }) {
         Column() {
           Grid() {
             ForEach(this.copyImage, (image: string) => {
               GridItem() {
                 Image(image)
                   .width('100%')
                   .height('100%')
               }
             }, (day: string) => day)
           }
           .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr')
           .rowsTemplate('1fr 1fr 1fr 1fr 1fr')
           .columnsGap(8)
           .rowsGap(8)
           .width('98%')
           .height('98%')
         }
         .layoutWeight(3)
         .backgroundColor('#EEEEEE')
         .borderRadius('10vp')
         .height('100%')

         Stack() {
           Canvas(this.signContext)
             .width('100%')
             .height('100%')
             .onReady(() => {
               this.signContext.beginPath()
               this.signContext.moveTo(0, 0)
               this.signContext.lineTo(this.signContext.width, this.signContext.height)
               this.signContext.moveTo(this.signContext.width, 0)
               this.signContext.lineTo(0, this.signContext.height)
               this.signContext.moveTo(this.signContext.width / 2, 0)
               this.signContext.lineTo(this.signContext.width / 2, this.signContext.height)
               this.signContext.moveTo(0, this.signContext.height / 2)
               this.signContext.lineTo(this.signContext.width, this.signContext.height / 2)
               this.signContext.setLineDash([10, 10])
               this.signContext.stroke()
             })
           Text(this.copyContent.substring(this.transcriptionMark, this.transcriptionMark + 1))
             .width('100%')
             .height('100%')
             .fontSize('130fp')
             .fontColor('#F0F0F0')
             .fontWeight(FontWeight.Bold)
             .textAlign(TextAlign.Center)

           Canvas(this.copyContext)
             .width('100%')
             .height('100%')
             .onReady(() => {
               this.copyContext.strokeStyle = "#ff000000"
               this.copyContext.lineWidth = 5
             })
             .gesture(PanGesture().onActionStart(event => {
               clearTimeout(this.timerId);
               this.isDown = true;
               // 按下时的点作为起点
               this.lastX = event.fingerList[0].localX;
               this.lastY = event.fingerList[0].localY
               // 创建一个新的路径
               this.copyContext.beginPath();
               // console.log("onActionStart() ")
             })
               .onActionUpdate(event => {
                 // console.log("onActionUpdate() ")
                 clearTimeout(this.timerId);
                 // 没有按下就不管
                 if (!this.isDown) {
                   return;
                 }
                 const offsetX = event.fingerList[0].localX
                 const offsetY = event.fingerList[0].localY
                 // 调用绘制方法
                 this.draw(this.copyContext, this.lastX, this.lastY, offsetX, offsetY);
                 // 把当前移动时的坐标作为下一次的绘制路径的起点
                 this.lastX = offsetX;
                 this.lastY = offsetY;
               })
               .onActionEnd(event => {
                 // console.log("onActionEnd() ")
                 this.isDown = false;
                 // 关闭路径
                 this.copyContext.closePath();
                 this.timerId = setInterval(() => {
                   clearTimeout(this.timerId);
                   let image = this.signContext.getImageData(0, 0, this.copyContext.width, this.copyContext.height)
                   let url = this.copyContext.toDataURL("image/png", 0.5)
                   this.copyImage[this.transcriptionMark] = url
                   this.copyContext.clearRect(0, 0, this.copyContext.width, this.copyContext.height)
                   this.transcriptionMark++
                 }, 2000)
               }), GestureMask.Normal)

         }
         .layoutWeight(2)
         .borderRadius('10vp')
         .borderColor('#CECECE')
         .height('100%')
         .borderWidth('3vp')
         .id('ban')
       }
       .height('58%')

       Row() {
         Row({ space: '10vp' }) {
           Button('完成')
             .width('80vp')
             .height('35vp')
             .fontSize('14fp')
             .backgroundColor('#fffe0403')
             .onClick(async () => {
               this.imagePixelMap = await this.combinePic(this.copyImage)
             })
         }
         .alignSelf(ItemAlign.End)
         .margin({ right: '20vp', bottom: '20vp' })
       }
       .width('100%')
       .justifyContent(FlexAlign.End)

     }
     .height('50%')

     Image(this.imagePixelMap)
       .width(200)
       .height(200)
       .backgroundColor(Color.Yellow)
       .objectFit(ImageFit.Contain)

     Image(this.orgImage)
       .enableAnalyzer(true)
       .width(200)
       .height(200)
       .border({ width: 1 })
   }
   .height('100%')
   .width('100%')
 }

 async combinePic(pics: string[]) {
   if (pics.length < 2) {
     let helper = new util.Base64Helper();
     let buffer: ArrayBuffer = helper.decodeSync(pics[0].substring(22), util.Type.MIME).buffer as ArrayBuffer;
     let imageSource = image.createImageSource(buffer);
     const imageInfo = await imageSource.getImageInfo();
     let opts: image.DecodingOptions = {
       editable: true,
       desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
       desiredSize: { width: imageInfo.size.width, height: imageInfo.size.height }
     };
     let pixelMap = await imageSource.createPixelMap(opts);
     return pixelMap;
   }
   const tempPath = pics[0];
   const imageSource = image.createImageSource(tempPath);
   const imageInfo = await imageSource.getImageInfo();
   const singleWidth = imageInfo.size.width;
   const singleHeight = imageInfo.size.height;
   const combineOpts: image.InitializationOptions = {
     alphaType: 0,
     editable: true,
     pixelFormat: image.PixelMapFormat.BGRA_8888,
     size: { width: singleWidth * pics.length, height: singleHeight }
   }
   const singleOpts: image.DecodingOptions = {
     editable: true,
     desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
     desiredSize: { width: singleWidth, height: singleHeight }
   };
   const combineColor = new ArrayBuffer(combineOpts.size.width * combineOpts.size.height * 4);
   let singleColor = new ArrayBuffer(singleOpts.desiredSize!.width * singleOpts.desiredSize!.height * 4);
   const newPixelMap = await image.createPixelMap(combineColor, combineOpts);
   for (let i = 0; i < pics.length; i++) {
     let singlePath = pics[i];
     let imageSource = image.createImageSource(singlePath);
     const singlePixelMap = await imageSource.createPixelMap(singleOpts);
     await singlePixelMap.readPixelsToBuffer(singleColor);

     let area: image.PositionArea = {
       pixels: singleColor,
       offset: 0,
       stride: singleWidth * 4,
       region: {
         size: { height: singleHeight, width: singleWidth },
         x: singleWidth * i,
         y: 0
       }
     }
     await newPixelMap.writePixels(area);
   }
   let combinePixelMap = newPixelMap;
   return combinePixelMap
 }
}

更多关于HarmonyOS 鸿蒙Next 多张string图片合并成一张的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next系统中,将多张string图片(假设这里指的是包含文本信息的图片,即图片格式的字符串内容,而非纯文本字符串)合并成一张图片,通常涉及图像处理技术。以下是一个简要的技术实现思路:

  1. 加载图片:首先,使用系统提供的图像加载库(如BitmapFactory)加载所有待合并的string图片。

  2. 创建画布:根据合并后图片的预期尺寸,创建一个Canvas对象。此画布将作为合并后图片的容器。

  3. 绘制图片:利用Canvas的drawBitmap方法,将每张图片按指定位置和大小绘制到画布上。注意调整图片的排列方式(如水平或垂直排列)。

  4. 保存结果:使用Bitmap类的compress方法,将合并后的画布内容保存为图片文件。

  5. 优化与调整:根据需要,对图片进行裁剪、缩放或添加边框等优化处理。

请注意,上述过程需确保所有图片已正确加载,且Canvas的尺寸足够容纳所有图片。此外,还需处理可能出现的内存溢出问题,特别是在处理大图片时。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部