HarmonyOS 鸿蒙Next:【PixelMap】crop后,显示到Image控件中仍然未被截取

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

HarmonyOS 鸿蒙Next:【PixelMap】crop后,显示到Image控件中仍然未被截取 按照以下代码,点击添加照片按钮,期望显示一张被截取了一半的图片,但不管origin还是cropped,显示在Image中的都是完整而未被截取的图片。(后来试着多点几次添加同一张照片,有点时候能小概率(低于50%)显示两个Image均为截取后的图片)

<div class="highlight-div">
<div class="highlight-div-header">
<div class="handle-button theme-button">
<div class="handle-hover-tips">深色代码主题</div>
</div>
<div class="handle-button copy-button">
<div class="handle-hover-tips">复制</div>
</div>
</div>
<pre><code class="language-javascript hljs" data-highlighted="yes">
<span class="hljs-keyword">import</span> { photoAccessHelper } <span class="hljs-keyword">from</span> <span class="hljs-string">'@kit.MediaLibraryKit'</span>;
<span class="hljs-keyword">import</span> { fileIo, picker } <span class="hljs-keyword">from</span> <span class="hljs-string">'@kit.CoreFileKit'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">BusinessError</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@kit.BasicServicesKit'</span>;
<span class="hljs-keyword">import</span> { image } <span class="hljs-keyword">from</span> <span class="hljs-string">'@kit.ImageKit'</span>;

@<span class="hljs-title class_">Entry</span>
@<span class="hljs-title class_">Component</span>
struct <span class="hljs-title class_">CropPage</span> {
  @<span class="hljs-title class_">State</span> <span class="hljs-attr">origin</span>: <span class="hljs-title class_">PixelMap</span> | <span class="hljs-literal">undefined</span> = <span class="hljs-literal">undefined</span>
  @<span class="hljs-title class_">State</span> <span class="hljs-attr">cropped</span>: <span class="hljs-title class_">PixelMap</span> | <span class="hljs-literal">undefined</span> = <span class="hljs-literal">undefined</span>

