รับขนาดภาพโดยไม่ต้องอ่านทั้งไฟล์


104

มีวิธีที่ถูกในการรับขนาดของภาพ (jpg, png, ... ) หรือไม่? โดยเฉพาะอย่างยิ่งฉันต้องการบรรลุสิ่งนี้โดยใช้เฉพาะไลบรารีคลาสมาตรฐาน (เนื่องจากข้อ จำกัด ในการโฮสต์) ฉันรู้ว่ามันควรจะค่อนข้างง่ายในการอ่านส่วนหัวของรูปภาพและแยกวิเคราะห์ด้วยตัวเอง แต่ดูเหมือนว่าจะมีอะไรแบบนี้อยู่แล้ว นอกจากนี้ฉันได้ตรวจสอบแล้วว่าโค้ดต่อไปนี้อ่านภาพทั้งหมด (ซึ่งฉันไม่ต้องการ):

using System;
using System.Drawing;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Image img = new Bitmap("test.png");
            System.Console.WriteLine(img.Width + " x " + img.Height);
        }
    }
}

มันจะช่วยได้ถ้าคุณเจาะจงมากขึ้นในคำถามที่เหมาะสม แท็กบอกฉันว่า. net และ c # และคุณต้องการไลบรารีมาตรฐาน แต่ข้อ จำกัด การโฮสต์ที่คุณกล่าวถึงคืออะไร?
wnoise

หากคุณสามารถเข้าถึง System.Windows.Media.Imaging namespace (ใน WPF) โปรดดูคำถาม SO นี้: stackoverflow.com/questions/784734/…
Charlie

คำตอบ:


106

ทางออกที่ดีที่สุดของคุณคือหาห้องสมุดที่ผ่านการทดสอบมาอย่างดี อย่างไรก็ตามคุณบอกว่าเป็นเรื่องยากดังนั้นนี่คือการหลีกเลี่ยงโค้ดที่ยังไม่ผ่านการทดสอบซึ่งส่วนใหญ่ควรใช้งานได้กับหลายกรณี:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;

namespace ImageDimensions
{
    public static class ImageHelper
    {
        const string errorMessage = "Could not recognize image format.";

