从 JPEG 解析图像大小

发布于 2024-09-30 09:30:17 字数 173 浏览 2 评论 0原文

我想知道是否有一种便宜的方法可以在加载字节数组后获取 JPEG 的宽度和高度。

我知道 JpegBitmapDecoder 可以获取 JPEG 的像素宽度和高度,但它也会加载大量信息,我认为这将是一项昂贵的操作。

是否有另一种方法可以从字节数组中获取宽度和高度而不对其进行解码?

谢谢

I was wondering if there was an inexpensive way to get the width and height of a JPEG after loading an array of bytes.

I know JpegBitmapDecoder can get the JPEG's pixel width and height but it loads alot of information as well, which I assume would be an expensive operation.

Is there another way to get the width and height from the array of bytes without decoding it?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

注定孤独终老 2024-10-07 09:30:17

由于某种未知的原因,我没有去睡觉,而是去做这件事。

这里有一些代码可以以最小的存储需求解决这个问题。

void Main()
{
    var filePath=@"path\to\my.jpg";
    var bytes=File.ReadAllBytes(filePath);
    var dimensions=GetJpegDimensions(bytes);
    //or
    //var dimensions=GetJpegDimensions(filePath);
    Console.WriteLine(dimensions);
}
public static Dimensions GetJpegDimensions(byte[] bytes)
{
    using(var ms=new MemoryStream(bytes))
    {
        return GetJpegDimensions(ms);
    }
}
public static Dimensions GetJpegDimensions(string filePath)
{
    using(var fs=File.OpenRead(filePath))
    {
        return GetJpegDimensions(fs);
    }
}
public static Dimensions GetJpegDimensions(Stream fs)
{
    if(!fs.CanSeek) throw new ArgumentException("Stream must be seekable");
    long blockStart;
    var buf = new byte[4];
    fs.Read(buf, 0, 4);
    if(buf.SequenceEqual(new byte[]{0xff, 0xd8, 0xff, 0xe0}))
    {
        blockStart = fs.Position;
        fs.Read(buf, 0, 2);
        var blockLength = ((buf[0] << 8) + buf[1]);
        fs.Read(buf, 0, 4);
        if(Encoding.ASCII.GetString(buf, 0, 4) == "JFIF" 
            && fs.ReadByte() == 0)
        {
            blockStart += blockLength;
            while(blockStart < fs.Length)
            {
                fs.Position = blockStart;
                fs.Read(buf, 0, 4);
                blockLength = ((buf[2] << 8) + buf[3]);
                if(blockLength >= 7 && buf[0] == 0xff && buf[1] == 0xc0)
                {
                    fs.Position += 1;
                    fs.Read(buf, 0, 4);
                    var height = (buf[0] << 8) + buf[1];
                    var width = (buf[2] << 8) + buf[3];
                    return new Dimensions(width, height);
                }
                blockStart += blockLength + 2;
            }
        }
    }
    return null;
}

public class Dimensions
{
    private readonly int width;
    private readonly int height;
    public Dimensions(int width, int height)
    {
        this.width = width;
        this.height = height;
    }
    public int Width
    {
        get{return width;}
    }
    public int Height
    {
        get{return height;}
    }
    public override string ToString()
    {
        return string.Format("width:{0}, height:{1}", Width, Height);
    }
}

For some unknown reason, instead of going to bed, I went to work on this.

Here's some code that solves this with minimal storage requirements.

void Main()
{
    var filePath=@"path\to\my.jpg";
    var bytes=File.ReadAllBytes(filePath);
    var dimensions=GetJpegDimensions(bytes);
    //or
    //var dimensions=GetJpegDimensions(filePath);
    Console.WriteLine(dimensions);
}
public static Dimensions GetJpegDimensions(byte[] bytes)
{
    using(var ms=new MemoryStream(bytes))
    {
        return GetJpegDimensions(ms);
    }
}
public static Dimensions GetJpegDimensions(string filePath)
{
    using(var fs=File.OpenRead(filePath))
    {
        return GetJpegDimensions(fs);
    }
}
public static Dimensions GetJpegDimensions(Stream fs)
{
    if(!fs.CanSeek) throw new ArgumentException("Stream must be seekable");
    long blockStart;
    var buf = new byte[4];
    fs.Read(buf, 0, 4);
    if(buf.SequenceEqual(new byte[]{0xff, 0xd8, 0xff, 0xe0}))
    {
        blockStart = fs.Position;
        fs.Read(buf, 0, 2);
        var blockLength = ((buf[0] << 8) + buf[1]);
        fs.Read(buf, 0, 4);
        if(Encoding.ASCII.GetString(buf, 0, 4) == "JFIF" 
            && fs.ReadByte() == 0)
        {
            blockStart += blockLength;
            while(blockStart < fs.Length)
            {
                fs.Position = blockStart;
                fs.Read(buf, 0, 4);
                blockLength = ((buf[2] << 8) + buf[3]);
                if(blockLength >= 7 && buf[0] == 0xff && buf[1] == 0xc0)
                {
                    fs.Position += 1;
                    fs.Read(buf, 0, 4);
                    var height = (buf[0] << 8) + buf[1];
                    var width = (buf[2] << 8) + buf[3];
                    return new Dimensions(width, height);
                }
                blockStart += blockLength + 2;
            }
        }
    }
    return null;
}

public class Dimensions
{
    private readonly int width;
    private readonly int height;
    public Dimensions(int width, int height)
    {
        this.width = width;
        this.height = height;
    }
    public int Width
    {
        get{return width;}
    }
    public int Height
    {
        get{return height;}
    }
    public override string ToString()
    {
        return string.Format("width:{0}, height:{1}", Width, Height);
    }
}
倾其所爱 2024-10-07 09:30:17

几年前我读过一篇关于它的 CodeProject 文章:)
我不是 100% 确定它有多好,也没有亲自测试过,但作者绝对对它感到满意;他的测试也证明它比阅读整个图像要快得多,正如您所期望的:)

这是文章本身..希望这是您所需要的!
http://www.codeproject.com/KB/cs/ReadingImageHeaders.aspx
您正在寻找的代码片段从这里开始:
http://www.codeproject.com/KB/cs/ReadingImageHeaders.aspx#premain3

UPD:另外,请检查底部的评论。尤其是最后一个(顶部)评论。可能有助于使其更加通用

此外,可以在此处获取更深入的高级信息:< a href="http://www.codeproject.com/KB/graphics/iptc.aspx" rel="nofollow">http://www.codeproject.com/KB/graphics/iptc.aspx

I've read a CodeProject article about it a couple years back :)
I'm not 100% sure how good it is, and haven't tested it myself, but the author's definitely happy with it; also his tests prove it's a LOT faster than reading the whole image, as you'd expect :)

Here's the article itself.. Hope it's what you need!
http://www.codeproject.com/KB/cs/ReadingImageHeaders.aspx
The piece of code you're looking for starts about here:
http://www.codeproject.com/KB/cs/ReadingImageHeaders.aspx#premain3

UPD: Also, check the comments in the bottom.. Especially the last (top) one there.. Might be useful to make it more generic

Also, more in-depth, advanced info can be picked up here: http://www.codeproject.com/KB/graphics/iptc.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文