  private <span class="hljs-keyword">async</span> <span class="hljs-title function_">decodeImage</span>(<span class="hljs-params">uri: string</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">let</span> file = fileIo.<span class="hljs-title function_">openSync</span>(uri, fileIo.<span class="hljs-property">OpenMode</span>.<span class="hljs-property">READ_ONLY</span>)
      <span class="hljs-keyword">const</span> imageSourceApi = image.<span class="hljs-title function_">createImageSource</span>(file.<span class="hljs-property">fd</span>)
      imageSourceApi.<span class="hljs-title function_">getImageInfo</span>(<span class="hljs-number">0</span>, <span class="hljs-function">(<span class="hljs-params">error: BusinessError, imageInfo</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (imageInfo ==
          <span class="hljs-literal">undefined</span>) {
          <span class="hljs-comment">//log.e(error)</span>
        }
        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`imageInfo: &nbsp;<span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(imageInfo)}</span>`</span>)
      })
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> imageSourceApi.<span class="hljs-title function_">createPixelMap</span>()
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">//log.e(error)</span>
      <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>
    }
  }

  <span class="hljs-title function_">build</span>(<span class="hljs-params"></span>) {
    <span class="hljs-title class_">Column</span>() {
      <span class="hljs-title class_">Button</span>(<span class="hljs-string">'添加照片'</span>).<span class="hljs-title function_">onClick</span>(<span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">let</span> uris = <span class="hljs-keyword">await</span> <span class="hljs-title function_">selectPhoto</span>({
          <span class="hljs-title class_">MIMEType</span>: picker.<span class="hljs-property">PhotoViewMIMETypes</span>.<span class="hljs-property">IMAGE_TYPE</span>,
          <span class="hljs-attr">maxSelectNumber</span>: <span class="hljs-number">1</span>,
          <span class="hljs-attr">isPhotoTakingSupported</span>: <span class="hljs-literal">false</span>,
          <span class="hljs-attr">recommendationOptions</span>: { <span class="hljs-attr">recommendationType</span>: photoAccessHelper.<span class="hljs-property">RecommendationType</span>.<span class="hljs-property">PROFILE_PICTURE</span>, }
        })
        <span class="hljs-keyword">if</span> (uris.<span class="hljs-property">length</span> == <span class="hljs-number">0</span>) {
          <span class="hljs-keyword">return</span>
        }
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">origin</span> = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">decodeImage</span>(uris[<span class="hljs-number">0</span>])
        <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">origin</span>) {
          <span class="hljs-keyword">let</span> info = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">origin</span>.<span class="hljs-title function_">getImageInfo</span>()
          <span class="hljs-variable language_">this</span>.<span class="hljs-property">origin</span>.<span class="hljs-title function_">crop</span>({ <span class="hljs-attr">x</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">size</span>: { <span class="hljs-attr">width</span>: info.<span class="hljs-property">size</span>.<span class="hljs-property">width</span>, <span class="hljs-attr">height</span>: info.<span class="hljs-property">size</span>.<span class="hljs-property">height</span> / <span class="hljs-number">2</span> } })
          <span class="hljs-variable language_">this</span>.<span class="hljs-property">cropped</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">origin</span>
        }
      })
      <span class="hljs-title class_">Image</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">origin</span>).<span class="hljs-title function_">width</span>(<span class="hljs-string">'100%'</span>).<span class="hljs-title function_">height</span>(<span class="hljs-string">'100%'</span>).<span class="hljs-title function_">layoutWeight</span>(<span class="hljs-number">1</span>).<span class="hljs-title function_">objectFit</span>(<span class="hljs-title class_">ImageFit</span>.<span class="hljs-property">Contain</span>)
      <span class="hljs-title class_">Image</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">cropped</span>).<span class="hljs-title function_">width</span>(<span class="hljs-string">'100%'</span>).<span class="hljs-title function_">height</span>(<span class="hljs-string">'100%'</span>).<span class="hljs-title function_">layoutWeight</span>(<span class="hljs-number">1</span>).<span class="hljs-title function_">objectFit</span>(<span class="hljs-title class_">ImageFit</span>.<span class="hljs-property">Contain</span>)
    }.<span class="hljs-title function_">width</span>(<span class="hljs-string">`100%`</span>)
  }
}

<span class="hljs-keyword">const</span> <span class="hljs-attr">PHOTO_DEFAULT_SELECT_NUMBER</span>: number =
  <span class="hljs-number">9</span>;

