HarmonyOS鸿蒙开发实战( Beta5.0)图片压缩实践方案

news2024/11/16 19:45:10

鸿蒙HarmonyOS NEXT开发实战往期文章必看(持续更新......)

HarmonyOS NEXT应用开发性能实践总结

HarmonyOS NEXT应用开发案例实践总结合集

最新版!“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通)

非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!


介绍

图片压缩在应用开发中是一个非常常见的需求,比如在处理用户上传图片时,需要上传指定大小以内的图片。目前图片压缩支持jpeg、webp、png格式。本例将介绍如何通过packing和scale实现图片压缩(如自动压缩到目标大小以内,手动调整图片质量和尺寸进行压缩等),以及把图片压缩成不同格式后保存到图库。

效果图预览

使用说明

  1. 进入页面,点击添加图片,从拉起的图库中选择一张图片,点击完成。在应用页面压缩前一栏会显示图片的大小以及格式。

  2. 压缩模式选择自动模式,输入图片压缩目标大小,可以自定义调整scale每次缩小倍数(相关参数说明点击右侧?帮助图标查看)。压缩偏好选择优先压缩质量,可以自定义调整packing最小二分单位(相关参数说明点击右侧?帮助图标查看)。可以选择图片压缩的输出格式。点击压缩按钮开始压缩,压缩完成后提示压缩完成,并在压缩后一栏显示压缩后预估的图片大小(压缩后所展示的图片大小,是该图片在内存中作为ArrayBuffer数据的压缩后大小,这一数值并不直接等同于该图片在最终保存到相册时的实际文件大小),以及压缩后的图片格式。点击保存到图库按钮,保存完成后提示已保存到相册。打开图库相册可查看保存的图片,相册中图片格式和压缩后一栏显示的格式一致,图片大小和压缩后一栏显示的图片大小相近。

  3. 压缩模式选择自动模式,输入图片压缩目标大小,可以自定义调整scale每次缩小倍数压缩偏好选择优先压缩尺寸,可以自定义调整最低图片质量(相关参数说明点击右侧?帮助图标查看)。可以选择图片压缩的输出格式。点击压缩按钮开始压缩,压缩完成后提示压缩完成,并在压缩后一栏显示压缩后预估的图片大小,以及压缩后的图片格式。点击保存到图库按钮,保存后提示已保存到相册。打开图库相册可查看保存的图片,相册中图片格式和压缩后一栏显示的格式一致,图片大小和压缩后一栏显示的图片大小相近。

  4. 压缩模式选择手动模式,可以自定义调整图片质量和图片尺寸(相关参数说明点击右侧?帮助图标查看)。可以选择图片压缩的输出格式。点击压缩按钮开始压缩,压缩完成后提示压缩完成,并在压缩后一栏显示压缩后预估的图片大小,以及压缩后的图片格式。点击保存到图库按钮,保存后提示已保存到相册。打开图库相册可查看保存的图片,相册中图片格式和压缩后一栏显示的格式一致,图片大小和压缩后一栏显示的图片大小相近。

  5. 点击应用页面上功能项右侧对应的?帮助图标可查看对应功能项的相关说明。

  6. 手动模式的压缩是指手动调整图片质量和尺寸进行图片压缩。自动模式的压缩是指通过设置图片压缩目标大小,根据设置的相关压缩参数(如scale每次缩小倍数,packing最小二分单位,最低图片质量),将图片自动压缩至最接近但不超过该压缩目标的大小。但是如果参数配置不合理(如scale每次缩小倍数设置较大,但压缩目标大小又设置很小),可能会出现最终压缩出来的图片达不到设定的压缩目标大小。

  7. 自动模式的压缩分为优先压缩图片质量和优先压缩图片尺寸。优先压缩图片质量是指优先通过调整图片质量进行压缩。但是如果图片质量压缩到最低仍然超过目标大小,则会再采用scale进行二次压缩。对于通过调整图片质量就能满足目标大小要求的图片,如果想要找到尽可能接近目标大小的最佳压缩大小,可以调低packing最小二分单位,但相应的压缩性能也会更差一些。优先压缩图片尺寸是指优先通过调整图片尺寸进行压缩。如果对图片质量要求不高但是需要压缩后的图片尺寸尽可能大一些也可以调低最低图片质量

