原文链接:https://blog.csdn.net/flj135792468/article/details/107963280?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-8&spm=1001.2101.3001.4242

读取图片流前8个字节

Png图片 8字节:89 50 4E 47 0D 0A 1A 0A = [1]:P[2]:N[3]:G

Jpg图片 2字节:FF D8

Gif图片 6字节:47 49 46 38 39|37 61 = G I F 8 9 7 a

Bmp图片 2字节:42 4D

根据字节判断所属是什么类型

public class FileUtility
{
public enum ImageType
{
Null,
Png,
Jpg,
Gif,
Bmp
}

/// <summary>
/// 获取图片格式
/// </summary>
private static ImageType GetImageType(byte[] bytes)
{
byte[] header = new byte[8];
Array.Copy(bytes, header, header.Length);
ImageType type = ImageType.Null;
//读取图片文件头8个字节
//Png图片 8字节:89 50 4E 47 0D 0A 1A 0A = [1]:P[2]:N[3]:G
if (header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47 &&
header[4] == 0x0D && header[5] == 0x0A && header[6] == 0x1A && header[7] == 0x0A)
{
type = ImageType.Png;
}
//Jpg图片 2字节:FF D8
else if (header[0] == 0xFF && header[1] == 0xD8)
{
type = ImageType.Jpg;
}
//Gif图片 6字节:47 49 46 38 39|37 61 = GIF897a
else if (header[0] == 0x47 && header[1] == 0x49 && header[2] == 0x46 && header[3] == 0x38 &&
(header[4] == 0x39 || header[4] == 0x37) && header[5] == 0x61)
{
type = ImageType.Gif;
}
//Bmp图片 2字节:42 4D
else if (header[0] == 0x42 && header[1] == 0x4D)
{
type = ImageType.Bmp;
}
return type;
}

private static byte[] _header = null;
private static byte[] _buffer = null;

public static void FileInfo(string filePath, out byte[] bytes, out Vector2 size)
{
size = Vector2.zero;
FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
stream.Seek(0, SeekOrigin.Begin);
bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);

ImageType imageType = GetImageType(bytes);
switch (imageType)
{
case ImageType.Png:
{
stream.Seek(0, SeekOrigin.Begin);
_header = new byte[8];
stream.Read(_header, 0, 8);
stream.Seek(8, SeekOrigin.Current);

_buffer = new byte[8];
stream.Read(_buffer, 0, _buffer.Length);

Array.Reverse(_buffer, 0, 4);
Array.Reverse(_buffer, 4, 4);

size.x = BitConverter.ToInt32(_buffer, 0);
size.y = BitConverter.ToInt32(_buffer, 4);
}
break;
case ImageType.Jpg:
{
stream.Seek(0, SeekOrigin.Begin);
_header = new byte[2];
stream.Read(_header, 0, 2);
//段类型
int type = -1;
int ff = -1;
//记录当前读取的位置
long ps = 0;
//逐个遍历所以段,查找SOFO段
do
{
do
{
//每个新段的开始标识为oxff,查找下一个新段
ff = stream.ReadByte();
if (ff < 0) //文件结束
{
return;
}
} while (ff != 0xff);

do
{
//段与段之间有一个或多个oxff间隔,跳过这些oxff之后的字节为段标识
type = stream.ReadByte();
} while (type == 0xff);

//记录当前位置
ps = stream.Position;
switch (type)
{
case 0x00:
case 0x01:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
break;
case 0xc0: //SOF0段(图像基本信息)
case 0xc2: //JFIF格式的 SOF0段
{
//找到SOFO段,解析宽度和高度信息
//跳过2个自己长度信息和1个字节的精度信息
stream.Seek(3, SeekOrigin.Current);

//高度 占2字节 低位高位互换
size.y = stream.ReadByte() * 256;
size.y += stream.ReadByte();
//宽度 占2字节 低位高位互换
size.x = stream.ReadByte() * 256;
size.x += stream.ReadByte();
return;
}
default: //别的段都跳过
//获取段长度,直接跳过
ps = stream.ReadByte() * 256;
ps = stream.Position + ps + stream.ReadByte() - 2;
break;
}
if (ps + 1 >= stream.Length) //文件结束
{
return;
}
stream.Position = ps; //移动指针
} while (type != 0xda); // 扫描行开始
}
break;
case ImageType.Gif:
{
stream.Seek(0, SeekOrigin.Begin);
_header = new byte[6];
stream.Read(_header, 0, 6);

_buffer = new byte[4];
stream.Read(_buffer, 0, _buffer.Length);

size.x = BitConverter.ToInt16(_buffer, 0);
size.y = BitConverter.ToInt16(_buffer, 2);
}
break;
case ImageType.Bmp:
{
stream.Seek(0, SeekOrigin.Begin);
_header = new byte[2];
stream.Read(_header, 0, 2);
//跳过16个字节
stream.Seek(16, SeekOrigin.Current);
//bmp图片的宽度信息保存在第 18-21位 4字节
//bmp图片的高度度信息保存在第 22-25位 4字节
_buffer = new byte[8];
stream.Read(_buffer, 0, _buffer.Length);

size.x = BitConverter.ToInt32(_buffer, 0);
size.y = BitConverter.ToInt32(_buffer, 4);
}
break;
default:
break;
}

stream.Close();
stream.Dispose();
}

}