        private static Dictionary<byte[], Func<BinaryReader, Size>> imageFormatDecoders = new Dictionary<byte[], Func<BinaryReader, Size>>()
        {
            { new byte[]{ 0x42, 0x4D }, DecodeBitmap},
            { new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
            { new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
            { new byte[]{ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
            { new byte[]{ 0xff, 0xd8 }, DecodeJfif },
        };

        /// <summary>
        /// Gets the dimensions of an image.
        /// </summary>
        /// <param name="path">The path of the image to get the dimensions of.</param>
        /// <returns>The dimensions of the specified image.</returns>
        /// <exception cref="ArgumentException">The image was of an unrecognized format.</exception>
        public static Size GetDimensions(string path)
        {
            using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(path)))
            {
                try
                {
                    return GetDimensions(binaryReader);
                }
                catch (ArgumentException e)
                {
                    if (e.Message.StartsWith(errorMessage))
                    {
                        throw new ArgumentException(errorMessage, "path", e);
                    }
                    else
                    {
                        throw e;
                    }
                }
            }
        }

        /// <summary>
        /// Gets the dimensions of an image.
        /// </summary>
        /// <param name="path">The path of the image to get the dimensions of.</param>
        /// <returns>The dimensions of the specified image.</returns>
        /// <exception cref="ArgumentException">The image was of an unrecognized format.</exception>    
        public static Size GetDimensions(BinaryReader binaryReader)
        {
            int maxMagicBytesLength = imageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;

            byte[] magicBytes = new byte[maxMagicBytesLength];

            for (int i = 0; i < maxMagicBytesLength; i += 1)
            {
                magicBytes[i] = binaryReader.ReadByte();

                foreach(var kvPair in imageFormatDecoders)
                {
                    if (magicBytes.StartsWith(kvPair.Key))
                    {
                        return kvPair.Value(binaryReader);
                    }
                }
            }

            throw new ArgumentException(errorMessage, "binaryReader");
        }

        private static bool StartsWith(this byte[] thisBytes, byte[] thatBytes)
        {
            for(int i = 0; i < thatBytes.Length; i+= 1)
            {
                if (thisBytes[i] != thatBytes[i])
                {
                    return false;
                }
            }
            return true;
        }

        private static short ReadLittleEndianInt16(this BinaryReader binaryReader)
        {
            byte[] bytes = new byte[sizeof(short)];
            for (int i = 0; i < sizeof(short); i += 1)
            {
                bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte();
            }
            return BitConverter.ToInt16(bytes, 0);
        }

        private static int ReadLittleEndianInt32(this BinaryReader binaryReader)
        {
            byte[] bytes = new byte[sizeof(int)];
            for (int i = 0; i < sizeof(int); i += 1)
            {
                bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte();
            }
            return BitConverter.ToInt32(bytes, 0);
        }

        private static Size DecodeBitmap(BinaryReader binaryReader)
        {
            binaryReader.ReadBytes(16);
            int width = binaryReader.ReadInt32();
            int height = binaryReader.ReadInt32();
            return new Size(width, height);
        }

        private static Size DecodeGif(BinaryReader binaryReader)
        {
            int width = binaryReader.ReadInt16();
            int height = binaryReader.ReadInt16();
            return new Size(width, height);
        }

        private static Size DecodePng(BinaryReader binaryReader)
        {
            binaryReader.ReadBytes(8);
            int width = binaryReader.ReadLittleEndianInt32();
            int height = binaryReader.ReadLittleEndianInt32();
            return new Size(width, height);
        }

        private static Size DecodeJfif(BinaryReader binaryReader)
        {
            while (binaryReader.ReadByte() == 0xff)
            {
                byte marker = binaryReader.ReadByte();
                short chunkLength = binaryReader.ReadLittleEndianInt16();

                if (marker == 0xc0)
                {
                    binaryReader.ReadByte();

                    int height = binaryReader.ReadLittleEndianInt16();
                    int width = binaryReader.ReadLittleEndianInt16();
                    return new Size(width, height);
                }

                binaryReader.ReadBytes(chunkLength - 2);
            }

            throw new ArgumentException(errorMessage);
        }
    }
}

หวังว่าโค้ดจะค่อนข้างชัดเจน ในการเพิ่มรูปแบบไฟล์ใหม่คุณต้องเพิ่มimageFormatDecodersโดยมีคีย์เป็นอาร์เรย์ของ "magic bits" ซึ่งปรากฏที่จุดเริ่มต้นของไฟล์ทุกไฟล์ในรูปแบบที่กำหนดและค่าที่เป็นฟังก์ชันที่แยกขนาดออกจากสตรีม รูปแบบส่วนใหญ่เรียบง่ายพอตัวเหม็นจริงเพียง jpeg


6
เห็นด้วย JPEG แย่มาก Btw - หมายเหตุสำหรับผู้ที่ต้องการใช้รหัสนี้ในอนาคต: นี่ยังไม่ได้ทดสอบ ฉันได้ใช้หวีอย่างดีและนี่คือสิ่งที่ฉันพบ: รูปแบบ BMP มีรูปแบบส่วนหัว (แบบโบราณ) แบบอื่นโดยที่ขนาดเป็น 16 บิต ความสูงบวกสามารถเป็นลบได้ (วางเครื่องหมายแล้ว) สำหรับ JPEG - 0xC0 ไม่ใช่เฉพาะส่วนหัว โดยทั่วไป 0xC0 ถึง 0xCF ทั้งหมดยกเว้น 0xC4 และ 0xCC เป็นส่วนหัวที่ถูกต้อง (คุณสามารถรับได้อย่างง่ายดายใน JPG แบบอินเทอร์เลซ) และเพื่อให้สิ่งต่างๆสนุกยิ่งขึ้นความสูงสามารถเป็น 0 และระบุได้ในภายหลังในบล็อก 0xDC ดูw3.org/Graphics/JPEG/itu-t81.pdf
Vilx-

ปรับแต่งเมธอด DecodeJfif ด้านบนเพื่อขยายเดิม (marker == 0xC0) ตรวจสอบเพื่อยอมรับ 0xC1 และ 0xC2 ด้วย ส่วนหัวเริ่มต้นของเฟรมอื่น ๆ เหล่านี้ SOF1 และ SOF2 เข้ารหัสความกว้าง / ความสูงในตำแหน่งไบต์เดียวกัน SOF2 ค่อนข้างธรรมดา
Ryan Barton

4
คำเตือนมาตรฐาน: คุณไม่ควรเขียนthrow e;แต่เขียนthrow;แทน ความคิดเห็นเอกสาร XML ของคุณในวินาทีGetDimensionsยังแสดงpathแทนbinaryReader
Eregrith

1
นอกจากนี้ดูเหมือนว่ารหัสนี้ไม่ยอมรับ JPEG ที่เข้ารหัสในรูปแบบ EXIF ​​/ TIFF ซึ่งส่งออกโดยกล้องดิจิทัลจำนวนมาก รองรับเฉพาะ JFIF
cwills

2
System.Drawing.Image.FromStream (สตรีมเท็จเท็จ) จะให้ขนาดโดยไม่ต้องโหลดภาพทั้งหมดและใช้งานได้กับรูปภาพใด ๆ Net สามารถโหลดได้ เหตุใดโซลูชันที่ยุ่งเหยิงและไม่สมบูรณ์นี้จึงมีการโหวตเพิ่มขึ้นมากมายเกินความเข้าใจ
dynamichael

25
using (FileStream file = new FileStream(this.ImageFileName, FileMode.Open, FileAccess.Read))
{
    using (Image tif = Image.FromStream(stream: file, 
                                        useEmbeddedColorManagement: false,
                                        validateImageData: false))
    {
        float width = tif.PhysicalDimension.Width;
        float height = tif.PhysicalDimension.Height;
        float hresolution = tif.HorizontalResolution;
        float vresolution = tif.VerticalResolution;
     }
}

validateImageDataชุดfalseป้องกัน GDI + จากการดำเนินการวิเคราะห์ค่าใช้จ่ายของข้อมูลภาพจึงลดลงอย่างรุนแรงเวลาในการโหลด คำถามนี้ให้ความกระจ่างมากขึ้นในเรื่องนี้


1
ฉันใช้โซลูชันของคุณเป็นทรัพยากรสุดท้ายผสมกับโซลูชันของ ICR ด้านบน มีปัญหากับ JPEG และแก้ไขด้วยสิ่งนี้
Zorkind

2
ฉันเพิ่งพยายามนี้ในโครงการที่ผมได้มีการสอบถามขนาดของ 2000 + ภาพ (JPG และ png ส่วนใหญ่ขนาดผสมมาก) new Bitmap()และมันเป็นจริงได้เร็วกว่าวิธีแบบดั้งเดิมโดยใช้
AeonOfTime

1
คำตอบที่ดีที่สุด รวดเร็วสะอาดและมีประสิทธิภาพ
dynamichael

1
ฟังก์ชั่นนี้เหมาะสำหรับ windows แต่มันไม่ทำงานบน linux มันจะยังคงอ่านทั้งไฟล์บน linux (.net core 2.2)
zhengchun

21

คุณได้ลองใช้คลาส WPF Imaging แล้วหรือยัง? System.Windows.Media.Imaging.BitmapDecoderฯลฯ ?

ฉันเชื่อว่าความพยายามบางอย่างคือการตรวจสอบให้แน่ใจว่าตัวแปลงสัญญาณเหล่านั้นอ่านเฉพาะส่วนย่อยของไฟล์เพื่อกำหนดข้อมูลส่วนหัว มันคุ้มค่าที่จะตรวจสอบ


ขอบคุณ. ดูเหมือนจะสมเหตุสมผล แต่โฮสติ้งของฉันมี. NET 2
ม.ค. Zich

1
คำตอบที่ยอดเยี่ยม หากคุณได้รับการอ้างอิงถึง PresentationCore ในโครงการของคุณนี่คือวิธีที่จะไป
ojrac

ในการทดสอบหน่วยของฉันคลาสเหล่านี้ไม่ได้ทำงานได้ดีไปกว่า GDI ...
Nariman

ดังนั้นเพื่อให้ได้ขนาดภาพของ OP คุณจะใช้ BitmapDecoder ได้อย่างไร?
Chuck Savage

1
ดูคำถาม SO นี้: stackoverflow.com/questions/784734/…
Charlie

12

ฉันกำลังมองหาสิ่งที่คล้ายกันเมื่อไม่กี่เดือนก่อนหน้านี้ ฉันต้องการอ่านประเภทเวอร์ชันความสูงและความกว้างของรูปภาพ GIF แต่ไม่พบสิ่งที่เป็นประโยชน์ทางออนไลน์

โชคดีในกรณีของ GIF ข้อมูลที่จำเป็นทั้งหมดอยู่ใน 10 ไบต์แรก:

Type: Bytes 0-2
Version: Bytes 3-5
Height: Bytes 6-7
Width: Bytes 8-9

PNG มีความซับซ้อนกว่าเล็กน้อย (ความกว้างและความสูงคือ 4 ไบต์):

Width: Bytes 16-19
Height: Bytes 20-23

ดังที่ได้กล่าวไว้ข้างต้นwotsitเป็นเว็บไซต์ที่ดีสำหรับข้อกำหนดโดยละเอียดเกี่ยวกับรูปแบบภาพและข้อมูลแม้ว่าข้อกำหนดของ PNG ที่pnglibจะมีรายละเอียดมากกว่ามากก็ตาม อย่างไรก็ตามฉันคิดว่ารายการ Wikipedia ในรูปแบบPNGและGIFเป็นจุดเริ่มต้นที่ดีที่สุด

นี่คือรหัสเดิมของฉันสำหรับการตรวจสอบ GIF ฉันได้ตบบางอย่างสำหรับ PNG ด้วย:

using System;
using System.IO;
using System.Text;

public class ImageSizeTest
{
    public static void Main()
    {
        byte[] bytes = new byte[10];

        string gifFile = @"D:\Personal\Images&Pics\iProduct.gif";
        using (FileStream fs = File.OpenRead(gifFile))
        {
            fs.Read(bytes, 0, 10); // type (3 bytes), version (3 bytes), width (2 bytes), height (2 bytes)
        }
        displayGifInfo(bytes);

        string pngFile = @"D:\Personal\Images&Pics\WaveletsGamma.png";
        using (FileStream fs = File.OpenRead(pngFile))
        {
            fs.Seek(16, SeekOrigin.Begin); // jump to the 16th byte where width and height information is stored
            fs.Read(bytes, 0, 8); // width (4 bytes), height (4 bytes)
        }
        displayPngInfo(bytes);
    }