实现思路

  1. 拉起图库选择要压缩的图片。使用photoAccessHelper.PhotoViewPicker创建图库选择器实例photoViewPicker,调用photoViewPicker.select()接口拉起图库界面进行图片选择。图片选择成功后,返回photoSelectResult结果集。从photoSelectResult.photoUris中获取返回图库选择后的媒体文件的uri数组,从而获取图片大小,并在页面上显示选择的图片。
async selectPhotoFromAlbum() {
  // 创建图库选项实例
  const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
  // 设置选择的媒体文件类型为Image
  photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
  // 设置选择媒体文件的最大数目
  photoSelectOptions.maxSelectNumber = 1;
  // 创建图库选择器实例
  const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
  // 调用photoViewPicker.select()接口拉起图库界面进行图片选择,图片选择成功后,返回photoSelectResult结果集。
  photoViewPicker.select(photoSelectOptions).then((photoSelectResult) => {
    // select返回的uri权限是只读权限,需要将uri写入全局变量@State中即可进行读取文件数据操作。
    this.uris = photoSelectResult.photoUris;
    this.photoCount = this.uris.length;
    if (this.photoCount > 0) {
      const ALBUM_PATH: string = photoSelectResult.photoUris[0];
      // 找到最后一个点(.)的索引位置
      let lastDotIndex = ALBUM_PATH.lastIndexOf('.');
      // 使用slice方法从最后一个点之后的位置开始截取字符串到末尾
      this.beforeCompressFmt =
        ALBUM_PATH.slice(lastDotIndex + 1) === 'jpg' ? 'jpeg' : ALBUM_PATH.slice(lastDotIndex + 1);
      this.afterCompressFmt = this.beforeCompressFmt;
      // 读取选择图片的buffer
      const file = fs.openSync(ALBUM_PATH, fs.OpenMode.READ_ONLY);
      // 获取选择图片的字节长度
      this.beforeCompressByteLength = fs.statSync(file.fd).size;
      fs.closeSync(file);
    }
  }).catch((err: BusinessError) => {
    hilog.error(0x0000, TAG, `PhotoViewPicker.select failed :, error code: ${err.code}, message: ${err.message}.`);
  })
}
  1. 手动模式压缩图片。先获取从图库选择的图片uris,然后将图片数据读取到buffer。通过createImageSource(buffer)创建图片源实例,设置解码参数DecodingOptions,传入createPixelMap创建PixelMap图片对象originalPixelMap。使用scale进行图片尺寸压缩,使用packing进行图片质量压缩。
manualCompression() {
  const ALBUM_PATH: string = this.uris[0];
  const file = fs.openSync(ALBUM_PATH, fs.OpenMode.READ_ONLY);
  let buffer = new ArrayBuffer(fs.statSync(file.fd).size);
  fs.readSync(file.fd, buffer);
  fs.closeSync(file);
  const decodingOptions: image.DecodingOptions = { editable: true };
  const imageSource: image.ImageSource = image.createImageSource(buffer);
  imageSource.createPixelMap(decodingOptions).then(async (originalPixelMap: image.PixelMap) => {
    // 使用scale对图片进行缩放。入参分别为图片宽高的缩放倍数
    await originalPixelMap.scale(this.imageScaleVal / 100, this.imageScaleVal / 100);
    // savePixelMap用于把压缩后的图片保存到图库时使用。由于保存图片时调用的packToFile内部会做类似packing的处理,所以这里只保存scale缩放尺寸后的PixelMap。
    this.savePixelMap = originalPixelMap;
    // packing压缩图片
    let compressedImageData: ArrayBuffer =
      await this.packing(originalPixelMap, this.imageQualityVal, this.afterCompressFmt);
    // 压缩后的ArrayBuffer数据转PixelMap
    let imageSource = image.createImageSource(compressedImageData);
    let opts: image.DecodingOptions = { editable: true };
    // showPixelMap用于显示压缩后的图片
    this.showPixelMap = await imageSource.createPixelMap(opts);
    // showCompressFormat用于显示压缩后的图片格式
    this.showCompressFormat = this.afterCompressFmt;
    // 显示估算packing压缩后的图片大小。该图片在内存中作为ArrayBuffer数据的压缩后大小,这一数值并不直接等同于该图片在最终保存到相册时的实际文件大小。
    this.afterCompressionSize = (compressedImageData.byteLength / BYTE_CONVERSION).toFixed(1);
    promptAction.showToast({ message: $r('app.string.image_compression_compress_completed') });
  }).catch((err: BusinessError) => {
    hilog.error(0x0000, TAG, `Failed to create PixelMap, error code: ${err.code}, message: ${err.message}.`);
  });
}
  1. 自动模式(指定压缩目标大小)优先压缩图片尺寸。优先使用scale对图片进行尺寸缩放,采用while循环每次递减reduceScaleVal倍数(对应‘scale每次缩小倍数’)进行尺寸缩放,再用packing(其中图片质量参数quality根据‘最低图片质量’设置)获取压缩后的图片大小,最终查找压缩到最接近指定图片压缩目标的大小,并获取图片压缩数据用于后续图片保存。
