HarmonyOS 鸿蒙Next app图片拼接:实现两张图片拼接生成一张图片的功能,麻烦提供demo参考

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

HarmonyOS 鸿蒙Next app图片拼接:实现两张图片拼接生成一张图片的功能,麻烦提供demo参考 我们app需要实现两张图片拼接生成一张图片的功能,麻烦提供demo参考 app图片拼接

3 回复

请参考如下demo:

Index.ets

import { common } from '@kit.AbilityKit';
import { BusinessError, request } from '@kit.BasicServicesKit';
import fs from '@ohos.file.fs';
import { fileUri } from '@kit.CoreFileKit';
import { joinPicture } from '../pages/JoinPicture'
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { image } from '@kit.ImageKit';

@Component
struct Index5 {
  @State imageUri: string = '';
  @State combineImageUri: string = '';
  context = this.context as common.UIAbilityContext;
  filePath = this.context.filesDir + '/test.jpg';
  combinePath = this.context.filesDir + '/combine.jpg';
  saveButtonOptions: SaveButtonOptions = {
    icon: SaveIconStyle.FULL_FILLED,
    text: SaveDescription.SAVE_IMAGE,
    buttonType: ButtonType.Capsule
  } // 设置安全控件按钮属性

  onPageShow(): void {
    this.checkImageExist()
  }

  checkImageExist(notExistCallback?: Function) {
    fs.access(this.filePath).then((res: boolean) => {
      if (res) {
        console.info("PictureJoinTogether file exists");
        this.imageUri = fileUri.getUriFromPath(this.filePath);
      } else {
        console.info("PictureJoinTogether file not exists");
        if (notExistCallback) {
          notExistCallback()
        }
      }
    }).catch((err: BusinessError) => {
      console.info("PictureJoinTogether access failed with error message: " + err.message + ", error code: " + err.code);
    });
  }

  // 只是为了分享图片,随便找个图片下载
  downloadFile(callback: Function) {
    this.checkImageExist(() => {
      request.downloadFile(this.context, {
        url: 'https://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F2019-11-22%2F5dd7afa7df0fc.jpg&thumburl=https%3A%2F%2Fimg1.baidu.com%2Fit%2Fu%3D2205810988%2C4283060315%26fm%3D253%26fmt%3Dauto%26app%3D138%26f%3DJPEG%3Fw%3D800%26h%3D500',
        filePath: this.filePath,
        background: true
      }).then((downloadTask: request.DownloadTask) => {
        downloadTask.on('progress', (receivedSize: number, totalSize: number) => {
          console.info("PictureJoinTogether download receivedSize:" + receivedSize + " totalSize:" + totalSize);
        });
        downloadTask.on('complete', () => {
          console.info('PictureJoinTogether download complete');
          callback()
        })
      }).catch((err: BusinessError) => {
        console.error(`PictureJoinTogether Invoke downloadTask failed, code is ${err.code}, message is ${err.message}`);
      });
    })
  }

