前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >简单易用的图像解码库介绍 —— stb_image

简单易用的图像解码库介绍 —— stb_image

作者头像
音视频开发进阶
发布于 2019-06-03 04:41:11
发布于 2019-06-03 04:41:11
4.2K10
代码可运行
举报
运行总次数:0
代码可运行

说到图像解码库,最容易想起的就是 libpnglibjpeg 这两个老牌图像解码库了。

libpnglibjpeg 分别各自对应 pngjpeg 两种图像格式。这两种格式的区别如下:

png 支持透明度,无损压缩的图片格式,能在保证不失真的情况下尽可能压缩图像文件的大小,因此图像质量高,在一些贴纸应用中也大部分用的是 png 图片。

jpg 不支持透明度,有损压缩的图片格式,有损压缩会使得原始图片数据质量下载,也因此它占用的内存小,在网页应用中加速速度快。

要想在工程中同时解码 pngjpeg 格式图片,就必须同时引用这两种库,而且还得经过一系列编译步骤才行。

在这里,介绍一个简单易用的图像库:stb_image 。Github 地址为:https://github.com/nothings/stb ,目前已经有了 9600+ Star 。它的使用非常简单,看看 README 可能你就会了。

看看它的源码,你会发现全是 .h 头文件。这就是它的强大之处了,仅需在工程中加入头文件就可以解析图像了(实际上是函数实现等内容都放在头文件了而已)。

重点关注如下三个头文件:

  • stb_image.h
    • 用于图像加载
  • stb_image_write.h
    • 用于写入图像文件
  • stb_image_resize.h
    • 用于改变图像尺寸

下面就开始实践吧,先给出一个完整的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1#include <iostream>
 2
 3#define STB_IMAGE_IMPLEMENTATION
 4#include "stb_image.h"
 5#define STB_IMAGE_WRITE_IMPLEMENTATION
 6#include "stb_image_write.h"
 7#define STB_IMAGE_RESIZE_IMPLEMENTATION
 8#include "stb_image_resize.h"
 9#include <string>
10#include <stdio.h>
11#include <stdlib.h>
12#include <vector>
13
14using namespace std;
15
16int main() {
17    std::cout << "Hello, STB_Image" << std::endl;
18
19    string inputPath = "/Users/glumes/Pictures/input.png";
20    int iw, ih, n;
21
22    // 加载图片获取宽、高、颜色通道信息
23    unsigned char *idata = stbi_load(inputPath.c_str(), &iw, &ih, &n, 0);
24
25    int ow = iw / 2;
26    int oh = ih / 2;
27    auto *odata = (unsigned char *) malloc(ow * oh * n);
28
29    // 改变图片尺寸
30    stbir_resize(idata, iw, ih, 0, odata, ow, oh, 0, STBIR_TYPE_UINT8, n, STBIR_ALPHA_CHANNEL_NONE, 0,
31                 STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP,
32                 STBIR_FILTER_BOX, STBIR_FILTER_BOX,
33                 STBIR_COLORSPACE_SRGB, nullptr
34    );
35
36    string outputPath = "/Users/glumes/Pictures/output.png";
37    // 写入图片
38    stbi_write_png(outputPath.c_str(), ow, oh, n, odata, 0);
39
40    stbi_image_free(idata);
41    stbi_image_free(odata);
42    return 0;
43}

这个例子很简单也很全面,主要就是加载了一张图片,并将它的宽高都缩小一倍,并保存缩小后图片。

stb_image

首先是调用 stbi_load 方法去加载图像数据,并获取相关信息。传入的参数除了图片文件地址,还有宽、高、颜色通道信息的引用。

变量 n 就代表图片的颜色通道值,通常有如下的情况:

  • 1 : 灰度图
  • 2 : 灰度图加透明度
  • 3 : 红绿蓝 RGB 三色图
  • 4 : 红绿蓝加透明度 RGBA 图

返回的结果就是图片像素数据的指针了。

stbi_load 不仅仅支持 png 格式,把上面例子中的图片改成 jpg 格式后缀的依旧可行。

它支持的所有格式如下:

  • png
  • jpg
  • tga
  • bmp
  • psd
  • gif
  • hdr
  • pic

格式虽多,不过一般用到 png 和 jpg 就好了。

除了从文件加载图片,stb_image 还支持从内存中加载图片,通过该方法 stbi_load_from_memory ,在后续文章中会用到它的。