    public static void displayGifInfo(byte[] bytes)
    {
        string type = Encoding.ASCII.GetString(bytes, 0, 3);
        string version = Encoding.ASCII.GetString(bytes, 3, 3);

        int width = bytes[6] | bytes[7] << 8; // byte 6 and 7 contain the width but in network byte order so byte 7 has to be left-shifted 8 places and bit-masked to byte 6
        int height = bytes[8] | bytes[9] << 8; // same for height

        Console.WriteLine("GIF\nType: {0}\nVersion: {1}\nWidth: {2}\nHeight: {3}\n", type, version, width, height);
    }

    public static void displayPngInfo(byte[] bytes)
    {
        int width = 0, height = 0;

        for (int i = 0; i <= 3; i++)
        {
            width = bytes[i] | width << 8;
            height = bytes[i + 4] | height << 8;            
        }

        Console.WriteLine("PNG\nWidth: {0}\nHeight: {1}\n", width, height);  
    }
}

8

จากคำตอบจนถึงตอนนี้และการค้นหาเพิ่มเติมดูเหมือนว่าในไลบรารีคลาส. NET 2 จะไม่มีฟังก์ชันการทำงานสำหรับมัน เลยตัดสินใจเขียนของตัวเอง นี่คือเวอร์ชันคร่าวๆของมัน ในขณะนี้ฉันต้องการมันสำหรับ JPG เท่านั้น ดังนั้นคำตอบที่โพสต์โดย Abbas จะสมบูรณ์

ไม่มีการตรวจสอบข้อผิดพลาดหรือการตรวจสอบอื่น ๆ แต่ตอนนี้ฉันต้องการมันสำหรับงานที่ จำกัด และในที่สุดก็สามารถเพิ่มได้อย่างง่ายดาย ฉันทดสอบกับภาพจำนวนหนึ่งและมักจะไม่อ่านเพิ่มเติมว่า 6K จากรูปภาพ ฉันเดาว่ามันขึ้นอยู่กับจำนวนข้อมูล EXIF

using System;
using System.IO;

namespace Test
{