  build() {
    Column({space: 10}) {
      Button('下载图片')
        .onClick(() => {
          if (this.imageUri !== '') {
            return;
          }
          this.downloadFile(() => {
            this.imageUri = fileUri.getUriFromPath(this.filePath);
          })
        }
      Image(this.imageUri)
        .width(200)
        .height(200)
        .backgroundColor(Color.Gray)
      Button('合并图片并保存到应用内')
        .onClick(() => {
          joinPicture.join([this.filePath, this.filePath], this.combinePath, () => {
            this.combineImageUri = fileUri.getUriFromPath(this.combinePath);
          })
        })
      Image(this.combineImageUri)
        .width(400)
        .height(200)
        .backgroundColor(Color.Gray)
      // 通过安全控件保存应用图片到图库
      SaveButton(this.saveButtonOptions)
        .onClick(async (event, result: SaveButtonOnClickResult) => {
          if (result === SaveButtonOnClickResult.SUCCESS) {
            try {
              const context = getContext();
              const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
              const uri = await phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
              console.info('createAsset successfully, uri: ' + uri);
              const file = await fs.open(uri, fs.OpenMode.READ_WRITE);
              const imageSource = image.createImageSource(this.combinePath);
              const imageInfo = await imageSource.getImageInfo();
              const opts: image.DecodingOptions = {
                editable: true,
                desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
                desiredSize: { width: imageInfo.size.width, height: imageInfo.size.height }
              };
              const pixelMap = await imageSource.createPixelMap(opts);
              const imagePackerApi: image.ImagePacker = image.createImagePacker();
              let packOpts: image.PackingOption = { format: "image/jpeg", quality: 100 };
              const packingArrayBuffer = await imagePackerApi.packing(pixelMap, packOpts);
              console.info('packing succeeded.');
              fs.writeSync(file.fd, packingArrayBuffer, { offset: 0 })
              fs.closeSync(file.fd)
            } catch (err) {
              console.error('createAsset failed, message = ', err);
            }
          } else {
            console.error('SaveButtonOnClickResult createAsset failed');
          }
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

JoinPicture.ets

import { image } from '@kit.ImageKit';
import fs from '@ohos.file.fs';

class JoinPicture {
  /**
   * RGBA与BGRA编码互换,前后统一编码后,就不需要转换了
   * @param data
   * @returns
   */
  rgba2BGRA(data: ArrayBuffer): ArrayBuffer {
    let length: number = data.byteLength;
    let tempBuffer: ArrayBuffer = new ArrayBuffer(length);
    let rgbaData = new DataView(data);
    let bgraData = new DataView(tempBuffer);
    for (let i = 0; i < length; i += 4) {
      bgraData.setUint8(i, rgbaData.getUint8(i + 2));
      bgraData.setUint8(i + 1, rgbaData.getUint8(i + 1));
      bgraData.setUint8(i + 2, rgbaData.getUint8(i));
      bgraData.setUint8(i + 3, rgbaData.getUint8(i + 3));
    }
    return bgraData.buffer
  }

  // 这里只考虑横向排列拼接,且每张小图的高度一致
  async join(picturePaths: Array<string>, joinPath: string, callback: Function) {
    try {
      if (picturePaths.length < 2) {
        console.info('PictureJoinTogether 需要拼接的图片数量不足')
        return;
      }
      const tempPath = picturePaths[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 * picturePaths.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 x = 0; x < picturePaths.length; x++) {
        //读取小图
        //图片应用沙箱路径
        let singlePath = picturePaths[x];
        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 * x,
            y: 0
          }
        }
        await newPixelMap.writePixels(area);
      }
      let combinePixelMap = newPixelMap;
      //保存大图
      const saveResult = await this.save(combinePixelMap, joinPath)
      saveResult && callback();
    } catch (err) {
      console.error('PictureJoinTogether join error: ' + JSON.stringify(err))
    }
  }

  async save(pixelMap: image.PixelMap | undefined, path: string) {
    if (pixelMap === undefined) {
      return false;
    }
    const imagePackerApi: image.ImagePacker = image.createImagePacker();
    let packOpts: image.PackingOption = { format: "image/jpeg", quality: 100 };
    const packingArrayBuffer = await imagePackerApi.packing(pixelMap, packOpts);
    console.info('packing succeeded.');
    let file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    fs.writeSync(file.fd, packingArrayBuffer, { offset: 0 })
    fs.closeSync(file.fd)
    return true
  }
}

export const joinPicture = new JoinPicture()

更多关于HarmonyOS 鸿蒙Next app图片拼接:实现两张图片拼接生成一张图片的功能,麻烦提供demo参考的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


使用canvas可以实现,

图片

在HarmonyOS中实现两张图片拼接生成一张图片的功能,可以通过Canvas类来完成。以下是一个简单的示例代码,展示如何实现这一功能:

// 假设你已经有了两张Bitmap对象,bitmap1和bitmap2
Bitmap resultBitmap = Bitmap.createBitmap(
    bitmap1.getWidth() + bitmap2.getWidth(), // 新Bitmap的宽度
    Math.max(bitmap1.getHeight(), bitmap2.getHeight()), // 新Bitmap的高度,取两张图片中的最大值
    Bitmap.Config.ARGB_8888 // 配置
);

Canvas canvas = new Canvas(resultBitmap);
canvas.drawBitmap(bitmap1, 0, 0, null); // 将第一张图片绘制到左上角
canvas.drawBitmap(bitmap2, bitmap1.getWidth(), 0, null); // 将第二张图片绘制到第一张图片的右侧

// 此时resultBitmap就是拼接后的图片
// 你可以将其保存到文件中,或者用于其他显示需求

注意,上述代码假设你已经有了bitmap1bitmap2这两个Bitmap对象。在实际应用中,你可能需要从资源文件、网络或其他来源加载这些图片。

如果你需要在UI中显示拼接后的图片,可以使用ImageView等组件来展示resultBitmap

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

回到顶部