加载完图片之后,stb_image 还提供了相应的释放方法 stbi_image_free,实际上就是把 free 封装了一下而已。

sbt_image_resize

加载完图片像素数据之后,就可以通过 stbir_resize 方法改变图片的尺寸。

stbir_resize 方法参数有很多:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1STBIRDEF int stbir_resize(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
2                             void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
3                             stbir_datatype datatype,
4                             int num_channels, int alpha_channel, int flags,
5                             // stb 中提供了多种模式,但是修改后并没有见很明显的效果
6                             stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
7                             stbir_filter filter_horizontal,  stbir_filter filter_vertical,
8                             stbir_colorspace space, void *alloc_context)
9

stbir_edgestbir_filter 类型的参数,stb_image_resize 提供了多种类型:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1typedef enum
 2{
 3    STBIR_EDGE_CLAMP   = 1,
 4    STBIR_EDGE_REFLECT = 2,
 5    STBIR_EDGE_WRAP    = 3,
 6    STBIR_EDGE_ZERO    = 4,
 7} stbir_edge;
 8
 9typedef enum
10{
11    STBIR_FILTER_DEFAULT      = 0,  // use same filter type that easy-to-use API chooses
12    STBIR_FILTER_BOX          = 1,  // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios
13    STBIR_FILTER_TRIANGLE     = 2,  // On upsampling, produces same results as bilinear texture filtering
14    STBIR_FILTER_CUBICBSPLINE = 3,  // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque
15    STBIR_FILTER_CATMULLROM   = 4,  // An interpolating cubic spline
16    STBIR_FILTER_MITCHELL     = 5,  // Mitchell-Netrevalli filter with B=1/3, C=1/3
17} stbir_filter;

但实际上调整不同类型组合得到的图片并没有太多的变化 ┑( ̄Д  ̄)┍。

真正有用的可能还是前面那几个参数,指定了要将图片缩放后的宽高数据。

stb_image_write

最后就是调用 stbi_write_png 方法将像素数据写入文件中,除此之外,stb_image_write 还提供了 stbi_write_jpg 方法来保存 jpg 格式图片。

根据两者格式的不同,方法调用的参数也是不一样的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
2
3int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
4

总结

以上就是关于 stb_image 图像解码库的小介绍。

总的来说,它还是挺简单易用的,在平常做一些 Demo 以及需要快速实现、验证功能的情况下都可以考虑考虑。

但是在一些大型的项目中,还是要深思熟虑一些,从性能方面考虑,它肯定不如老牌的图像解码库了,像 libjpeg-turbo 解码用到了 NEON 这样 SIMD (单指令流多数据流)的操作,才是大型项目的首选了。

参考

关于 stb_image 在 Android 中的使用实践,可以参考我的项目:

https://github.com/glumes/InstantGLSL

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 纸上浅谈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
brew里面根本没有这个包
brew里面根本没有这个包
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
使用kubeadm工具箱创建kubernetes1.9集群
版权声明:本文为木偶人shaon原创文章,转载请注明原文地址,非常感谢。 https://blog.csdn.net/wh211212/article/details/79209551
shaonbean
2019/05/26
5610
K8S(V1.10.1)高可用集群超详细版本(包含Dashboard、Rancher)
六台主机配置、停防火墙、关闭Swap、关闭Selinux、设置内核、安装依赖包、配置ntp(配置完后建议重启一次)
全栈程序员站长
2022/06/29
3330
K8S(V1.10.1)高可用集群超详细版本(包含Dashboard、Rancher)
Centos7安装K8S集群环境
kubelet不支持SELinux, 这里需要将SELinux设置为permissive模式
用户1392128
2024/01/08
1.6K0
部署k8s集群(k8s集群搭建详细实践版)
Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
zjiekou
2022/11/12
21.8K5
国内 CentOS 7 安装 K8S v1.29.2(CRI:containerd),通过安装 K8S,了解 K8S 的核心概念
通过安装 K8S,了解 K8S 的核心概念:控制面、CRI、CNI、Deployment、Service、sandbox 等,本文不仅包含安装流程,而且包含丰富的 Troubeshooting 实战,以及解释这背后发生了什么。
SRE扫地僧
2024/04/27
3.4K0
国内 CentOS 7 安装 K8S v1.29.2(CRI:containerd),通过安装 K8S,了解 K8S 的核心概念
kubernetes-1:使用kubeadm搭建K8S单master节点集群
现在官方推荐的是kubespray,但也是基于kubeadm;除此之外,还有kind,minikube,但是并不试用于部署生产级别集群。
千里行走
2019/07/03
2.1K0
k8s学习一:使用kubeadm安装k8s
在学习整个k8s之前,先想办法搭建个k8s出现成果,然后根据这个成果进行深入学习,才会让人有学习的动力,本文将记录自己的安装k8s教程
仙士可
2022/09/13
6760
k8s学习一:使用kubeadm安装k8s
CentOS7.7部署k8s(1 master + 2 node)
VMware创建三个vm,规格2cpu 4G mem 200G disk,一个NAT网卡
后端云
2020/04/22
1.4K0
CentOS7.7部署k8s(1 master + 2 node)
K8s 安装
如果你的节点上面有科学上网的工具,可以忽略这一步,我们需要提前将所需的gcr.io上面的镜像下载到节点上面,当然前提条件是你已经成功安装了docker。
分母为零
2019/07/04
1.8K0
K8s 安装
利用GPU服务器实现边云协同推理
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
鳄鱼儿
2024/05/22
2530
利用GPU服务器实现边云协同推理
附003.Kubeadm部署Kubernetes
Kubeadm 是一个工具,它提供了 kubeadm init 以及 kubeadm join 这两个命令作为快速创建 kubernetes 集群的最佳实践。
木二
2019/07/01
8400
手动搭建K8S环境
在三台机器上均安装docker、kubeadm、kubelet,在master节点安装kubectl
谢公子
2022/11/29
1K0
手动搭建K8S环境
公网环境搭建 k8s 集群
笔者利用手头几台云服务器搭建 k8s 集群,由于这几台云服务属于不同的云服务厂商,无法搭建局域网环境的 k8s 集群,故笔者搭建的是公网环境的 k8s 集群,在此做个记录, 以下均在 ubuntu 20.04 环境下进行
菜菜cc
2022/11/15
3.4K0
公网环境搭建 k8s 集群
kubernetes炼气期之k8s平台快速搭建
环境说明 功能名称 IP 配置 k8s-master 192.168.10.231 4c8g k8s-node1 192.168.10.232 8c16g K8s-node2 192.168.10.233 8c16g k8s-node3 192.168.10.234 8c16g k8s-node4 192.168.10.235 8c16g 环境初始化 更新环境 yum update -y yum install -y wget vim net-tools epel-release 关闭filewal
公众号: 云原生生态圈
2020/06/15
5220
kubeadm安装Kubernetes1.11集群
9、设置内核(可不设置) echo "* soft nofile 65536" >> /etc/security/limits.conf echo "* hard nofile 65536" >> /etc/security/limits.conf echo "* soft nproc 65536" >> /etc/security/limits.conf echo "* hard nproc 65536" >> /etc/security/limits.conf echo "* soft memlock unlimited" >> /etc/security/limits.conf echo "* hard memlock unlimited" >> /etc/security/limits.conf
菲宇
2019/06/12
1.8K0
kubeadm安装Kubernetes1.11集群
CentOS7系统上Kubernetes集群搭建
在自己的Mac系统里面利用Parallels Desktop创建3台虚拟机,具体信息如下:
chengcheng222e
2021/11/04
1.7K0
Kubernetes 使用kubeadm创建集群
注意,安装docker时,需要指Kubenetes支持的版本(参见如下),如果安装的docker版本过高导致,会提示以下问题
授客
2021/09/26
3.4K0
kubeadm实现K8S的HA
(1)k8s各节点SSH设置免密登录 所有节点用root用户操作,全部设置免密登陆,不做细分。
用户1499526
2019/07/15
1.2K0
CentOS7.7部署k8s(3 master + 3 node + 1 client)
VMware创建7个vm,规格2cpu 2G mem 200G disk,一个NAT网卡
后端云
2020/04/22
2.3K0
CentOS7.7部署k8s(3 master + 3 node + 1 client)
K8S学习笔记之二进制的方式创建一个Kubernetes集群
Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,尝试Kubernetes或日常开发的用户使用。不能用于生产环境。
Jetpropelledsnake21
2019/03/20
1.3K0
K8S学习笔记之二进制的方式创建一个Kubernetes集群
推荐阅读
相关推荐
使用kubeadm工具箱创建kubernetes1.9集群
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文