原文链接: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. [cocos2d-x]捕鱼达人炮台射击角度的旋转实现

    话不多说,先上图,下面是实现代码(在后面会具体讲解实现过程): //第一步:将炮台的坐标转换为世界坐标下的坐标点 CCPoint location = this->getParent()-> ...

  2. Java集合 - ConcurrentHashMap

    介绍 ConcurrentHashMap 技术是为了解决问题而生的,ConcurrentHashMap 解决了多个线程同时操作一个 HashMap 时,可能出现的内部问题.当多个线程同时操作一个 Ha ...

  3. ng + zorro angular表格横纵向合并,横向目前是手动,纵向是自动合并,微调后可适配三大框架使用

    表格横纵向合并,可以看一下代码编写之前和之后的样式,先上图~~ 表格页面文件.html <h1>正常表格</h1> <nz-table #colSpanTable [nz ...

  4. 【学习笔记】珂朵莉树(ODT)

    珂朵莉树 \(\tt 0x00\) 起源 起源于 CodeForces 的一题 CF896C,当时出题人提供了这种做法,在随机数据下均摊复杂度比较优秀. 正统名字好像叫颜色段均摊,由于题目也得名于 \ ...

  5. ubuntu20.04 gnome桌面系统添加开机自启动GUI程序

    在终端执行 gnome-session-properties,点击添加自己的脚本或执行文件,便可以在用户登录后自动执行.

  6. 带你读AI论文丨S&P21 Survivalism: Living-Off-The-Land 经典离地攻击

    摘要:这篇文章属于系统分析类的文章,通过详细的实验分析了离地攻击(Living-Off-The-Land)的威胁性和流行度,包括APT攻击中的利用及示例代码论证. 本文分享自华为云社区<[论文阅 ...

  7. 注解 @RequestMapping @RequestParam @RequestBody

    @RequestMapping  @RequestParam @RequestBody @PathVariable与@RequestParam的区别 1) 相同点A. 作用位置相同:都是直接修饰方法参 ...

  8. Redis避坑指南:为什么要有分布式锁?

    作者:京东保险 张江涛 1.为什么要有分布式锁? JUC提供的锁机制,可以保证在同一个JVM进程中同一时刻只有一个线程执行操作逻辑: 多服务多节点的情况下,就意味着有多个JVM进程,要做到这样,就需要 ...

  9. Visual Studio 集成了.NET 升级助手插件

    .NET团队2023年2月16日在官方博客上发布了名为".NET Upgrade Assistant"的全新 Visual Studio 扩展,帮助开发人员升级.NET 应用程序. ...

  10. SpringMVC的文件、数据校验(Vaildator、Annotation JSR-303)

    SpringMvc的文件上传下载: 文件上传 单文件上传 1.底层使用的是Apache fileupload组件进行上传的功能,Springmvc 只是对其进行了封装,简化开发, pom.xml &l ...