当前位置: 首页 > news >正文

如何让你的图片服务也有类似OSS的图片处理功能

原文链接

前言

有自己机房的公司一般都有一套存储系统用于存储公司的图片、视频、音频、文件等数据,常见的存储系统有以NAS、FASTDFS为代表的传统文件存储,和以Minio为代表的对象存储系统,随着云服务的兴起很多公司逐渐将数据迁移到以阿里云OSS为代表的云对象存储,OSS的好处是不但解决了数据的存储还自带的很多文件的处理功能,如图片的缩放、打水印、裁剪等功能,例如我们要获获取一张宽为200大小的图片只需要在原图后面增加?x-oss-process=image/resize,w_200这个参数就可以了,处理图片确实非常方便。
https://oss-console-img-demo-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,w_200。
传统的NAS、FASTDFS只有存储功能,没有文件处理能力的,我们可以使用图片处理软件给它加上类似的图片处理功能。常用的图片处理软件有ImagemagickGraphicsMagickOpenCV对应的JAVA操作库为im4javaJMagickJavacv。用上这些图片处理软件再配置Nginx+Lua或者OpenResty就可以让你的传统NAS存储也也有像OSS一样的图片处理能力。

ImageMagick、GraphicsMagick的安装

ImageMagick官网下载

官网下载地址:https://imagemagick.org/script/download.php
以windows为例,下载ImageMagick-7.1.1-15-Q16-HDRI-x64-dll.exe ,然后下一步、下一步安装就好了,安装完成后输入magick -version检查是否安装成功:

PS C:\Users\Administrator> magick -version
Version: ImageMagick 7.1.1-15 Q16-HDRI x64 a0a5f3d:20230730 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenCL OpenMP(2.0)
Delegates (built-in): bzlib cairo flif freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib
Compiler: Visual Studio 2022 (193532217)

GraphicsMagick官网下载

GraphicsMagick最初源于ImageMagick5.5.2(2002年11月),但从那时起就完全独立于ImageMagick项目。自从ImageMagick的fork以来,许多作者使用开放的开发模型进行了许多改进(参见新闻),但没有破坏API或实用程序操作。下载地址:
http://www.graphicsmagick.org/download.html
安装完成后输出gm检测是否安装成功。

C:\Users\Administrator>gm
GraphicsMagick 1.3.40 2023-01-14 Q16 http://www.GraphicsMagick.org/
Copyright (C) 2002-2023 GraphicsMagick Group.
Additional copyrights and licenses apply to this software.
See http://www.GraphicsMagick.org/www/Copyright.html for details.
Usage: gm command [options ...]

JAVA操作

JAVA操作GraphicsMagick可以使用im4java
引入POM依赖im4java

        <dependency><groupId>org.im4java</groupId><artifactId>im4java</artifactId><version>1.4.0</version></dependency>

im4java官网地址:
https://im4java.sourceforge.net

im4java源码地址:im4java download | SourceForge.net

JAVA操作ImageMagick可以使用JMagick,引入POM依赖:

<dependency><groupId>jmagick</groupId><artifactId>jmagick</artifactId><version>6.6.9</version>
</dependency>

JMagick官网地址:www.jmagick.org

JMagick源码地址:JMagick download | SourceForge.net

图片信息获取

命令获取图片信息

 magick identify .\1.jpg
.\1.jpg PNG 1920x1080 1920x1080+0+0 8-bit sRGB 1.31707MiB 0.000u 0:00.000//格式化输出
magick identify -format '%W,%H,%B,%f,%m'  .\1.jpg
1920,1080,1381050,1.jpg,PNG