    class Program
    {

        static bool GetJpegDimension(
            string fileName,
            out int width,
            out int height)
        {

            width = height = 0;
            bool found = false;
            bool eof = false;

            FileStream stream = new FileStream(
                fileName,
                FileMode.Open,
                FileAccess.Read);

            BinaryReader reader = new BinaryReader(stream);

            while (!found || eof)
            {

                // read 0xFF and the type
                reader.ReadByte();
                byte type = reader.ReadByte();

                // get length
                int len = 0;
                switch (type)
                {
                    // start and end of the image
                    case 0xD8: 
                    case 0xD9: 
                        len = 0;
                        break;

                    // restart interval
                    case 0xDD: 
                        len = 2;
                        break;

                    // the next two bytes is the length
                    default: 
                        int lenHi = reader.ReadByte();
                        int lenLo = reader.ReadByte();
                        len = (lenHi << 8 | lenLo) - 2;
                        break;
                }

                // EOF?
                if (type == 0xD9)
                    eof = true;

                // process the data
                if (len > 0)
                {

                    // read the data
                    byte[] data = reader.ReadBytes(len);

                    // this is what we are looking for
                    if (type == 0xC0)
                    {
                        width = data[1] << 8 | data[2];
                        height = data[3] << 8 | data[4];
                        found = true;
                    }

                }

            }

            reader.Close();
            stream.Close();

            return found;

        }

