سؤال

أقوم بتنزيل بعض الصور من خدمة لا تتضمن دائمًا نوع محتوى ولا توفر امتدادًا للملف الذي أقوم بتنزيله (لا تسأل).

ما هي أفضل طريقة لتحديد تنسيق الصورة في .NET؟

يحتاج التطبيق الذي يقرأ هذه الصور التي تم تنزيلها إلى أن يكون له امتداد ملف مناسب وإلا ينفجر كل شيء.

هل كانت مفيدة؟

المحلول

ربما تكون الطريقة الأسهل هي استخدام Image.FromFile() ثم استخدام خاصية RawFormat، حيث أنها تعرف بالفعل عن البتات السحرية في الرؤوس للتنسيقات الأكثر شيوعًا، مثل هذا:

Image i = Image.FromFile("c:\\foo");
if (System.Drawing.Imaging.ImageFormat.Jpeg.Equals(i.RawFormat)) 
    MessageBox.Show("JPEG");
else if (System.Drawing.Imaging.ImageFormat.Gif.Equals(i.RawFormat))
    MessageBox.Show("GIF");
//Same for the rest of the formats

نصائح أخرى

تقوم جميع تنسيقات الصور بتعيين وحدات البايت الأولية الخاصة بها على قيمة معينة:

ابحث عن "تنسيق ملف jpg" مع استبدال jpg بتنسيقات الملفات الأخرى التي تحتاج إلى تحديدها.

كما يوصي غارث، هناك قاعدة بيانات لهذه "الأرقام السحرية" إظهار نوع الملف للعديد من الملفات.إذا كان عليك اكتشاف الكثير من أنواع الملفات المختلفة، فمن المفيد البحث فيها للعثور على المعلومات التي تحتاجها.إذا كنت بحاجة إلى توسيع هذا ليشمل العديد والعديد من أنواع الملفات، فاطلع على ما يرتبط بها أمر الملف الذي ينفذ المحرك لاستخدام قاعدة البيانات بشكل صحيح (وهو أمر غير تافه بالنسبة للعديد من تنسيقات الملفات، ويكاد يكون عملية إحصائية)

-آدم

يمكنك استخدام التعليمات البرمجية أدناه دون الرجوع إلى System.Drawing والإنشاء غير الضروري لصورة الكائن.كما يمكنك استخدام أليكس الحل حتى بدون تيار ومرجع System.IO.

public enum ImageFormat
{
    bmp,
    jpeg,
    gif,
    tiff,
    png,
    unknown
}

public static ImageFormat GetImageFormat(Stream stream)
{
    // see http://www.mikekunz.com/image_file_header.html
    var bmp = Encoding.ASCII.GetBytes("BM");     // BMP
    var gif = Encoding.ASCII.GetBytes("GIF");    // GIF
    var png = new byte[] { 137, 80, 78, 71 };    // PNG
    var tiff = new byte[] { 73, 73, 42 };         // TIFF
    var tiff2 = new byte[] { 77, 77, 42 };         // TIFF
    var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg
    var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon

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

    if (bmp.SequenceEqual(buffer.Take(bmp.Length)))
        return ImageFormat.bmp;

    if (gif.SequenceEqual(buffer.Take(gif.Length)))
        return ImageFormat.gif;

    if (png.SequenceEqual(buffer.Take(png.Length)))
        return ImageFormat.png;

    if (tiff.SequenceEqual(buffer.Take(tiff.Length)))
        return ImageFormat.tiff;

    if (tiff2.SequenceEqual(buffer.Take(tiff2.Length)))
        return ImageFormat.tiff;

    if (jpeg.SequenceEqual(buffer.Take(jpeg.Length)))
        return ImageFormat.jpeg;

    if (jpeg2.SequenceEqual(buffer.Take(jpeg2.Length)))
        return ImageFormat.jpeg;

    return ImageFormat.unknown;
}

يشير آدم إلى الاتجاه الصحيح تمامًا.

إذا كنت تريد معرفة كيفية ذلك يشعر تقريبا أي ملف, ، انظر إلى قاعدة البيانات الموجودة خلف ملف file الأمر على جهاز UNIX أو Linux أو Mac OS X.