async scalePriorityCompress(sourcePixelMap: image.PixelMap, maxCompressedImageSize: number, quality: number) {
  // ...
  // scale压缩图片尺寸。采用while循环每次递减reduceScaleVal,最终查找到最接近指定图片压缩目标大小的缩放倍数的图片压缩数据。
  let imageScale = 1; // 定义图片宽高的缩放倍数,1表示原比例。
  const REDUCE_SCALE = this.reduceScaleVal;
  const AFTER_COMPRESS_FMT = this.afterCompressFmt;
  // 判断压缩后的图片大小是否大于指定图片的压缩目标大小,如果大于,继续降低缩放倍数压缩。
  while (compressedImageData.byteLength > maxCompressedImageSize * BYTE_CONVERSION) {
    if (imageScale > 0) {
      // 性能知识点: 由于scale会直接修改图片PixelMap数据,所以不适用二分查找scale缩放倍数。这里采用循环递减reduceScaleVal缩放图片,
      // 来查找确定最适合的缩放倍数。如果对图片压缩质量要求不高,建议调高每次递减的缩放倍数,减少循环,提升scale压缩性能。
      imageScale = imageScale - REDUCE_SCALE; // 每次缩放倍数
      // 使用scale对图片尺寸进行缩放
      await sourcePixelMap.scale(imageScale, imageScale);
      // packing压缩
      compressedImageData = await this.packing(sourcePixelMap, quality, AFTER_COMPRESS_FMT);
    } else {
      // imageScale缩放倍数小于等于0时,没有意义,结束压缩。
      break;
    }
  }
  // ...
}
  1. 自动模式(指定压缩目标大小)优先压缩图片质量。先判断设置图片质量参数为0时,packing能压缩到的图片最小字节大小compressedImageData.byteLength是否满足指定的图片压缩大小。如果满足,则使用packing方式二分查找最接近指定图片压缩目标大小的quality来压缩图片。如果不满足,则图片质量按最低0进行设置,并调用scalePriorityCompress进行scale尺寸压缩。
// 优先压缩图片质量
async qualityPriorityCompress(sourcePixelMap: image.PixelMap, maxCompressedImageSize: number) {
  let compressedImageData: ArrayBuffer =
    await this.packing(sourcePixelMap, IMAGE_QUALITY_ZERO, this.afterCompressFmt);
  // 先判断图片质量参数设置最低0能否满足目标大小。如果能满足目标大小,则直接使用packing二分图片质量。如果不满足,则质量参数固定为0,进行scale尺寸压缩
  if (compressedImageData.byteLength <= maxCompressedImageSize * BYTE_CONVERSION) {
    // 满足目标大小,直接使用packing二分
    await this.packingImage(sourcePixelMap, compressedImageData, maxCompressedImageSize * BYTE_CONVERSION);
  } else {
    // 不满足目标大小,质量参数设置为0,再进行scale尺寸压缩
    await this.scalePriorityCompress(sourcePixelMap, maxCompressedImageSize, IMAGE_QUALITY_ZERO);
  }
  // 更新显示压缩后的图片格式
  this.showCompressFormat = this.afterCompressFmt;
}