Unity 使用IO流获取PNG/JPG/GIF/BMP的宽高【转】的更多相关文章

  1. IO流-获取指定目录下文件夹和文件对象【File类】

    一.运用File类实现获取指定目录下文件夹和文件对象 1.File类 2.方法: 获取文件绝对路径 :getAbsolutePath 案例: import java.io.File; /** * 获取 ...

  2. Android如何在初始化的时候获取加载的布局的宽高

    在自定义ListView中,需要将下拉刷新的View在初始化的时候设置padding隐藏起来,这时就要在初始化的时候获得要加载的布局View的高度. private View headView; he ...

  3. js获取图片信息(二)-----js获取img的height、width宽高值为0

    首先,创建一个图片对象: var oImg= new Image(); oImg.src = "apple.jpg"; 然后我们打印一下图片的信息: console.log(oIm ...

  4. [转]ASP.NET如何获取上传图片尺寸(是指宽高)

    1.采用客户端javascript可以取得图片大小 <input id="FileUpload" type="file" size="27&qu ...

  5. JavaScript(获取或设置html元素的宽,高,坐标),确定和判断鼠标是否在元素内部,二级导航菜单鼠标离开样式问题解决

    设置: document.getElementById('id').style.width=value    document.getElementById('id').style.height=va ...

  6. Java IO流题库

    一.    填空题 Java IO流可以分为   节点流   和处理流两大类,其中前者处于IO操作的第一线,所有操作必须通过他们进行. 输入流的唯一目的是提供通往数据的通道,程序可以通过这个通道读取数 ...

  7. JavaEE基础(二十一)/IO流

    1.IO流(字符流FileReader) 1.字符流是什么 字符流是可以直接读写字符的IO流 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出. 2 ...

  8. IO流作业

    IO流作业 一.    填空题 Java IO流可以分为    字节流          和处理流两大类,其中前者处于IO操作的第一线,所有操作必须通过他们进行. 输入流的唯一目的是提供通往数据的通道 ...

  9. day21<IO流+&FIle递归>

    IO流(字符流FileReader) IO流(字符流FileWriter) IO流(字符流的拷贝) IO流(什么情况下使用字符流) IO流(字符流是否可以拷贝非纯文本的文件) IO流(自定义字符数组的 ...

  10. Java 基础(四)| IO 流之使用文件流的正确姿势

    为跳槽面试做准备,今天开始进入 Java 基础的复习.希望基础不好的同学看完这篇文章,能掌握泛型,而基础好的同学权当复习,希望看完这篇文章能够起一点你的青涩记忆. 一.什么是 IO 流? 想象一个场景 ...

随机推荐

  1. Qt界面设计--侧边栏隐藏和滑出

    在日常项目中,界面布局上经常使用到侧边栏的方式,在侧边栏放置控件进行复合使用,可以实现子功能界面的隐藏和滑出,效果展示如下: 界面控件很简单,主界面QWidget,侧边栏也用一个QWidget和一个按 ...

  2. 01-逻辑仿真工具VCS使用

    1 逻辑仿真工具VCS的使用 在书写完成RTL代码之后,确保自己书写的代码和自己想要的逻辑是一致的. VCS是synopsys公司下的的仿真工具. 1 VCS仿真过程 编译-->仿真--> ...

  3. VSCode 创建flutter项目和运行、调试、热更新项目

    1.创建--在終端輸入命令 flutter create 项目名 2.普通运行--在终端输入命令 flutter run 3.打开你的虚拟机或者是连上手机等待页面加载 4.普通運行情況下修改代碼后想要 ...

  4. JUC并发编程

    什么是JUC java.util.concurrent* public class Test1 { public static void main(String[] args) { //获取处理器核数 ...

  5. java入门与进阶P-2.3

    判断 if语句 一个基本的if语句由一个关键字if开头,跟上在括号里的表示条件的逻辑表达式, 然后是一对大括号"{}"之间的若干条语句.如果表示条件的逻辑表达式的结果为true,那 ...

  6. 深度复盘-重启 etcd 引发的异常

    作者信息: 唐聪.王超凡,腾讯云原生产品中心技术专家,负责腾讯云大规模 TKE 集群和 etcd 控制面稳定性.性能和成本优化工作. 王子勇,腾讯云专家级工程师, 腾讯云计算产品技术服务专家团队负责人 ...

  7. Timer的定时调度函数schedule的四种用法

    schedule的四种用法 schedule(task,time) task-所安排的任务  time-执行任务的时间 作用:在时间等于或者超过time的时候执行且仅执行一次 import java. ...

  8. drf-jwt、simplejwt的使用

    1.接口文档 # 前后端分离 -我们做后端,写接口 -前端做前端,根据接口写app,pc,小程序 -作为后端来讲,我们很清楚,比如登录接口 /api/v1/login/---->post---- ...

  9. 【亲妈教学】配置Gzip压缩,含前后端步骤

    前言 在使用 vite 进行项目打包时,默认已经帮我们做了一些优化工作,比如代码的压缩,分包等等. 除此之外,我们还有一些可选的优化策略,比如使用 CDN ,开启 Gzip 压缩等.本文会介绍在 vi ...

  10. 【TS】class类和接口

    class可以用来做数据的存储与回显,能将页面的数据分离出来并提取到class内,函数也可以抽离到class,实例化class进行调用.ts中的class类与js的class类基本相同,不同点在于ts ...