        static void Main(string[] args)
        {
            foreach (string file in Directory.GetFiles(args[0]))
            {
                int w, h;
                GetJpegDimension(file, out w, out h);
                System.Console.WriteLine(file + ": " + w + " x " + h);
            }
        }

    }
}

ความกว้างและความสูงจะกลับกันเมื่อฉันลองสิ่งนี้
Jason Sturges

@JasonSturges คุณอาจต้องคำนึงถึงแท็ก Exif Orientation
Andrew Morton

3

ฉันทำสิ่งนี้สำหรับไฟล์ PNG

  var buff = new byte[32];
        using (var d =  File.OpenRead(file))
        {            
            d.Read(buff, 0, 32);
        }
        const int wOff = 16;
        const int hOff = 20;            
        var Widht =BitConverter.ToInt32(new[] {buff[wOff + 3], buff[wOff + 2], buff[wOff + 1], buff[wOff + 0],},0);
        var Height =BitConverter.ToInt32(new[] {buff[hOff + 3], buff[hOff + 2], buff[hOff + 1], buff[hOff + 0],},0);

1

ใช่คุณสามารถทำได้อย่างแน่นอนและรหัสจะขึ้นอยู่กับรูปแบบไฟล์ ฉันทำงานให้กับผู้จำหน่ายภาพ ( Atalasoft ) และผลิตภัณฑ์ของเรามี GetImageInfo () สำหรับตัวแปลงสัญญาณทุกตัวที่ทำขั้นต่ำในการค้นหาขนาดและข้อมูลอื่น ๆ ที่ง่ายต่อการรับข้อมูล

หากคุณต้องการม้วนของคุณเองฉันขอแนะนำให้เริ่มต้นด้วยwotsit.orgซึ่งมีข้อกำหนดโดยละเอียดสำหรับรูปแบบภาพทั้งหมดและคุณจะเห็นวิธีระบุไฟล์และข้อมูลที่สามารถพบได้

หากคุณพอใจที่จะทำงานกับ C คุณสามารถใช้ jpeglib ฟรีเพื่อรับข้อมูลนี้ได้เช่นกัน ฉันจะพนันได้เลยว่าคุณสามารถทำสิ่งนี้กับไลบรารี. NET ได้ แต่ฉันไม่รู้วิธี


ปลอดภัยหรือไม่ที่จะคิดว่าการใช้new AtalaImage(filepath).Widthสิ่งที่คล้ายกัน
drzaus


1
ภาพแรก (AtalaImage) อ่านภาพทั้งหมด - ภาพที่สอง (GetImageInfo) อ่านข้อมูลเมตาขั้นต่ำเพื่อรับองค์ประกอบของวัตถุข้อมูลภาพ
Lou Franco

0

อัปเดตคำตอบของ ICR เพื่อรองรับ jPegs & WebP แบบก้าวหน้าเช่นกัน :)

internal static class ImageHelper
{
    const string errorMessage = "Could not recognise image format.";