<span class="hljs-comment">//数量 </span>
<span class="hljs-comment">/**
 * 通过选择模式拉起photoPicker界面,用户可以选择一个或多个图片/视频。
 * <span class="hljs-doctag">@param</span> options * <span class="hljs-doctag">@returns</span>
 **/</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">selectPhoto</span>(<span class="hljs-params">options?: PhotoSelectOptions</span>): <span class="hljs-title class_">Promise</span>&lt;<span class="hljs-title class_">Array</span>&lt;string&gt;&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">if</span> (!options) {
      options = <span class="hljs-keyword">new</span> <span class="hljs-title class_">PhotoSelectOptions</span>();
    }
    <span class="hljs-keyword">if</span> (!options.<span class="hljs-property">MIMEType</span>) {
      <span class="hljs-comment">//可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。 </span>
      options.<span class="hljs-property">MIMEType</span> = photoAccessHelper.<span class="hljs-property">PhotoViewMIMETypes</span>.<span class="hljs-property">IMAGE_TYPE</span>;
    }
    <span class="hljs-keyword">if</span> (!options.<span class="hljs-property">maxSelectNumber</span>) {
      <span class="hljs-comment">//选择媒体文件数量的最大值,默认9 </span>
      options.<span class="hljs-property">maxSelectNumber</span> = <span class="hljs-variable constant_">PHOTO_DEFAULT_SELECT_NUMBER</span>;
    }
    <span class="hljs-keyword">if</span> (options.<span class="hljs-property">isPhotoTakingSupported</span> == <span class="hljs-literal">undefined</span>) {
      options.<span class="hljs-property">isPhotoTakingSupported</span> =
        <span class="hljs-literal">true</span>;
      <span class="hljs-comment">//支持拍照。 </span>
      <span class="hljs-comment">// } </span>
      <span class="hljs-keyword">if</span> (options.<span class="hljs-property">isEditSupported</span> == <span class="hljs-literal">undefined</span>) {
        options.<span class="hljs-property">isEditSupported</span> =
          <span class="hljs-literal">true</span>;
        <span class="hljs-comment">//支持编辑照片。 </span>
        <span class="hljs-comment">// } </span>
        <span class="hljs-keyword">if</span> (options.<span class="hljs-property">isSearchSupported</span> == <span class="hljs-literal">undefined</span>) {
          options.<span class="hljs-property">isSearchSupported</span> =
            <span class="hljs-literal">true</span>;
          <span class="hljs-comment">//支持编辑照片。 </span>
          <span class="hljs-comment">// } </span>
          <span class="hljs-keyword">let</span> <span class="hljs-attr">photoSelectOptions</span>: photoAccessHelper.<span class="hljs-property">PhotoSelectOptions</span> = {
            <span class="hljs-title class_">MIMEType</span>: options.<span class="hljs-property">MIMEType</span>,
            <span class="hljs-attr">maxSelectNumber</span>: options.<span class="hljs-property">maxSelectNumber</span>,
            <span class="hljs-attr">isPhotoTakingSupported</span>: options.<span class="hljs-property">isPhotoTakingSupported</span>,
            <span class="hljs-attr">isEditSupported</span>: options.<span class="hljs-property">isEditSupported</span>,
            <span class="hljs-attr">isSearchSupported</span>: options.<span class="hljs-property">isSearchSupported</span>,
            <span class="hljs-attr">recommendationOptions</span>: options.<span class="hljs-property">recommendationOptions</span>,
            <span class="hljs-attr">preselectedUris</span>: options.<span class="hljs-property">preselectedUris</span>
          }
          <span class="hljs-keyword">let</span> photoPicker = <span class="hljs-keyword">new</span> photoAccessHelper.<span class="hljs-title class_">PhotoViewPicker</span>();
          <span class="hljs-keyword">let</span> <span class="hljs-attr">photoSelectResult</span>: photoAccessHelper.<span class="hljs-property">PhotoSelectResult</span> = <span class="hljs-keyword">await</span> photoPicker.<span class="hljs-title function_">select</span>(photoSelectOptions)
          <span class="hljs-keyword">if</span> (photoSelectResult &amp;&amp; photoSelectResult.<span class="hljs-property">photoUris</span> &amp;&amp; photoSelectResult.<span class="hljs-property">photoUris</span>.<span class="hljs-property">length</span> &gt; <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">return</span> photoSelectResult.<span class="hljs-property">photoUris</span>
          } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> [];
          }
        }
        <span class="hljs-keyword">catch</span>(err) {
          <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(err)
          <span class="hljs-keyword">return</span> [];
        }
      }

      <span class="hljs-keyword">class</span> <span class="hljs-title class_">PhotoSelectOptions</span> {
        <span class="hljs-title class_">MIMEType</span>?: photoAccessHelper.<span class="hljs-property">PhotoViewMIMETypes</span> =
          photoAccessHelper.<span class="hljs-property">PhotoViewMIMETypes</span>.<span class="hljs-property">IMAGE_TYPE</span>;
        <span class="hljs-comment">//可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。 </span>
        maxSelectNumber?: number = <span class="hljs-variable constant_">PHOTO_DEFAULT_SELECT_NUMBER</span>;
        <span class="hljs-comment">//选择媒体文件数量的最大值(默认值为50,最大值为500)。 </span>
        isPhotoTakingSupported?: boolean = <span class="hljs-literal">true</span>;
        <span class="hljs-comment">//支持拍照。 </span>
        isEditSupported?: boolean = <span class="hljs-literal">true</span>;
        <span class="hljs-comment">//支持编辑照片。 </span>
        isSearchSupported?: boolean = <span class="hljs-literal">true</span>;
        <span class="hljs-comment">//支持搜索。 </span>
        recommendationOptions?: photoAccessHelper.<span class="hljs-property">RecommendationOptions</span>;
        <span class="hljs-comment">//支持照片推荐。 </span>
        preselectedUris?: <span class="hljs-title class_">Array</span>&lt;string&gt;;
        <span class="hljs-comment">//预选择图片的uri数据。 </span>
        <span class="hljs-comment">// }</span>
      }
