自动优化图片

1.压缩jpeg:

接到这个任务,我首先找到了jpegoptim(https://github.com/tjko/jpegoptim),然后编译,实验了一下:

jpegoptim.exe -o input.jpg -S 90% -d dest_path 或 jpegoptim.exe -o input.jpg -m 90 -d dest_path

两者有区别的。-S表示压缩到原文件的百分之多少,-m则对应jpg的质量

很明显,这个只能指定压缩,和任务相去甚远,不同的jpg没办法自动压缩啊。

知乎有人只招说用SNR(图片信噪比)比对,大概落在30+就可以了。

然后就是通过二分法实现一个很挫的方案(伪代码)

src_image=load(from_file);
max_p=100;
mix_p=1;
mid_p=(max_p+ mix_p)/2;
ok_file = NULL;
while(1)
{run(“jpegoptim.exe -o from.jpg -S %d%% -d dest_path”,mid_p);   //在dest_path目录下有一个与原文件同名jpgto_jpg_file = dest_path/file_name(from.jpg);cmp_image = load(to_jpg_file);Snr = snr_fun(src_image, cmp_image);if(Snr>=30){max_p = mid_p;ok_file = to_jpg_file;}else{mix_p= mid_p;}mid_p=(max_p+ mix_p)/2;
}
if(ok_file)
{copy_file(ok_file,out_file);printf(“OK\n”);
}
else
{printf(“FAILED\n”);
}

其中snr_fun就是图像信噪比,说白了就是原图-比较图=差值图,然后10*lg(原图图的均方差/差值图的均方差),大概这样吧,有些会写20*lg(原图图的均方差/差值图的均方差),无所谓,最终要得到合理的经验值进行比对,具体的实现可以自行搜索一下。

好了,上面的伪代码是能实现自动优化jpg的,问题是效率相当低下,最差的需要7-8次,大概要10到20秒,烂大街的东西估计很快有人丢西红柿的。

好吧,我去翻了一下jpegoptim的代码,发现它实现-S的方案,其实是通过内存编码比对最终尺寸,那么为什么我不自己直接实现呢?于是先通过二分法先来个内存编码解码+SNR检查,获取最优的质量值(0-100),然后通过最优质量一次性调用“jpegoptim.exe -o input.jpg -m 质量值 -d dest_path”输出,不到2秒,还能接受,先用着吧。伪代码大概是这样:

src_image=load(from_file);
max_p=100;
mix_p=1;
mid_p=(max_p+ mix_p)/2;
ok_file = NULL;
percent = 100;
while(1)
{cmp_image_buffer = jpeg_zip(src_image, mid_p);cmp_image = load_memory(cmp_image_buffer);Snr = snr_fun(src_image, cmp_image);if(Snr>=30){max_p = mid_p;percent = mid_p;}else{mix_p= mid_p;}mid_p=(max_p+ mix_p)/2;
}
run("jpegotim.exe -o input.jpg -m %d", percent);

2.png压缩:

拿到pngquant(https://github.com/kornelski/pngquant)项目编译一下,调用“pngquant.exe --quality 10-97 -f -o output.png input.png”就可以得到优化的png。如果直接调用libpngquant.lib也可以实现,抄作业(https://github.com/ImageOptim/libimagequant/blob/f54d2f1a3e1cf728e17326f4db0d45811c63f063/example.c)。我比对了一下,使用loadpng输出结果与pngquant直接输出的结果有差异,pngquant压缩更多,具体原因我没继续查,有兴趣的可以看看源码。

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

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

相关文章

升级node版本后vue2的项目node-sass、sass-loader安装报错(14.x升级到16.x)

node升级到16.x版本后,对应的node-sass需要升级到^6.0.0,此时sass-loader的版本需要升级到10.2.0以上 ,具体对应版本规则可参考链接: https://github.com/webpack-contrib/sass-loader/releases?page3 vue2通过vue/cli创建的项目&#xff0…

学会RabbitMQ的延迟队列,提高消息处理效率

系列文章目录 手把手教你,本地RabbitMQ服务搭建(windows) 消息队列选型——为什么选择RabbitMQ RabbitMQ灵活运用,怎么理解五种消息模型 RabbitMQ 能保证消息可靠性吗 推或拉? RabbitMQ 消费模式该如何选择 死信是什么…

C++初阶——函数重载

前言:C中除了可以在不同的命名空间中使用同名函数,还有一种支持在同一个作用域中同名函数的方式——函数重载。 函数重载 一.什么是函数重载?二.函数重载的3种规则三.特殊情况 一.什么是函数重载? C允许同样同一作用域中声明几个功…

Ubuntu 20.04 安装 Stable Diffusionn

步骤 1:安装 wget、git、Python3 和 Python3虚拟环境(如果已安装可忽略这步骤) sudo apt install wget git python3 python3-venv步骤 2:克隆 SD 项目到本地 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webu…

Vscode python调试和运行环境设置

Vscode python调试和运行环境设置 文章目录 Vscode python调试和运行环境设置前言一、是否为每次运行python程序都要选择环境烦恼二、是否为python程序调试不能进标准/第三方库而烦恼 前言 一、是否为每次运行python程序都要选择环境烦恼 在.vscode文件夹(没有就自己造一个)下…

Flink之SideOutput(数据分流)

Flink在早期版本有一个split算子用来做数据分流使用的,但是在flink-1.12开始这个API就已经被删除了,在1.12版本以后我们是通过process算子来做数据分流的,这里就介绍一下如何使用prodess进行数据分流. 代码 import org.apache.flink.api.common.typeinfo.TypeInformation; im…

【网络编程】实现一个简单多线程版本TCP服务器(附源码)

TCP多线程 🌵预备知识🎄 Accept函数🌲字节序转换函数🌳listen函数 🌴代码🌱Log.hpp🌿Makefile☘️TCPClient.cc🍀TCPServer.cc🎍 util.hpp 🌵预备知识 &…

RabbitMQ - 简单案例

目录 0.引用 1.Hello world 2.轮训分发消息 2.1 抽取工具类 2.2 启动两个工作线程接受消息 2.4 结果展示 3.消息应答 3.1 自动应答 3.2 手动消息应答的方法 3.3 消息自动重新入队 3.4 消息手动应答代码 4.RabbitMQ 持久化 4.1 队列如何实现持久化 4.2 消息实现持久化 5.不…

对 Promise 的理解

Promise 是异步编程的一种解决方案,它是一个对象,可以获取异步 操作的消息,他的出现大大改善了异步编程的困境,避免了地狱回调, 它比传统的解决方案回调函数和事件更合理和更强大。 所谓 Promise,简单说就…

算法通关村——透彻理解二分查找

1. 循环法 public static int binarySearch(int[] arr, int low, int high, int target) {while (low < high) {// 这样写主要是避免溢出的情况&#xff0c;以及>>优先级小于&#xff0c;避免出现死循环int mid low ((high - low) >> 1);if (arr[mid] target…

7.1 动手实现AlexNet

AlexNet引入了dropput层 代码 import torch from torch import nn from d2l import torch as d2lnet nn.Sequential(# 样本数为1,通道数为96,11x11的卷积核,步幅为4&#xff0c;减少输出的高度和深度。 LeNet的通道数才6&#xff0c;此处96&#xff0c;为什么要增加这么多通…

MIT 6.830数据库系统 -- lab six

MIT 6.830数据库系统 -- lab six 项目拉取引言steal/no-force策略redo log与undo log日志格式和检查点 开始回滚练习1&#xff1a;LogFile.rollback() 恢复练习2&#xff1a;LogFile.recover() 测试结果疑问点分析 项目拉取 原项目使用ant进行项目构建&#xff0c;我已经更改为…

在python中使用nvidia的VPF库对RTSP流进行硬解码并使用opencv进行显示

解码并处理视频流的多线程应用 随着视频处理技术的不断发展&#xff0c;越来越多的应用需要对视频流进行解码和处理。在本文中&#xff0c;我们将介绍一个基于Python的多线程应用程序&#xff0c;该应用程序可以解码并处理多个RTSP视频流&#xff0c;同时利用GPU加速&#xff0…

use gnustep objective-c

first app #import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {NSAutoreleasePool *pool [NSAutoreleasePool new];NSLog("first start");[pool drain];return 0; }tech 专注于概念&#xff0c;而不是迷失在语言技术细节中编程语言…

微服务技术栈(1.0)

微服务技术栈 认识微服务 单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署 优点&#xff1a; 架构简单部署成本低 缺点&#xff1a; 耦合度高 分布式架构 分布式架构&#xff1a;根据业务功能对系统进行拆分&#xff0c…

npm四种下载方式的区别

npm install moduleName 命令 安装模块到项目node_modules目录下。 不会将模块依赖写入devDependencies或dependencies 节点。 运行 npm install 初始化项目时不会下载模块。npm install -g moduleName 命令 安装模块到全局&#xff0c;不会在项目node_modules目录中保存模块包…

如何在 Spring Boot 中集成日志框架 SLF4J、Log4j

文章目录 具体步骤附录 笔者的操作环境&#xff1a; Spring Cloud Alibaba&#xff1a;2022.0.0.0-RC2 Spring Cloud&#xff1a;2022.0.0 Spring Boot&#xff1a;3.0.2 Nacos 2.2.3 Maven 3.8.3 JDK 17.0.7 IntelliJ IDEA 2022.3.1 (Ultimate Edition) 具体步骤 因为 …

Java课题笔记~ 使用 Spring 的事务注解管理事务(掌握)

通过Transactional 注解方式&#xff0c;可将事务织入到相应 public 方法中&#xff0c;实现事务管理。 Transactional 的所有可选属性如下所示&#xff1a; propagation&#xff1a;用于设置事务传播属性。该属性类型为 Propagation 枚举&#xff0c; 默认值为 Propagation.R…

【学习日记】【FreeRTOS】链表结构体及函数详解

写在前面 本文主要是对于 FreeRTOS 中链表相关内容的详细解释&#xff0c;代码大部分参考了野火FreeRTOS教程配套源码&#xff0c;作了一小部分修改。 一、结构体定义 主要包含三种结构体&#xff1a; 普通节点结构体结尾节点&#xff08;mini节点&#xff09;结构体链表结…

awk经典实战、正则表达式

目录 1.筛选给定时间范围内的日志 2.统计独立IP 案列 需求 代码 运行结果 3.根据某字段去重 案例 运行结果 4.正则表达式 1&#xff09;认识正则 2&#xff09;匹配字符 3&#xff09;匹配次数 4&#xff09;位置锚定&#xff1a;定位出现的位置 5&#xff09;分组…