JAVA获取图片信息

    @Testpublic void info() throws IOException, InterruptedException, IM4JavaException {String iImageDir = "C:\\Users\\Administrator\\Desktop\\img\\1.jpg";IMOperation operation = new IMOperation();//格式化输出//operation.format("%W,%H,%B,%f,%m");operation.addImage(iImageDir);IdentifyCmd indentity = new IdentifyCmd();ArrayListOutputConsumer output = new ArrayListOutputConsumer();indentity.setOutputConsumer(output);indentity.run(operation);ArrayList<String> cmdOutput = output.getOutput();String line = cmdOutput.get(0);System.out.println(line);//C:\Users\Administrator\Desktop\img\1.jpg PNG 1920x1080 1920x1080+0+0 8-bit sRGB 1.31707MiB 0.000u 0:00.000}

注意事项

  1. 如果运行代码报org.im4java.core.CommandException: java.io.IOException: Cannot run program "identify": CreateProcess error=2, 系统找不到指定的文件。是因为刚安装软件,系统没找到命令,重启电脑后就可以解决。

  2. 可以使用-format '%W,%H,%B,%f,%m'来格式化图片信息的输出 ,具体的格式化参数有很多,详细可以参考官方文档,你想要的图片信息应该都是有的。https://imagemagick.org/script/escape.phps

图片缩放

命令图片缩放

magick .\1.jpg -resize 200x100 1_w200h100.jpg
magick identify -format '%W,%H,%B,%f,%m'  .\1_w200h100.jpg
输出:
178,100,8003,1_w200h100.jpg,JPEG

JAVA图片缩放

    @Testpublic void resizeImg() throws IOException, InterruptedException, IM4JavaException {String srcImagePath = "C:\\Users\\Administrator\\Desktop\\img\\1.jpg";Integer width = 200;Integer height = 100;String newImagePath = "C:\\Users\\Administrator\\Desktop\\img\\1_w200h100.jpg";IMOperation op = new IMOperation();op.addImage(srcImagePath);op.resize(width, height);op.addImage(newImagePath);ImageCommand convert = new ConvertCmd();convert.run(op);}

注意事项

这里我们使用 -resize 200x100 想生成一张200x100的图片,结果输出图片是178x100,因为原始图片为1920x1080为了保持图片宽高比例,做了等比例缩放,防止图片变形。

图片打水印

命令图片打水印

 magick composite  -geometry  '200x200+100+50'  -gravity  'center'  .\avatar.png .\1.jpg  1_avater.jpg

JAVA图片打水印

    @Testpublic void testaddImgWatermark() throws Exception {String srcImagePath="D://img/1.jpg";String destImagePath="D://img/1_avater.jpg";String waterImgPath="D://img/avatar.png";IMOperation op = new IMOperation();//水印大小op.geometry(1000,1000,1000,500);// 水印图片位置NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEastop.gravity("NorthEast");// 水印透明度op.dissolve(100);// 水印op.addImage(waterImgPath);// 原图op.addImage(srcImagePath);// 目标op.addImage(destImagePath);ImageCommand cmd = new CompositeCmd();cmd.run(op);}

注意事项

  1. -geometry '200x200+100+50' 中的200x200是设置水印图片的大小,+200+50设置水印图片相对于gravity的位置
  2. -gravity 'center'是给定水印的相对原图的位置,支持NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEast,这个参数和阿里OSS加水印的也是一样的。

最终打出水印的效果如下:

image.png

图片裁剪

命令图片裁剪

magick convert -gravity  'center'   .\1_avater.jpg -crop  200x200+100+50 1_cut.jpg

JAVA图片裁剪

    @Testpublic  void testCrop()  throws Exception {String srcImagePath="D://img//1.jpg";String destImagePath="D://img/1_cut.jpg";IMOperation op = new IMOperation();op.gravity("center");op.addImage(srcImagePath);op.crop( 200,200,100,50);op.addImage(destImagePath);ImageCommand cmd  = new ConvertCmd();cmd.run(op, srcImagePath, destImagePath);}

最张裁剪效果:

image.png

注意事项

  1. -crop 200x200+100+50 结合 -gravity 'center'刚好可以把我们打上的水印裁剪出来;
  2. 裁剪出的图片在左右两边还是有一点红色边框,这个可能是计算有一两个像素误差。

图片加参数自动处理

有了以上的图片处理命令之后想要实现OSS ?x-oss-process=image/resize,w_200这样加参数处理图片可以使用Nginx+Lua来实现,集成了Lua模块的Nginx项目OpenResty

例如我们原始图片地址:

http://127.0.0.1/img/1.jpg

自动缩放图片尺寸:

http://127.0.0.1/img/1_400x400.jpg

  1. 下载安装 OpenResty - Download
  2. 下载安装LUA Release Lua for Windows v5.1.5-52 Released · rjpcomputing/luaforwindows · GitHub

Nginx配置引入Lua:

http {lua_package_path 'D:\software\openresty\lualib\\?.lua;;';lua_package_cpath 'D:\software\openresty\lualib\\?.so;;';
}

Nginx配置文件中可以写成这样:

 location ~ '/img/(\d+)_(\d+)x(\d+).jpg$' {root D:/img;set $img_root  "D:/img/img";set $fileName  ngx.arg[1];set $width  ngx.arg[2];set $height  ngx.arg[3];set $origin "${img_root}/${fileName}.jpg" ;set $file  "${img_root}/${fileName}_${width}x${height}.jpg";if (!-f $file) {rewrite_by_lua 'local command = "magick  "..ngx.var.origin.." -resize "..ngx.var.width.."x" ..ngx.var.height.." "..ngx.var.file;os.execute(command);';}}

当访问(http://127.0.0.1/img/1_400x400.jpg时可动态生成对应尺寸图片,类似OSS的功能:

image.png

生成的文件,当然我们还可以使用Lua+Redis缓存这里生成的文件,如果有CDN还可以配置CDN缓存这些文件,下次就可以从CDN缓存直接取对应尺寸的图片了,减少服务器处理图片的性能消耗。很多大厂不将这种图片处理下沉到CDN边缘节点,利用离用户最近CDN节点完成图片数据的处理,减少数据回源,从而减少中心服务器的性能消耗。

image.png

当然这个只是使用Nginx+Lua+GraphicsMagick来实现简单的图片裁剪功能,如果要实现阿里OSS图片处理要比这个复杂的多,不仅要解决大量文件存储高可要和自动扩容问题,还要解决高并发下图片裁剪的性能问题,们只是通过这个案例了解图片自动缩放的基本原理,原理看起来比较简单,想要做的好而且还要给全国那么多企业用,要保持高可用、高性能就比较有难度了。

总结

本文主要介绍了常用图片处理软件ImageMagick的使用,并通过命令和JAVA代码演示图片信息的获取、缩放、打水印、裁剪功能,在最后通过OpenResty+Lua实现类似OSS的自动图片缩放功能。

相关文章:

如何让你的图片服务也有类似OSS的图片处理功能

原文链接 前言 有自己机房的公司一般都有一套存储系统用于存储公司的图片、视频、音频、文件等数据&#xff0c;常见的存储系统有以NAS、FASTDFS为代表的传统文件存储&#xff0c;和以Minio为代表的对象存储系统&#xff0c;随着云服务的兴起很多公司逐渐将数据迁移到以阿里云…...

Oracle PL/SQL 类型(Type):索引表、嵌套表、变长数组、pipelined 管道

1、Oracle 新建员工表和部门表.sql。 集合类型 1、Oracle 集合是相同类型元素的组合&#xff0c;在集合中&#xff0c;使用唯一的下标来标识其中的每个元素&#xff0c;与 Java 的 List 很像。 2、常用集合方式&#xff1a; 类型语法下标元素个数初始值.extend能否存在DB中…...

Web 服务器 -【Tomcat】的简单学习

Tomcat1 简介1.1 什么是Web服务器 2 基本使用2.1 下载2.2 安装2.3 卸载2.4 启动2.5 关闭2.6 配置2.7 部署 3 Maven创建Web项目3.1 Web项目结构3.2 创建Maven Web项目 4 IDEA使用Tomcat4.1 集成本地Tomcat4.2 Tomcat Maven插件 Tomcat 1 简介 1.1 什么是Web服务器 Web服务器是…...

armbian使用1panel快速部署部署springBoot项目后端

文章目录 前言环境准备实现步骤第一步&#xff1a;Armbian安装1panel第二步&#xff1a;安装数据库第三步&#xff1a;查看数据库容器重要信息【重要】查看容器所在的网络查看容器连接地址 第四步&#xff1a;项目配置和打包第五步:构建项目镜像 前言 这里只是简单记录部署spr…...

Streamlit 讲解专栏(八):图像、音频与视频魔法

文章目录 1 前言2 st.image&#xff1a;嵌入图像内容2.1 图像展示与描述2.2 调整图像尺寸2.3 使用本地文件或URL 3 st.audio&#xff1a;嵌入音频内容3.1 播放音频文件3.2 生成音频数据播放 4 st.video&#xff1a;嵌入视频内容4.1 播放视频文件4.2 嵌入在线视频 5 结语&#x…...

python使用装饰器记录方法耗时

思路 python使用修饰器记录方法耗时&#xff0c;目的是每当方法执行完后&#xff0c;可以记录该方法耗时&#xff0c;而不需要在每个方法的执行前后&#xff0c;去创建一个临时变量&#xff0c;来记录耗时。 方式一&#xff08;不推荐&#xff09;&#xff1a; 在每个方法的…...

JavaWeb课程学习--Day01

HTML 建立css文件&#xff1a; css使用方式&#xff1a; <span>...</span>无语意包裹标签 css中的三种选择器&#xff1a; 注意&#xff1a;播放视音频时要留出播放空间 盒子模型&#xff1a; 表格标签&#xff1a; 以上表格&#xff1a; 表单标签&#xff1a; 表…...

Spring Boot单元测试使用MockBean注解向Service注入Mock对象

1. 背景介绍 我们在测试时有一个Service&#xff0c;我们需要测试Service&#xff0c;但Service内部依赖ServiceA、ServiceB&#xff0c;此时我们希望Mock ServiceA&#xff0c;ServiceB 注入真实对象。 class Service {private ServiceA A;private ServiceB B;public int me…...

Java中使用instanceof判断对象类型

记录&#xff1a;470 场景&#xff1a;Java中使用instanceof判断对象类型。例如在解析JSON字符串转换为指定类型时&#xff0c;先判断类型&#xff0c;再定向转换。在List<Object>中遍历Object时&#xff0c;先判断类型&#xff0c;再定向转换。 版本&#xff1a;JDK 1…...

postman测试后端增删改查

目录 一、本文介绍 二、准备工作 &#xff08;一&#xff09;新建测试 &#xff08;二&#xff09;默认url路径查看方法 三、增删改查 &#xff08;一&#xff09;查询全部 &#xff08;二&#xff09;增加数据 &#xff08;三&#xff09;删除数据 &#xff08;四&…...

根据源码,模拟实现 RabbitMQ - 通过 SQLite + MyBatis 设计数据库(2)

目录 一、数据库设计 1.1、数据库选择 1.2、环境配置 1.3、建库建表接口实现 1.4、封装数据库操作 1.5、针对 DataBaseManager 进行单元测试 一、数据库设计 1.1、数据库选择 MySQL 是我们最熟悉的数据库&#xff0c;但是这里我们选择使用 SQLite&#xff0c;原因如下&am…...

1、基于 CentOS 7 构建 LVS-DR 群集。 2、配置nginx负载均衡

一、基于CentOS7和、构建LVS-DR群集 准备四台虚拟机 ip作用192.168.27.150客户端192.168.27.151LVS192.168.27.152RS192.168.27.152RS 关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld安装ifconfig yum install net-tools.x86_64 -y1、DS上 1.1 配置LVS虚拟IP …...

android 如何分析应用的内存(十七)——使用MAT查看Android堆

android 如何分析应用的内存&#xff08;十七&#xff09;——使用MAT查看Android堆 前一篇文章&#xff0c;介绍了使用Android profiler中的memory profiler来查看Android的堆情况。 如Android 堆中有哪些对象&#xff0c;这些对象的引用情况是什么样子的。 可是我们依然面临…...

Spring 使用注解储存对象

文章目录 前言存储 Bean 对象五大注解五大注解示例配置包扫描路径读取bean的示例 方法注解 Bean Bean 命名规则重命名 Bean 前言 通过在 spring-config 中添加bean的注册内容&#xff0c;我们已经可以实现基本的Spring读取和存储对象的操作了&#xff0c;但在操作中我们发现读…...

一、初始 Spring MVC

文章目录 一、回顾 MVC 模式二、初始 Spring MVC2.1 Spring MVC 核心组件2.1.1 前端控制器&#xff08;DispatcherServlet&#xff09;2.1.2 处理器映射器&#xff08;HandlerMapping&#xff09;2.1.3 处理器适配器&#xff08;HandlerAdapter&#xff09;2.1.3 后端控制器&am…...

《爬虫》爬取页面图片并保存

爬虫 前言代码效果 简单的爬取图片 前言 这几天打算整理与迁移一下博客。因为 CSDN 的 Markdown 编辑器很好用 &#xff0c;所以全部文章与相关图片都保存在 CSDN。而且 CSDN 支持一键导出自己的文章为 markdown 文件。但导出的文件中图片的连接依旧是 url 连接。为了方便将图…...

【项目部署】JavaScript解析JSON解析报错Unexpected token xxx is not valid JSON

问题背景 这个报错发生在之前部署的一个前后端分离的项目中。后端使用的Spring Boot&#xff0c;前端使用的JavaScript&#xff0c;前后端交互使用Thymeleaf框架。 现象 项目组的另一个小伙伴说&#xff0c;突然有个页面打不开了&#xff0c;整个页面全空白。我F12打开浏览器…...

做接口测试如何上次文件

在日常工作中&#xff0c;经常有上传文件功能的测试场景&#xff0c;因此&#xff0c;本文介绍两种主流编写上传文件接口测试脚本的方法。 首先&#xff0c;要知道文件上传的一般原理&#xff1a;客户端根据文件路径读取文件内容&#xff0c;将文件内容转换成二进制文件流的格式…...

Java SPI机制详解-01

1. 概述 SPI&#xff08;Service Provider Interface&#xff09;&#xff0c;是 Java 6 引入了一个内置功能&#xff0c;实现服务提供发现和加载机制&#xff0c;使之与特定接口的匹配。 SPI 机制的核心思想就是 解耦 &#xff0c;将装配的控制权移到程序之外&#xff0c;这…...

由浅入深C系列六:C中实现字符串trim的功能

C中实现字符串trim的功能 简介设计思路代码实现运行效果 简介 一个项目中&#xff0c;需要用c语言实现对字符串中的字定字符进行过滤并从字符串的删除&#xff0c;查询了C语言的基本库&#xff0c;没有发现有这样的函数&#xff0c;于是发挥程序员的主观能力性&#xff0c;自力…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...