// packing二分方式循环压缩
async packingImage(sourcePixelMap: image.PixelMap, compressedImageData: ArrayBuffer, maxCompressedImageByte: number) {
  let imageQuality: number = 0;
  const DICHOTOMY_ACCURACY = this.minBisectUnit;
  // 图片质量参数范围为0-100,这里以minBisectUnit为最小二分单位创建用于packing二分图片质量参数的数组。
  const packingArray: number[] = [];
  // 性能知识点: 如果对图片压缩质量要求不高,建议调高minBisectUnit(对应‘packing最小二分单位’),减少循环,提升packing压缩性能。
  for (let i = 0; i <= 100; i += DICHOTOMY_ACCURACY) {
    packingArray.push(i);
  }
  let left = 0; // 定义二分搜索范围的左边界
  let right = packingArray.length - 1; // 定义二分搜索范围的右边界
  const AFTER_COMPRESS_FMT = this.afterCompressFmt;
  // 二分压缩图片
  while (left <= right) {
    const mid = Math.floor((left + right) / 2); // 定义二分搜索范围的中间位置
    imageQuality = packingArray[mid]; // 获取二分中间位置的图片质量值
    // 根据传入的图片质量参数进行packing压缩,返回压缩后的图片文件流数据。
    compressedImageData = await this.packing(sourcePixelMap, imageQuality, AFTER_COMPRESS_FMT);
    // 判断查找一个尽可能接近但不超过压缩目标的压缩大小
    if (compressedImageData.byteLength <= maxCompressedImageByte) {
      // 二分目标值在右半边,继续在更高的图片质量参数(即mid + 1)中搜索
      left = mid + 1;
      // 判断mid是否已经二分到最后,如果二分完了,退出
      if (mid === packingArray.length - 1) {
        break;
      }
      // 获取下一次二分的图片质量参数(mid+1)压缩的图片文件流数据
      compressedImageData = await this.packing(sourcePixelMap, packingArray[mid + 1], AFTER_COMPRESS_FMT);
      // 判断用下一次图片质量参数(mid+1)压缩的图片大小是否大于指定图片的压缩目标大小。如果大于,说明当前图片质量参数(mid)压缩出来的
      // 图片大小最接近指定图片的压缩目标大小。传入当前图片质量参数mid,得到最终目标图片压缩数据。
      if (compressedImageData.byteLength > maxCompressedImageByte) {
        compressedImageData = await this.packing(sourcePixelMap, packingArray[mid], AFTER_COMPRESS_FMT);
        break;
      }
    } else {
      // 目标值不在当前范围的右半部分,将搜索范围的右边界向左移动,以缩小搜索范围并继续在下一次迭代中查找左半部分。
      right = mid - 1;
    }
  }
  // ...
}
  1. 压缩后的图片数据保存到相册。通过photoAccessHelper.getPhotoAccessHelper获取相册管理模块的实例,使用createAsset创建图片资源,然后使用createImagePacker创建ImagePacker实例。最后调用imagePacker.packToFile传入压缩后的PixelMap图片源,对应的图片格式和质量参数packOpts,编码后打包进图片文件,图片将自动保存到相册。需要说明packToFile内部会进行packing操作,所以传入packToFile的PixelMap对象只是scale尺寸缩放后的图片数据,最终需要压缩的图片质量通过packOpts进行设置。
async saveImageToAlbum(): Promise<void> {
  // 获取相册管理模块的实例
  const HELPER = photoAccessHelper.getPhotoAccessHelper(this.context);
  // 指定待创建的文件类型、后缀和创建选项,创建图片资源
  const URI = await HELPER.createAsset(photoAccessHelper.PhotoType.IMAGE, this.afterCompressFmt);
  let file = await fs.open(URI, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  let imagePacker = image.createImagePacker();
  let packOpts: image.PackingOption = {
    format: 'image/' + this.afterCompressFmt,
    quality: this.isAutoMode ? this.autoModeQuality : this.imageQualityVal
  };
  // 指定打包参数,将PixelMap图片源编码后直接打包进文件
  imagePacker.packToFile(this.savePixelMap, file.fd, packOpts, async (err: BusinessError) => {
    if (err) {
      hilog.error(0x0000, TAG, `Failed to pack the image to file, error code: ${err.code}, message: ${err.message}.`);
    } else {
      promptAction.showToast({ message: $r('app.string.image_compression_save_image_msg') });
    }
    // TODO 知识点:使用packToFile方法,需要调用imagePacker.release主动释放imagePacker,打开图库时才能看到新存入的图片
    await fs.close(file.fd).finally(() => {
      imagePacker.release();
    })
  })
}

高性能知识点

本示例packing方式压缩图片时,使用二分查找最接近指定图片压缩目标大小的图片质量quality来压缩图片,提升查找性能。

工程结构&模块类型

imagecompression                               // har类型
|---view
|   |---ImageCompression.ets                   // 视图层-图片压缩页面
|   |---HelpDescription.ets                    // 视图层-自定义帮助组件

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为体系杂乱无章,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)路线、视频、文档用来跟着学习是非常有必要的。