    private static Dictionary<byte[], Func<BinaryReader, Size>> imageFormatDecoders = new Dictionary<byte[], Func<BinaryReader, Size>>()
    {
        { new byte[] { 0x42, 0x4D }, DecodeBitmap },
        { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
        { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
        { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
        { new byte[] { 0xff, 0xd8 }, DecodeJfif },
        { new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
    };

    /// <summary>        
    /// Gets the dimensions of an image.        
    /// </summary>        
    /// <param name="path">The path of the image to get the dimensions of.</param>        
    /// <returns>The dimensions of the specified image.</returns>        
    /// <exception cref="ArgumentException">The image was of an unrecognised format.</exception>            
    public static Size GetDimensions(BinaryReader binaryReader)
    {
        int maxMagicBytesLength = imageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
        byte[] magicBytes = new byte[maxMagicBytesLength];
        for(int i = 0; i < maxMagicBytesLength; i += 1)
        {
            magicBytes[i] = binaryReader.ReadByte();
            foreach(var kvPair in imageFormatDecoders)
            {
                if(StartsWith(magicBytes, kvPair.Key))
                {
                    return kvPair.Value(binaryReader);
                }
            }
        }

        throw new ArgumentException(errorMessage, "binaryReader");
    }

    private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
    {
        for(int i = 0; i < thatBytes.Length; i += 1)
        {
            if(thisBytes[i] != thatBytes[i])
            {
                return false;
            }
        }

        return true;
    }

    private static short ReadLittleEndianInt16(BinaryReader binaryReader)
    {
        byte[] bytes = new byte[sizeof(short)];

        for(int i = 0; i < sizeof(short); i += 1)
        {
            bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte();
        }
        return BitConverter.ToInt16(bytes, 0);
    }

    private static int ReadLittleEndianInt32(BinaryReader binaryReader)
    {
        byte[] bytes = new byte[sizeof(int)];
        for(int i = 0; i < sizeof(int); i += 1)
        {
            bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte();
        }
        return BitConverter.ToInt32(bytes, 0);
    }

    private static Size DecodeBitmap(BinaryReader binaryReader)
    {
        binaryReader.ReadBytes(16);
        int width = binaryReader.ReadInt32();
        int height = binaryReader.ReadInt32();
        return new Size(width, height);
    }

    private static Size DecodeGif(BinaryReader binaryReader)
    {
        int width = binaryReader.ReadInt16();
        int height = binaryReader.ReadInt16();
        return new Size(width, height);
    }

    private static Size DecodePng(BinaryReader binaryReader)
    {
        binaryReader.ReadBytes(8);
        int width = ReadLittleEndianInt32(binaryReader);
        int height = ReadLittleEndianInt32(binaryReader);
        return new Size(width, height);
    }

    private static Size DecodeJfif(BinaryReader binaryReader)
    {
        while(binaryReader.ReadByte() == 0xff)
        {
            byte marker = binaryReader.ReadByte();
            short chunkLength = ReadLittleEndianInt16(binaryReader);
            if(marker == 0xc0 || marker == 0xc2) // c2: progressive
            {
                binaryReader.ReadByte();
                int height = ReadLittleEndianInt16(binaryReader);
                int width = ReadLittleEndianInt16(binaryReader);
                return new Size(width, height);
            }

            if(chunkLength < 0)
            {
                ushort uchunkLength = (ushort)chunkLength;
                binaryReader.ReadBytes(uchunkLength - 2);
            }
            else
            {
                binaryReader.ReadBytes(chunkLength - 2);
            }
        }

        throw new ArgumentException(errorMessage);
    }

    private static Size DecodeWebP(BinaryReader binaryReader)
    {
        binaryReader.ReadUInt32(); // Size
        binaryReader.ReadBytes(15); // WEBP, VP8 + more
        binaryReader.ReadBytes(3); // SYNC

        var width = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits width
        var height = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits height

        return new Size(width, height);
    }

}

-1

มันจะขึ้นอยู่กับรูปแบบไฟล์ โดยปกติพวกเขาจะระบุไว้ในไบต์ต้นของไฟล์ และโดยปกติแล้วการใช้งานการอ่านภาพที่ดีจะคำนึงถึงสิ่งนั้นด้วย ฉันไม่สามารถชี้ให้คุณเห็นสำหรับ. NET ได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.