تحديد نوع ملف الصورة
-
09-06-2019 - |
سؤال
أقوم بتنزيل بعض الصور من خدمة لا تتضمن دائمًا نوع محتوى ولا توفر امتدادًا للملف الذي أقوم بتنزيله (لا تسأل).
ما هي أفضل طريقة لتحديد تنسيق الصورة في .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
نصائح أخرى
تقوم جميع تنسيقات الصور بتعيين وحدات البايت الأولية الخاصة بها على قيمة معينة:
- جبغ: 0xFF 0xD8
- بي إن جي: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
- جيف: 'ز' 'أنا' 'ف'
ابحث عن "تنسيق ملف 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
تمت الإضافة:الفعلية هيكل الملف لبابوا نيو غينيا.