如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员

鸿蒙 NEXT 全栈开发学习笔记 希望这一份鸿蒙学习文档能够给大家带来帮助~

这份鸿蒙(HarmonyOS NEXT)包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、(南向驱动、嵌入式等)鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。


 鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.视频教程+学习PDF文档

(鸿蒙语法ArkTS、TypeScript、ArkUI教程……)全球开发者的开源社区,开源代码

 纯血版鸿蒙全套学习文档(面试、文档、全套视频等)全球开发者的开源社区,开源代码

                   

鸿蒙APP开发必备

​​

总结

参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaJUnit包 JUnit5断言assert用法

慢慢来&#xff0c;一切都会解决的 —— 24.9.26 在Java中使用JUnit包下断言assert&#xff0c;要区分JUnit4和JUnit5的区别 JUnit4不支持一些断言句 需要引入JUnit5的支持 引入步骤&#xff1a; ① ② 在settings中点击plugins插件&#xff0c;搜索JUnit&#xff0c;选择…

89个H5小游戏源码

下载地址&#xff1a;https://download.csdn.net/download/w2sft/89791650 亲测可用&#xff0c;代码完整&#xff0c;都是htmljs&#xff0c;保存到本地即可。 游戏截图&#xff1a;

uniapp出现 下拉框等组件被遮挡 的分析

目录 1. 问题所示2. 代码复现3. 解决方法3.1 下拉框被遮挡3.2 uni-collapse-item 无法下拉的问题 1. 问题所示 下拉框被遮挡的问题&#xff1a; uni-collapse-item组件无法下拉的问题&#xff1a; 2. 代码复现 博主的代码精简如下&#xff1a; <template><view>…