</code></pre>

更多关于HarmonyOS 鸿蒙Next:【PixelMap】crop后,显示到Image控件中仍然未被截取的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

修改后代码

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo, picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';

@Entry
@Component
struct Index {
  @State origin: PixelMap | undefined = undefined
  @State origin2: PixelMap | undefined = undefined
  @State cropped: PixelMap | undefined = undefined
  private uri:string = ''

  private async decodeImage(uri: string) {
    try {
      let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)
      const imageSourceApi = image.createImageSource(file.fd)
      imageSourceApi.getImageInfo(0, (error: BusinessError, imageInfo) => {
        if (imageInfo == undefined) {
          // log.e(error)
        }
        console.log(`imageInfo: ${JSON.stringify(imageInfo)}`)
      })

      return await imageSourceApi.createPixelMap()
    } catch (error) {
      // log.e(error)
      return undefined
    }
  }

  build() {
    Column() {
      Button('添加照片')
        .onClick(async () => {
          let uris = await selectPhoto({
            MIMEType: picker.PhotoViewMIMETypes.IMAGE_TYPE,
            maxSelectNumber: 1,
            isPhotoTakingSupported: false,
            recommendationOptions: {
              recommendationType: photoAccessHelper.RecommendationType.PROFILE_PICTURE,
            }
          })

          if (uris.length == 0) {
            return
          }
          this.origin = await this.decodeImage(uris[0])
          this.origin2 = await this.decodeImage(uris[0])
          if (this.origin) {
            let info = await this.origin.getImageInfo()
            let region: image.Region = { x: 0, y: 0, size: { height: info.size.height / 2, width: info.size.width } };
            if (this.origin2 != undefined) {
              this.origin2.crop(region).then(async () => {
                if (this.origin2 != undefined) {
                  let pixel = await copyPixelMap(this.origin2);
                  this.origin2.release();
                  this.origin2 = pixel;
                  console.info('Sucessed in setting crop.');
                }
              }).catch((err: BusinessError) => {
                console.error('Failed to crop pixelmap.');
              })
            }
          }
        })

      Image(this.origin)
        .width('100%')
        .height('100%')
        .layoutWeight(1)
        .objectFit(ImageFit.Contain)

      Image(this.origin2)
        .width('100%')
        .height('100%')
        .layoutWeight(1)
        .objectFit(ImageFit.Contain)
    }
    .width(`100%`)
  }
}

const PHOTO_DEFAULT_SELECT_NUMBER: number = 9; //数量

async function copyPixelMap(imagePixel: PixelMap): Promise<image.PixelMap> {
  let imageInfo: image.ImageInfo = await imagePixel.getImageInfo();
  console.info(`copyPixelMapSize: width:${imageInfo?.size.width} height:${imageInfo?.size.height}`);
  let newRegion: image.Region = {
    size: { height: imageInfo.size.height, width: imageInfo.size.width },
    x: 0,
    y: 0
  }

  let newArea: image.PositionArea = {
    pixels: new ArrayBuffer(imageInfo.size.height * imageInfo.size.width * 4),
    offset: 0,
    stride: imageInfo.stride,
    region: newRegion
  }

  await imagePixel.readPixels(newArea);
  let opts: image.InitializationOptions = { editable: true, pixelFormat: 4, size: imageInfo.size };
  let imagePixelCache = await image.createPixelMap(newArea.pixels, opts);
  return imagePixelCache;
}