file يستخدم قاعدة بيانات "الأرقام السحرية" - تلك البايتات الأولية التي ذكرها آدم - لاستشعار نوع الملف. man file سيخبرك بمكان العثور على قاعدة البيانات على جهازك، على سبيل المثال. /usr/share/file/magic. man magic سوف أقول لك ذلك شكل.

يمكنك إما كتابة رمز الكشف الخاص بك بناءً على ما تراه في قاعدة البيانات، أو استخدام المكتبات المعدة مسبقًا (على سبيل المثال. بيثون السحر)، أو - إذا كنت كذلك حقًا المغامرة — تنفيذ إصدار .NET من libmagic.لم أتمكن من العثور على واحد، وآمل أن يتمكن عضو آخر من الإشارة إليه.

إذا لم يكن لديك جهاز UNIX، فستبدو قاعدة البيانات كما يلي:

# PNG [Portable Network Graphics, or "PNG's Not GIF"] images
# (Greg Roelofs, newt@uchicago.edu)
# (Albert Cahalan, acahalan@cs.uml.edu)
#
# 137 P N G \r \n ^Z \n [4-byte length] H E A D [HEAD data] [HEAD crc] ...
#
0       string          \x89PNG         PNG image data,
>4      belong          !0x0d0a1a0a     CORRUPTED,
>4      belong          0x0d0a1a0a
>>16    belong          x               %ld x
>>20    belong          x               %ld,
>>24    byte            x               %d-bit
>>25    byte            0               grayscale,
>>25    byte            2               \b/color RGB,
>>25    byte            3               colormap,
>>25    byte            4               gray+alpha,
>>25    byte            6               \b/color RGBA,
#>>26   byte            0               deflate/32K,
>>28    byte            0               non-interlaced
>>28    byte            1               interlaced
1       string          PNG             PNG image data, CORRUPTED

# GIF
0       string          GIF8            GIF image data
>4      string          7a              \b, version 8%s,
>4      string          9a              \b, version 8%s,
>6      leshort         >0              %hd x
>8      leshort         >0              %hd
#>10    byte            &0x80           color mapped,
#>10    byte&0x07       =0x00           2 colors
#>10    byte&0x07       =0x01           4 colors
#>10    byte&0x07       =0x02           8 colors
#>10    byte&0x07       =0x03           16 colors
#>10    byte&0x07       =0x04           32 colors
#>10    byte&0x07       =0x05           64 colors
#>10    byte&0x07       =0x06           128 colors
#>10    byte&0x07       =0x07           256 colors

حظ سعيد!

هناك طريقة برمجية لتحديد نوع الصورة MIMETYPE.

هناك فئة System.Drawing.Imaging.ImageCodecInfo.

هذه الفئة لها خصائص نوع التمثيل الصامت و معرف التنسيق.كما أن لها طريقة GetImageEncoders والتي تعيد مجموعة من كافة برامج ترميز الصور.من السهل إنشاء قاموس لأنواع mime المفهرسة بواسطة معرف التنسيق.

فصل System.Drawing.Image لديك ممتلكات تنسيق خام من النوع System.Drawing.Imaging.ImageFormat التي لها ممتلكات دليل وهو ما يعادل الممتلكات معرف التنسيق من صنف System.Drawing.Imaging.ImageCodecInfo, وهذا هو المفتاح لأخذ MIMETYPE من القاموس.

مثال:

طريقة ثابتة لإنشاء قاموس لأنواع التمثيل الصامت

static Dictionary<Guid, string> GetImageFormatMimeTypeIndex()
{
  Dictionary<Guid, string> ret = new Dictionary<Guid, string>();

  var encoders = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();

  foreach(var e in encoders)
  {
    ret.Add(e.FormatID, e.MimeType);
  }

  return ret;
}

يستخدم:

Dictionary<Guid, string> mimeTypeIndex = GetImageFormatMimeTypeIndex();

FileStream imgStream = File.OpenRead(path);
var image = System.Drawing.Image.FromStream(imgStream);
string mimeType = mimeTypeIndex[image.RawFormat.Guid];

حاول تحميل الدفق إلى System.IO.BinaryReader.

ستحتاج بعد ذلك إلى الرجوع إلى المواصفات الخاصة بكل تنسيق صورة تحتاجه، وتحميل بايت الرأس بايت تلو الآخر للمقارنة بالمواصفات.على سبيل المثال هنا مواصفات PNG

تمت الإضافة:الفعلية هيكل الملف لبابوا نيو غينيا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top