基于Springboot+微信小程序 的高校社团管理小程序(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

Transcipher:从对称加密到同态加密

摘要 本文介绍了Transcipher的概念。在Transcipher的框架下&#xff0c;用户使用高效的对称加密&#xff0c;对自己的数据进行加密&#xff0c;然后将密文和私钥的同态加密密文传输给服务器。服务器进行同态解密&#xff0c;得到用户数据同态加密的密文。Transcipher通过将计算…

研控伺服驱动器通过EtherCAT转profinet网关与西门子PLC1200连接

本案例涉及西门子1200PLC与研控总线型混合伺服驱动器的连接&#xff0c;其在正常工作时需支持EtherCAT协议并作为EtherCAT从站&#xff0c;而监控系统中的PLC支持PROFINET协议。在本案例中采用EtherCat转ProfiNet网关&#xff0c;以实现PLC和伺服驱动器的整体交互。下图呈现了自…

andon安灯系统让生产异常快速高效解决

在现代化工厂的生产过程中&#xff0c;设备故障、物料短缺、工艺异常等突发事件屡见不鲜。这些异常情况不仅会直接影响生产效率&#xff0c;还会造成生产线停滞、产品质量下降&#xff0c;甚至引发安全事故。如何快速有效地解决这些异常&#xff0c;是提升生产效率和产品质量的…

java 解析excel

在Java中解析Excel文件&#xff0c;可以使用Apache POI库。以下是一个简单的例子&#xff0c;展示如何使用Apache POI读取一个Excel文件&#xff08;假设为.xlsx格式&#xff09;的内容。 首先&#xff0c;确保你的项目中包含了Apache POI的依赖。如果你使用Maven&#xff0c;…

CSRF高级防御绕过

1&#xff09;回顾low级别做过csrf页面的密码重置&#xff0c;重复之前的操作&#xff0c;我们发现级别调整中级之后&#xff0c;报错如下 2&#xff09;检查源码 进入dvwa源码&#xff0c;查找到checktoken&#xff1a; 3&#xff09;在dvwa-csrf页面上&#xff0c;抓包 http…

无人机之虚拟云台技术篇

一、概念解释 虚拟云台技术&#xff0c;并非直接安装在无人机上的机械装置&#xff0c;而是通过软件算法和传感器技术&#xff0c;模拟出物理云台的功能&#xff0c;实现对相机或传感器的稳定控制。这种技术通过高精度的算法和实时数据处理&#xff0c;能够在无人机飞行过程中&…

73 矩阵置零

解题思路&#xff1a; \qquad 原地算法&#xff0c;指除原有输入资料所占空间外&#xff0c;使用额外空间尽可能少(常数空间)的算法。本题容易想到的一种解法是&#xff0c;对于m x n的矩阵&#xff0c;一次遍历把含有0元素的行号、列号记录下来&#xff0c;然后再一次遍历把对…

uniapp 使用Vue3 setup引入 uniapp 的onReachBottom

在page.json中加入**“onReachBottonDistance”: 50**&#xff0c;这是距离底部多少开始触发 然后再对应的页面通过import将uniapp的api引入进去 dcloudio/uni-app是不用单独下载的&#xff0c;直接用就行 import {onReachBottom,} from dcloudio/uni-app;然后直接使用就好

centos7 更新 yum源 为 阿里云 LTS

centos7 更新 yum源 为 阿里云 按照下面的 步骤 1,2&#xff0c;3,4 来一遍 参考文档 CentOS yum源设置为国内aliyun yum源 https://developer.aliyun.com/article/1523301?spm5176.26934562.main.2.16c938e4ys9prQ CentOS 镜像 https://developer.aliyun.com/mirror/cent…

【【通信协议之ICMP协议的FPGA实现】】

通信协议之ICMP协议的FPGA实现 整体的实现框图如下所示 arp_rx.v module arp_rx#(//开发板MAC地址 00-11-22-33-44-55parameter BOARD_MAC 48h00_11_22_33_44_55, //开发板IP地址 192.168.1.10 parameter BOARD_IP {8d192,8d168,8d1,8d10} )(input …

【Linux:进程信号】

五个概念&#xff1a; 多个执行流能看到的一份资源叫做共享资源同步和互斥两种方式保护的公共资源叫做临界资源互斥&#xff1a;任何时候只能有一个进程访问该资源如何访问资源&#xff1f;&#xff1a;本质资源访问就是代码访问&#xff0c;代码访问共享资源不访问的共享资源对…

云原生|浅谈云原生中的对象存储之MinIO 的使用

一、什么是对象储存 对象存储&#xff08;Object Storage&#xff09;以对象的形式存储和管理数据&#xff0c;这些对象可以是任何类型的数据&#xff0c;例如 PDF&#xff0c;视频&#xff0c;音频&#xff0c;文本或其他文件类型。对象存储使用分布式存储架构&#xff0c;数据…

基于springboot+vue医院挂号就诊系统设计与实现

基于springbootvue医院挂号就诊系统设计与实现 springboot180基于spring boot的医院挂号就诊系统 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费…

解决macOS MySQL安装后不能远程访问的问题

主要是因为我的后端服务是通过docker部署的, 无法和宿主机的MySQL进行通信. 首先输入 use mysql; 之后输入 update user set host “%” where user “root”; 最后输入 flush privileges; 合起来就是: use mysql;update user set host "%" where user &qu…

视频集成与融合项目中需要视频编码,但是分辨率不兼容怎么办?

在众多视频整合项目中&#xff0c;一个显著的趋势是融合多元化的视频资源&#xff0c;以实现统一监管与灵活调度。这一需求促使项目团队不断探索新的集成方案&#xff0c;确保不同来源的视频流能够无缝对接&#xff0c;共同服务于统一的调看与管理平台&#xff0c;进而提升整体…

工具介绍---效率高+实用

Visual Studio Code (VS Code) 功能特点&#xff1a; 智能代码提示&#xff1a;内置的智能代码提示功能可以自动完成函数、变量等的输入&#xff0c;提高代码编写速度。插件丰富&#xff1a;支持成千上万的扩展插件&#xff0c;例如代码片段、主题、Linting等&#xff0c;能够…