/**
 * 通过选择模式拉起photoPicker界面,用户可以选择一个或多个图片/视频。
 */

async function selectPhoto(options?: PhotoSelectOptions): Promise<Array<string>> {
  try {
    if (!options) {
      options = new PhotoSelectOptions();
    }

    if (!options.MIMEType) { //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。
      options.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
    }

    if (!options.maxSelectNumber) { //选择媒体文件数量的最大值,默认9
      options.maxSelectNumber = PHOTO_DEFAULT_SELECT_NUMBER;
    }

    if (options.isPhotoTakingSupported == undefined) {
      options.isPhotoTakingSupported = true; //支持拍照。
    }

    if (options.isEditSupported == undefined) {
      options.isEditSupported = true; //支持编辑照片。
    }

    if (options.isSearchSupported == undefined) {
      options.isSearchSupported = true; //支持编辑照片。
    }

    let photoSelectOptions: photoAccessHelper.PhotoSelectOptions = {
      MIMEType: options.MIMEType,
      maxSelectNumber: options.maxSelectNumber,
      isPhotoTakingSupported: options.isPhotoTakingSupported,
      isEditSupported: options.isEditSupported,
      isSearchSupported: options.isSearchSupported,
      recommendationOptions: options.recommendationOptions,
      preselectedUris: options.preselectedUris
    }
    let photoPicker = new photoAccessHelper.PhotoViewPicker();
    let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(photoSelectOptions)
    if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
      return photoSelectResult.photoUris
    } else {
      return [];
    }
  } catch (err) {
    console.error(err)
    return [];
  }
}

class PhotoSelectOptions {
  MIMEType?: photoAccessHelper.PhotoViewMIMETypes = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。
  maxSelectNumber?: number = PHOTO_DEFAULT_SELECT_NUMBER; //选择媒体文件数量的最大值(默认值为50,最大值为500)。
  isPhotoTakingSupported?: boolean = true; //支持拍照。
  isEditSupported?: boolean = true; //支持编辑照片。
  isSearchSupported?: boolean = true; //支持搜索。
  recommendationOptions?: photoAccessHelper.RecommendationOptions; //支持照片推荐。
  preselectedUris?: Array<string>; //预选择图片的uri数据。
}

更多关于HarmonyOS 鸿蒙Next:【PixelMap】crop后,显示到Image控件中仍然未被截取的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对帖子标题“HarmonyOS 鸿蒙Next:【PixelMap】crop后,显示到Image控件中仍然未被截取”的问题,这里提供直接的专业解答:

在HarmonyOS中,如果你在使用PixelMap进行裁剪(crop)操作后,发现显示到Image控件中的内容并未按照预期被截取,可能的原因包括但不限于:

  1. 裁剪区域设置不正确:确保你设置的裁剪区域的坐标和尺寸是正确的,且该区域完全位于原始PixelMap的范围内。

  2. Image控件刷新问题:裁剪后的PixelMap需要重新设置给Image控件,并确保Image控件进行了刷新。可以通过调用Image控件的setImage(PixelMap pixelMap)方法来更新显示的图像,并检查是否有必要手动触发控件的刷新。

  3. 资源或内存管理问题:确认裁剪操作没有导致内存泄漏或资源未被正确释放,这可能会影响后续图像的正常显示。

  4. Image控件属性设置:检查Image控件的属性设置,确保没有设置会覆盖或影响图像显示的属性,如缩放模式、透明度等。

如果以上检查均无误,但问题依旧存在,请考虑是否是系统或框架层面的bug。此时,如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部