Jordan Nash Ответов: 0

Проблема C# привязка тегов метаданных к списку для 0x5013 и 0x5014.


Привет,

Я хочу отобразить определенные метаданные в моем списке для выбранного изображения в моем средстве просмотра изображений, которого нет в этой библиотеке Asim Goheer, которую я использую. https://www.codeproject.com/Articles/11305/EXIFextractor-library-to-extract-EXIF-information?msg=5528243#xx5528243xx


ПРОБЛЕМА:

К сожалению, у меня возникли проблемы с реализацией новых тегов, которых не было в EXIFextractor.Метод BuildDB ().

Системы.Исключение NullReferenceException. Системы.Исключение NullReferenceException: Объекта
ссылка не установлена на экземпляр объекта.' bmp был равен нулю.

Это происходит после попытки я установил тег для

er2.setTag(0x5013,"Thumbnail Width");


в моей форме.
На самом деле это происходит с любым тегом. Я пытаюсь реализовать код как для 0x5014,"Высота миниатюры", так и для 0x5013,"ширина миниатюры".

Вот мой код для моей формы Windows, только этот код мой. Классы ниже, где написано Асим Гохир, спасибо.

Форма 1.

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web.UI;
    
    namespace PictureViewer
    {    
        public partial class Form1 : Form
        {
                	string _big_fileName;
                	int _counter = 0;
                	int _imageIndex;
                
                	#region Initializers
                	public Form1()
                	{
                	InitializeComponent();
                	}
                
                	//Displays larger instance of selected image in picture box.
                	private void lstImages_SelectedIndexChanged(object sender, EventArgs e)
                	{
                		//FOR i is less than the first image.
                		for (int i = 0; i < lstImages.SelectedItems.Count; i++)
                		{
                		//GET filename from listview and store in index.
                		_big_fileName = lstImages.SelectedItems[i].Text;
                		//Create larger instance of image.
                		pictureBox1.Image = Image.FromFile(_big_fileName);
                		//Fill panel to the width and height of picture box.
                		panel1.AutoScrollMinSize = new Size(pictureBox1.Image.Width, pictureBox1.Image.Height);
                		_imageIndex = lstImages.SelectedIndices[0];
                		loadImageMetaData();
                		}
                	}
                	#endregion Initializers
                
                	#region File Menu Events
                	private void mnuOpen_Click(object sender, EventArgs e)
                	{
                		loadImageList();
                		_imageIndex = 0;
                	}
                
                	#region Methods
                	private void loadImageList()
                	{
                		imageList1.Images.Clear();
                		lstImages.Clear();
                
                		oFD1.InitialDirectory = "C:\\";
                		oFD1.Title = "Open an Image File";
                		oFD1.Filter = "JPEGS|*.jpg|GIFS|*.gif|PNGS|*.png|BMPS|*.bmp";
                
                		//Open Dialog Box.
                		var oldResults = oFD1.ShowDialog();
                
                		if (oldResults == DialogResult.Cancel)
                		{
                			return;
                		}
                
                		try
                		{
                			//GET amount of filenames.
                			int num_of_files = oFD1.FileNames.Length;
                			//Store filenames in string array.
                			string[] arryFilePaths = new string[num_of_files];
                
                
                			//FOREACH filename in the file.
                			foreach (string single_file in oFD1.FileNames)
                			{
                				//ACCESS array using _counter to find file.
                				arryFilePaths[_counter] = single_file;
                				//CREATE image in memory and add image to image list.
                				imageList1.Images.Add(Image.FromFile(single_file));
                				_counter++;
                			}
                			//BIND image list to listview.
                			lstImages.LargeImageList = imageList1;
                
                
                			for (int i = 0; i < _counter; i++)
                			{
                				//DISPLAY filename and image from image index param.
                				lstImages.Items.Add(arryFilePaths[i], i);
                			}
                		}
                
                		catch (Exception ex)
                		{
                			MessageBox.Show("Error " + ex.Message);
                		}
                	}
                
                	private void loadImageMetaData()
                	{
                		lstImageMetaData.Items.Clear();
                		Encoding ascii = Encoding.ASCII;
                		EXIF.EXIFextractor er2 = new EXIF.EXIFextractor(_big_fileName, "","");
                		
                		foreach (Pair s in er2)
                		{
                			lstImageMetaData.Items.Add(s.First + " : " + s.Second);
                		}
                		lstImageMetaData.SelectedIndex = lstImageMetaData.Items.Count - 1;
                		er2.setTag(0x5013,"Thumbnail Width");
                	}
                	#endregion Methods
                }
    }


Ошибка заключается в этом методе
public void setTag(int id, int len, short type, byte [] data)
            {
                PropertyItem p = CreatePropertyItem(type,id,len,data);
                this.bmp.SetPropertyItem( p );
                buildDB(this.bmp.PropertyItems);
            }
На этой самой линии.
this.bmp.SetPropertyItem(p);


Вот весь код для EXIFextractor.
using System;
using System.Text;
using System.Collections;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
using System.Web.UI;

    namespace EXIF
    {
        /// <summary>
        /// EXIFextractor Class
        ///
        /// </summary>
        public class EXIFextractor : IEnumerable
        {
            /// <summary>
            /// Get the individual property value by supplying property name
            /// These are the valid property names :
            ///
            /// "Exif IFD"
            /// "Gps IFD"
            /// "New Subfile Type"
            /// "Subfile Type"
            /// "Image Width"
            /// "Image Height"
            /// "Bits Per Sample"
            /// "Compression"
            /// "Photometric Interp"
            /// "Thresh Holding"
            /// "Cell Width"
            /// "Cell Height"
            /// "Fill Order"
            /// "Document Name"
            /// "Image Description"
            /// "Equip Make"
            /// "Equip Model"
            /// "Strip Offsets"
            /// "Orientation"
            /// "Samples PerPixel"
            /// "Rows Per Strip"
            /// "Strip Bytes Count"
            /// "Min Sample Value"
            /// "Max Sample Value"
            /// "X Resolution"
            /// "Y Resolution"
            /// "Planar Config"
            /// "Page Name"
            /// "X Position"
            /// "Y Position"
            /// "Free Offset"
            /// "Free Byte Counts"
            /// "Gray Response Unit"
            /// "Gray Response Curve"
            /// "T4 Option"
            /// "T6 Option"
            /// "Resolution Unit"
            /// "Page Number"
            /// "Transfer Funcition"
            /// "Software Used"
            /// "Date Time"
            /// "Artist"
            /// "Host Computer"
            /// "Predictor"
            /// "White Point"
            /// "Primary Chromaticities"
            /// "ColorMap"
            /// "Halftone Hints"
            /// "Tile Width"
            /// "Tile Length"
            /// "Tile Offset"
            /// "Tile ByteCounts"
            /// "InkSet"
            /// "Ink Names"
            /// "Number Of Inks"
            /// "Dot Range"
            /// "Target Printer"
            /// "Extra Samples"
            /// "Sample Format"
            /// "S Min Sample Value"
            /// "S Max Sample Value"
            /// "Transfer Range"
            /// "JPEG Proc"
            /// "JPEG InterFormat"
            /// "JPEG InterLength"
            /// "JPEG RestartInterval"
            /// "JPEG LosslessPredictors"
            /// "JPEG PointTransforms"
            /// "JPEG QTables"
            /// "JPEG DCTables"
            /// "JPEG ACTables"
            /// "YCbCr Coefficients"
            /// "YCbCr Subsampling"
            /// "YCbCr Positioning"
            /// "REF Black White"
            /// "ICC Profile"
            /// "Gamma"
            /// "ICC Profile Descriptor"
            /// "SRGB RenderingIntent"
            /// "Image Title"
            /// "Copyright"
            /// "Resolution X Unit"
            /// "Resolution Y Unit"
            /// "Resolution X LengthUnit"
            /// "Resolution Y LengthUnit"
            /// "Print Flags"
            /// "Print Flags Version"
            /// "Print Flags Crop"
            /// "Print Flags Bleed Width"
            /// "Print Flags Bleed Width Scale"
            /// "Halftone LPI"
            /// "Halftone LPIUnit"
            /// "Halftone Degree"
            /// "Halftone Shape"
            /// "Halftone Misc"
            /// "Halftone Screen"
            /// "JPEG Quality"
            /// "Grid Size"
            /// "Thumbnail Format"
            /// "Thumbnail Width"
            /// "Thumbnail Height"
            /// "Thumbnail ColorDepth"
            /// "Thumbnail Planes"
            /// "Thumbnail RawBytes"
            /// "Thumbnail Size"
            /// "Thumbnail CompressedSize"
            /// "Color Transfer Function"
            /// "Thumbnail Data"
            /// "Thumbnail ImageWidth"
            /// "Thumbnail ImageHeight"
            /// "Thumbnail BitsPerSample"
            /// "Thumbnail Compression"
            /// "Thumbnail PhotometricInterp"
            /// "Thumbnail ImageDescription"
            /// "Thumbnail EquipMake"
            /// "Thumbnail EquipModel"
            /// "Thumbnail StripOffsets"
            /// "Thumbnail Orientation"
            /// "Thumbnail SamplesPerPixel"
            /// "Thumbnail RowsPerStrip"
            /// "Thumbnail StripBytesCount"
            /// "Thumbnail ResolutionX"
            /// "Thumbnail ResolutionY"
            /// "Thumbnail PlanarConfig"
            /// "Thumbnail ResolutionUnit"
            /// "Thumbnail TransferFunction"
            /// "Thumbnail SoftwareUsed"
            /// "Thumbnail DateTime"
            /// "Thumbnail Artist"
            /// "Thumbnail WhitePoint"
            /// "Thumbnail PrimaryChromaticities"
            /// "Thumbnail YCbCrCoefficients"
            /// "Thumbnail YCbCrSubsampling"
            /// "Thumbnail YCbCrPositioning"
            /// "Thumbnail RefBlackWhite"
            /// "Thumbnail CopyRight"
            /// "Luminance Table"
            /// "Chrominance Table"
            /// "Frame Delay"
            /// "Loop Count"
            /// "Pixel Unit"
            /// "Pixel PerUnit X"
            /// "Pixel PerUnit Y"
            /// "Palette Histogram"
            /// "Exposure Time"
            /// "F-Number"
            /// "Exposure Prog"
            /// "Spectral Sense"
            /// "ISO Speed"
            /// "OECF"
            /// "Ver"
            /// "DTOrig"
            /// "DTDigitized"
            /// "CompConfig"
            /// "CompBPP"
            /// "Shutter Speed"
            /// "Aperture"
            /// "Brightness"
            /// "Exposure Bias"
            /// "MaxAperture"
            /// "SubjectDist"
            /// "Metering Mode"
            /// "LightSource"
            /// "Flash"
            /// "FocalLength"
            /// "Maker Note"
            /// "User Comment"
            /// "DTSubsec"
            /// "DTOrigSS"
            /// "DTDigSS"
            /// "FPXVer"
            /// "ColorSpace"
            /// "PixXDim"
            /// "PixYDim"
            /// "RelatedWav"
            /// "Interop"
            /// "FlashEnergy"
            /// "SpatialFR"
            /// "FocalXRes"
            /// "FocalYRes"
            /// "FocalResUnit"
            /// "Subject Loc"
            /// "Exposure Index"
            /// "Sensing Method"
            /// "FileSource"
            /// "SceneType"
            /// "CfaPattern"
            /// "Gps Ver"
            /// "Gps LatitudeRef"
            /// "Gps Latitude"
            /// "Gps LongitudeRef"
            /// "Gps Longitude"
            /// "Gps AltitudeRef"
            /// "Gps Altitude"
            /// "Gps GpsTime"
            /// "Gps GpsSatellites"
            /// "Gps GpsStatus"
            /// "Gps GpsMeasureMode"
            /// "Gps GpsDop"
            /// "Gps SpeedRef"
            /// "Gps Speed"
            /// "Gps TrackRef"
            /// "Gps Track"
            /// "Gps ImgDirRef"
            /// "Gps ImgDir"
            /// "Gps MapDatum"
            /// "Gps DestLatRef"
            /// "Gps DestLat"
            /// "Gps DestLongRef"
            /// "Gps DestLong"
            /// "Gps DestBearRef"
            /// "Gps DestBear"
            /// "Gps DestDistRef"
            /// "Gps DestDist"
            /// </summary>
            public object this[string index]
            {
                get
                {
                    return properties[index];
                }
            }
            //
            private System.Drawing.Bitmap bmp;
            //
            private string data;
            //
            private translation myHash;
            //
            private Hashtable properties;
            //
            internal int Count
            {
                get
                {
                    return this.properties.Count;
                }
            }
            //
            string sp;
            /// <summary>
            ///
            /// </summary>
            /// <param name="id"></param>
            /// <param name="len"></param>
            /// <param name="type"></param>
            /// <param name="data"></param>
            public void setTag(int id, string data)
            {
                Encoding ascii = Encoding.ASCII;
                this.setTag(id,data.Length,0x2,ascii.GetBytes(data));
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="id"></param>
            /// <param name="len"></param>
            /// <param name="type"></param>
            /// <param name="data"></param>
            public void setTag(int id, int len, short type, byte [] data)
            {
                PropertyItem p = CreatePropertyItem(type,id,len,data);
                this.bmp.SetPropertyItem( p );
                buildDB(this.bmp.PropertyItems);
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="type"></param>
            /// <param name="tag"></param>
            /// <param name="len"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            private static PropertyItem CreatePropertyItem(short type, int tag, int len, byte[] value)
            {
                PropertyItem item;

                // Loads a PropertyItem from a Jpeg image stored in the assembly as a resource.
                Assembly assembly = Assembly.GetExecutingAssembly();
                Stream emptyBitmapStream = assembly.GetManifestResourceStream("EXIFextractor.decoy.jpg");
                System.Drawing.Image empty = System.Drawing.Image.FromStream(emptyBitmapStream);

                item = empty.PropertyItems[0];

                // Copies the data to the property item.
                item.Type = type;
                item.Len = len;
                item.Id = tag;
                item.Value = new byte[value.Length];
                value.CopyTo(item.Value, 0);

                return item;
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="bmp"></param>
            /// <param name="sp"></param>
            public EXIFextractor(ref System.Drawing.Bitmap bmp, string sp )
            {
                properties = new Hashtable();
                //
                this.bmp = bmp;
                this.sp = sp;
                //
                myHash = new translation();
                buildDB(this.bmp.PropertyItems);
            }
            string msp = "";
            public EXIFextractor(ref System.Drawing.Bitmap bmp, string sp, string msp )
            {
                properties = new Hashtable();
                this.sp = sp;
                this.msp = msp;
                this.bmp = bmp;
                //
                myHash = new translation();
                this.buildDB(bmp.PropertyItems);

            }

            public static void CopyTo(Stream input, Stream outputStream)
            {
                byte[] btybuffer = new byte[16 * 1019]; // Fairly arbitrary size
                int bytesRead;
                while ((bytesRead = input.Read(btybuffer, 0, btybuffer.Length)) > 0)
                {
                    outputStream.Write(btybuffer, 0, bytesRead);
                }
            }

            public static PropertyItem[] GetExifProperties(string fileName)
            {
                MemoryStream ms = new MemoryStream();

                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    CopyTo(stream, ms);
                }

                System.Drawing.Image image = System.Drawing.Image.FromStream(ms,
                                 /* useEmbeddedColorManagement = */ true,
                                 /* validateImageData = */ false);

                return image.PropertyItems;
            }


            public EXIFextractor(string file, string sp, string msp )
            {
                properties = new Hashtable();
                this.sp = sp;
                this.msp = msp;

                myHash = new translation();
                //
                this.buildDB(GetExifProperties(file));

            }

            /// <summary>
            ///
            /// </summary>
            private void buildDB(System.Drawing.Imaging.PropertyItem[] parr)
            {
                properties.Clear();
                //
                data = "";
                //
                Encoding ascii = Encoding.ASCII;
                //
                foreach( System.Drawing.Imaging.PropertyItem p in parr )
                {
                    string v = "";
                    string name = (string)myHash[p.Id];
                    // tag not found. skip it
                    if( name == null ) continue;
                    //
                    data += name+": ";
                    //
                    //1 = BYTE An 8-bit unsigned integer.,
                    if( p.Type == 0x1 )
                    {
                        v = p.Value[0].ToString();
                    }
                        //2 = ASCII An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.,
                    else if( p.Type == 0x2 )
                    {
                        // string
                        v = ascii.GetString(p.Value);
                    }
                        //3 = SHORT A 16-bit (2 -byte) unsigned integer,
                    else if( p.Type == 0x3 )
                    {
                        // orientation // lookup table
                        switch( p.Id )
                        {
                            case 0x8827: // ISO
                                v = "ISO-" + convertToInt16U(p.Value).ToString();
                                break;
                            case 0xA217: // sensing method
                            {
                                switch( convertToInt16U(p.Value) )
                                {
                                    case 1: v = "Not defined"; break;
                                    case 2: v = "One-chip color area sensor"; break;
                                    case 3: v = "Two-chip color area sensor"; break;
                                    case 4: v = "Three-chip color area sensor"; break;
                                    case 5: v = "Color sequential area sensor"; break;
                                    case 7: v = "Trilinear sensor"; break;
                                    case 8: v = "Color sequential linear sensor"; break;
                                    default: v =" reserved"; break;
                                }
                            }
                                break;
                            case 0x8822: // aperture
                            switch( convertToInt16U(p.Value) )
                            {
                                case 0: v = "Not defined"; break;
                                case 1: v = "Manual"; break;
                                case 2: v = "Normal program"; break;
                                case 3: v = "Aperture priority"; break;
                                case 4: v = "Shutter priority"; break;
                                case 5: v = "Creative program (biased toward depth of field)"; break;
                                case 6: v = "Action program (biased toward fast shutter speed)"; break;
                                case 7: v = "Portrait mode (for closeup photos with the background out of focus)"; break;
                                case 8: v = "Landscape mode (for landscape photos with the background in focus)"; break;
                                default: v = "reserved"; break;
                            }
                                break;
                            case 0x9207: // metering mode
                            switch( convertToInt16U(p.Value) )
                            {
                                case 0: v = "unknown";break;
                                case 1: v = "Average";break;
                                case 2: v = "CenterWeightedAverage"; break;
                                case 3: v = "Spot"; break;
                                case 4: v = "MultiSpot"; break;
                                case 5: v = "Pattern"; break;
                                case 6: v = "Partial"; break;
                                case 255: v = "Other"; break;
                                default: v = "reserved"; break;
                            }
                                break;
                            case 0x9208: // light source
                            {
                                switch(convertToInt16U(p.Value) )
                                {
                                    case 0:v = "unknown";break;
                                    case 1:v = "Daylight";break;
                                    case 2:v = "Fluorescent";break;
                                    case 3:v = "Tungsten";break;
                                    case 17:v = "Standard light A";break;
                                    case 18:v = "Standard light B";break;
                                    case 19:v = "Standard light C";break;
                                    case 20:v = "D55";break;
                                    case 21:v = "D65";break;
                                    case 22:v = "D75";break;
                                    case 255:v = "other";break;
                                    default:v = "reserved";break;
                                }
                            }
                                break;
                            case 0x9209:
                            {
                                switch(convertToInt16U(p.Value) )
                                {
                                    case 0: v = "Flash did not fire"; break;
                                    case 1: v = "Flash fired"; break;
                                    case 5: v = "Strobe return light not detected"; break;
                                    case 7: v = "Strobe return light detected"; break;
                                    default: v = "reserved"; break;
                                }
                            }
                                break;
                            default:
                                v = convertToInt16U(p.Value).ToString();
                                break;
                        }
                    }
                        //4 = LONG A 32-bit (4 -byte) unsigned integer,
                    else if( p.Type == 0x4 )
                    {
                        // orientation // lookup table
                        v = convertToInt32U(p.Value).ToString();
                    }
                        //5 = RATIONAL Two LONGs. The first LONG is the numerator and the second LONG expresses the//denominator.,
                    else if( p.Type == 0x5 )
                    {
                    //My code starts here
                    if (p.Id == 0x0004)
                    {
                        //lat
                        // rational
                        byte[] deg = new byte[4];
                        byte[] degdiv = new byte[4];
                        byte[] min = new byte[4];
                        byte[] mindiv = new byte[4];
                        byte[] sec = new byte[4];
                        byte[] secdiv = new byte[4];
                        Array.Copy(p.Value, 0, deg, 0, 4);
                        Array.Copy(p.Value, 4, degdiv, 0, 4);
                        Array.Copy(p.Value, 8, min, 0, 4);
                        Array.Copy(p.Value, 12, mindiv, 0, 4);
                        Array.Copy(p.Value, 16, sec, 0, 4);
                        Array.Copy(p.Value, 20, secdiv, 0, 4);
                        double _a = convertToInt32U(deg);
                        double _b = convertToInt32U(degdiv);
                        double _c = convertToInt32U(min);
                        double _d = convertToInt32U(mindiv);
                        double _e = convertToInt32U(sec);
                        double _f = convertToInt32U(secdiv);
                        double _o = ((_a / _b) + ((_c / _b) / 60) + ((_e / _f) / 3600));
                        v = _o.ToString();
                        //    Rational r = new Rational(a, b);
                    }
                    else if (p.Id == 0x0002)
                    {
                        //long
                        byte[] deg = new byte[4];
                        byte[] degdiv = new byte[4];
                        byte[] min = new byte[4];
                        byte[] mindiv = new byte[4];
                        byte[] sec = new byte[4];
                        byte[] secdiv = new byte[4];
                        Array.Copy(p.Value, 0, deg, 0, 4);
                        Array.Copy(p.Value, 4, degdiv, 0, 4);
                        Array.Copy(p.Value, 8, min, 0, 4);
                        Array.Copy(p.Value, 12, mindiv, 0, 4);
                        Array.Copy(p.Value, 16, sec, 0, 4);
                        Array.Copy(p.Value, 20, secdiv, 0, 4);
                        double dblA = convertToInt32U(deg);
                        double dblB = convertToInt32U(degdiv);
                        double dblC = convertToInt32U(min);
                        double dblD = convertToInt32U(mindiv);
                        double dblE = convertToInt32U(sec);
                        double dblF = convertToInt32U(secdiv);
                        double o = ((dblA / dblB) + ((dblC/ dblB) / 60) + ((dblE/ dblF) / 3600));
                        v = o.ToString();
                    }
                    //My Code ends here
                    // rational
                    byte[]n = new byte[p.Len/2];
                        byte []d = new byte[p.Len/2];
                        Array.Copy(p.Value,0,n,0,p.Len/2);
                        Array.Copy(p.Value,p.Len/2,d,0,p.Len/2);
                        uint a = convertToInt32U(n);
                        uint b = convertToInt32U(d);
                        Rational r = new Rational(a,b);
                        //
                        //convert here
                        //
                        switch( p.Id )
                        {
                            case 0x9202: // aperture
                                v = "F/" + Math.Round(Math.Pow(Math.Sqrt(2),r.ToDouble()),2).ToString();
                                break;
                            case 0x920A:
                                v = r.ToDouble().ToString();
                                break;
                            case 0x829A:
                                v = r.ToDouble().ToString();
                                break;
                            case 0x829D: // F-number
                                v = "F/" + r.ToDouble().ToString();
                                break;
                            default:
                                v= r.ToString("/");
                                break;
                        }

                    }
                        //7 = UNDEFINED An 8-bit byte that can take any value depending on the field definition,
                    else if( p.Type == 0x7 )
                    {
                        switch (p.Id )
                        {
                            case 0xA300:
                            {
                                if( p.Value[0] == 3 )
                                {
                                    v = "DSC";
                                }
                                else
                                {
                                    v = "reserved";
                                }
                                break;
                            }
                            case 0xA301:
                                if( p.Value[0] == 1 )
                                    v = "A directly photographed image";
                                else
                                    v = "Not a directly photographed image";
                                break;
                            default:
                                v = "-";
                                break;
                        }
                    }
                        //9 = SLONG A 32-bit (4 -byte) signed integer (2's complement notation),
                    else if( p.Type == 0x9 )
                    {
                        v = convertToInt32(p.Value).ToString();
                    }
                        //10 = SRATIONAL Two SLONGs. The first SLONG is the numerator and the second SLONG is the
                        //denominator.
                    else if( p.Type == 0xA )
                    {

                        // rational
                        byte []n = new byte[p.Len/2];
                        byte []d = new byte[p.Len/2];
                        Array.Copy(p.Value,0,n,0,p.Len/2);
                        Array.Copy(p.Value,p.Len/2,d,0,p.Len/2);
                        int a = convertToInt32(n);
                        int b = convertToInt32(d);
                        Rational r = new Rational(a,b);
                        //
                        // convert here
                        //
                        switch( p.Id )
                        {
                            case 0x9201: // shutter speed
                                v = "1/" +Math.Round( Math.Pow(2,r.ToDouble()),2).ToString();
                                break;
                            case 0x9203:
                                v = Math.Round(r.ToDouble(),4).ToString();
                                break;
                            default:
                                v = r.ToString("/");
                                break;
                        }
                    }
                    // add it to the list
                    if( properties[name] == null )
                        properties.Add(name,v);
                    // cat it too
                    data+= v;
                    data+= this.sp;
                }

            }

            /// <summary>
            ///
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                return data;
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="arr"></param>
            /// <returns></returns>
            int convertToInt32(byte [] arr)
            {
                if(arr.Length != 4 )
                    return 0;
                else
                    return arr[3] << 24 | arr[2] << 16 | arr[1] << 8 | arr[0];
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="arr"></param>
            /// <returns></returns>
            int convertToInt16(byte [] arr)
            {
                if(arr.Length != 2 )
                    return 0;
                else
                    return arr[1] << 8 | arr[0];
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="arr"></param>
            /// <returns></returns>
            uint convertToInt32U(byte [] arr)
            {
                if(arr.Length != 4 )
                    return 0;
                else
                    return Convert.ToUInt32(arr[3] << 24 | arr[2] << 16 | arr[1] << 8 | arr[0]);
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="arr"></param>
            /// <returns></returns>
            uint convertToInt16U(byte [] arr)
            {
                if(arr.Length != 2 )
                    return 0;
                else
                    return Convert.ToUInt16(arr[1] << 8 | arr[0]);
            }
            #region IEnumerable Members

            public IEnumerator GetEnumerator()
            {
                // TODO:  Add EXIFextractor.GetEnumerator implementation
                return( new EXIFextractorEnumerator( this.properties ));
            }

            #endregion
        }

        //
        // dont touch this class. its for IEnumerator
        //
        //
        class EXIFextractorEnumerator : IEnumerator
        {
            Hashtable exifTable;
            IDictionaryEnumerator index;

            internal EXIFextractorEnumerator( Hashtable exif )
            {
                this.exifTable = exif;
                this.Reset();
                index = exif.GetEnumerator();
            }

            #region IEnumerator Members

            public void Reset()
            {
                this.index = null;
            }

            public object Current
            {
                get
                {
                    return ( new System.Web.UI.Pair(this.index.Key,this.index.Value) );
                }
            }

            public bool MoveNext()
            {
                if( index != null && index.MoveNext() )
                    return true;
                else
                    return false;
            }

            #endregion

        }
    }


А вот код для моего класса перевода.

using System;
using System.Collections;

	namespace EXIF
	{
		/// <summary>
		/// Summary description for translation.
		/// </summary>
		public class translation : Hashtable
		{
			/// <summary>
			/// 
			/// </summary>
			public translation()
			{
				this.Add(0x8769,"Exif IFD");
				this.Add(0x8825,"Gps IFD");
				this.Add(0xFE,"New Subfile Type");
				this.Add(0xFF,"Subfile Type");
				this.Add(0x100,"Image Width");
				this.Add(0x101,"Image Height");
				this.Add(0x102,"Bits Per Sample");
				this.Add(0x103,"Compression");
				this.Add(0x106,"Photometric Interp");
				this.Add(0x107,"Thresh Holding");
				this.Add(0x108,"Cell Width");
				this.Add(0x109,"Cell Height");
				this.Add(0x10A,"Fill Order");
				this.Add(0x10D,"Document Name");
				this.Add(0x10E,"Image Description");
				this.Add(0x10F,"Equip Make");
				this.Add(0x110,"Equip Model");
				this.Add(0x111,"Strip Offsets");
				this.Add(0x112,"Orientation");
				this.Add(0x115,"Samples PerPixel");
				this.Add(0x116,"Rows Per Strip");
				this.Add(0x117,"Strip Bytes Count");
				this.Add(0x118,"Min Sample Value");
				this.Add(0x119,"Max Sample Value");
				this.Add(0x11A,"X Resolution");
				this.Add(0x11B,"Y Resolution");
				this.Add(0x11C,"Planar Config");
				this.Add(0x11D,"Page Name");
				this.Add(0x11E,"X Position");
				this.Add(0x11F,"Y Position");
				this.Add(0x120,"Free Offset");
				this.Add(0x121,"Free Byte Counts");
				this.Add(0x122,"Gray Response Unit");
				this.Add(0x123,"Gray Response Curve");
				this.Add(0x124,"T4 Option");
				this.Add(0x125,"T6 Option");
				this.Add(0x128,"Resolution Unit");
				this.Add(0x129,"Page Number");
				this.Add(0x12D,"Transfer Funcition");
				this.Add(0x131,"Software Used");
				this.Add(0x132,"Date Time");
				this.Add(0x13B,"Artist");
				this.Add(0x13C,"Host Computer");
				this.Add(0x13D,"Predictor");
				this.Add(0x13E,"White Point");
				this.Add(0x13F,"Primary Chromaticities");
				this.Add(0x140,"ColorMap");
				this.Add(0x141,"Halftone Hints");
				this.Add(0x142,"Tile Width");
				this.Add(0x143,"Tile Length");
				this.Add(0x144,"Tile Offset");
				this.Add(0x145,"Tile ByteCounts");
				this.Add(0x14C,"InkSet");
				this.Add(0x14D,"Ink Names");
				this.Add(0x14E,"Number Of Inks");
				this.Add(0x150,"Dot Range");
				this.Add(0x151,"Target Printer");
				this.Add(0x152,"Extra Samples");
				this.Add(0x153,"Sample Format");
				this.Add(0x154,"S Min Sample Value");
				this.Add(0x155,"S Max Sample Value");
				this.Add(0x156,"Transfer Range");
				this.Add(0x200,"JPEG Proc");
				this.Add(0x201,"JPEG InterFormat");
				this.Add(0x202,"JPEG InterLength");
				this.Add(0x203,"JPEG RestartInterval");
				this.Add(0x205,"JPEG LosslessPredictors");
				this.Add(0x206,"JPEG PointTransforms");
				this.Add(0x207,"JPEG QTables");
				this.Add(0x208,"JPEG DCTables");
				this.Add(0x209,"JPEG ACTables");
				this.Add(0x211,"YCbCr Coefficients");
				this.Add(0x212,"YCbCr Subsampling");
				this.Add(0x213,"YCbCr Positioning");
				this.Add(0x214,"REF Black White");
				this.Add(0x8773,"ICC Profile");
				this.Add(0x301,"Gamma");
				this.Add(0x302,"ICC Profile Descriptor");
				this.Add(0x303,"SRGB RenderingIntent");
				this.Add(0x320,"Image Title");
				this.Add(0x8298,"Copyright");
				this.Add(0x5001,"Resolution X Unit");
				this.Add(0x5002,"Resolution Y Unit");
				this.Add(0x5003,"Resolution X LengthUnit");
				this.Add(0x5004,"Resolution Y LengthUnit");
				this.Add(0x5005,"Print Flags");
				this.Add(0x5006,"Print Flags Version");
				this.Add(0x5007,"Print Flags Crop");
				this.Add(0x5008,"Print Flags Bleed Width");
				this.Add(0x5009,"Print Flags Bleed Width Scale");
				this.Add(0x500A,"Halftone LPI");
				this.Add(0x500B,"Halftone LPIUnit");
				this.Add(0x500C,"Halftone Degree");
				this.Add(0x500D,"Halftone Shape");
				this.Add(0x500E,"Halftone Misc");
				this.Add(0x500F,"Halftone Screen");
				this.Add(0x5010,"JPEG Quality");
				this.Add(0x5011,"Grid Size");
				this.Add(0x5012,"Thumbnail Format");
				this.Add(0x5013,"Thumbnail Width");
				this.Add(0x5014,"Thumbnail Height");
				this.Add(0x5015,"Thumbnail ColorDepth");
				this.Add(0x5016,"Thumbnail Planes");
				this.Add(0x5017,"Thumbnail RawBytes");
				this.Add(0x5018,"Thumbnail Size");
				this.Add(0x5019,"Thumbnail CompressedSize");
				this.Add(0x501A,"Color Transfer Function");
				this.Add(0x501B,"Thumbnail Data");
				this.Add(0x5020,"Thumbnail ImageWidth");
				this.Add(0x502,"Thumbnail ImageHeight");
				this.Add(0x5022,"Thumbnail BitsPerSample");
				this.Add(0x5023,"Thumbnail Compression");
				this.Add(0x5024,"Thumbnail PhotometricInterp");
				this.Add(0x5025,"Thumbnail ImageDescription");
				this.Add(0x5026,"Thumbnail EquipMake");
				this.Add(0x5027,"Thumbnail EquipModel");
				this.Add(0x5028,"Thumbnail StripOffsets");
				this.Add(0x5029,"Thumbnail Orientation");
				this.Add(0x502A,"Thumbnail SamplesPerPixel");
				this.Add(0x502B,"Thumbnail RowsPerStrip");
				this.Add(0x502C,"Thumbnail StripBytesCount");
				this.Add(0x502D,"Thumbnail ResolutionX");
				this.Add(0x502E,"Thumbnail ResolutionY");
				this.Add(0x502F,"Thumbnail PlanarConfig");
				this.Add(0x5030,"Thumbnail ResolutionUnit");
				this.Add(0x5031,"Thumbnail TransferFunction");
				this.Add(0x5032,"Thumbnail SoftwareUsed");
				this.Add(0x5033,"Thumbnail DateTime");
				this.Add(0x5034,"Thumbnail Artist");
				this.Add(0x5035,"Thumbnail WhitePoint");
				this.Add(0x5036,"Thumbnail PrimaryChromaticities");
				this.Add(0x5037,"Thumbnail YCbCrCoefficients");
				this.Add(0x5038,"Thumbnail YCbCrSubsampling");
				this.Add(0x5039,"Thumbnail YCbCrPositioning");
				this.Add(0x503A,"Thumbnail RefBlackWhite");
				this.Add(0x503B,"Thumbnail CopyRight");
				this.Add(0x5090,"Luminance Table");
				this.Add(0x5091,"Chrominance Table");
				this.Add(0x5100,"Frame Delay");
				this.Add(0x5101,"Loop Count");
				this.Add(0x5110,"Pixel Unit");
				this.Add(0x5111,"Pixel PerUnit X");
				this.Add(0x5112,"Pixel PerUnit Y");
				this.Add(0x5113,"Palette Histogram");
				this.Add(0x829A,"Exposure Time");
				this.Add(0x829D,"F-Number");
				this.Add(0x8822,"Exposure Prog");
				this.Add(0x8824,"Spectral Sense");
				this.Add(0x8827,"ISO Speed");
				this.Add(0x8828,"OECF");
				this.Add(0x9000,"Ver");
				this.Add(0x9003,"DTOrig");
				this.Add(0x9004,"DTDigitized");
				this.Add(0x9101,"CompConfig");
				this.Add(0x9102,"CompBPP");
				this.Add(0x9201,"Shutter Speed");
				this.Add(0x9202,"Aperture");
				this.Add(0x9203,"Brightness");
				this.Add(0x9204,"Exposure Bias");
				this.Add(0x9205,"MaxAperture");
				this.Add(0x9206,"SubjectDist");
				this.Add(0x9207,"Metering Mode");
				this.Add(0x9208,"LightSource");
				this.Add(0x9209,"Flash");
				this.Add(0x920A,"FocalLength");
				this.Add(0x927C,"Maker Note");
				this.Add(0x9286,"User Comment");
				this.Add(0x9290,"DTSubsec");
				this.Add(0x9291,"DTOrigSS");
				this.Add(0x9292,"DTDigSS");
				this.Add(0xA000,"FPXVer");
				this.Add(0xA001,"ColorSpace");
				this.Add(0xA002,"PixXDim");
				this.Add(0xA003,"PixYDim");
				this.Add(0xA004,"RelatedWav");
				this.Add(0xA005,"Interop");
				this.Add(0xA20B,"FlashEnergy");
				this.Add(0xA20C,"SpatialFR");
				this.Add(0xA20E,"FocalXRes");
				this.Add(0xA20F,"FocalYRes");
				this.Add(0xA210,"FocalResUnit");
				this.Add(0xA214,"Subject Loc");
				this.Add(0xA215,"Exposure Index");
				this.Add(0xA217,"Sensing Method");
				this.Add(0xA300,"FileSource");
				this.Add(0xA301,"SceneType");
				this.Add(0xA302,"CfaPattern");
				this.Add(0x0,"Gps Ver");
				this.Add(0x1,"Gps LatitudeRef");
				this.Add(0x2,"Gps Latitude");
				this.Add(0x3,"Gps LongitudeRef");
				this.Add(0x4,"Gps Longitude");
				this.Add(0x5,"Gps AltitudeRef");
				this.Add(0x6,"Gps Altitude");
				this.Add(0x7,"Gps GpsTime");
				this.Add(0x8,"Gps GpsSatellites");
				this.Add(0x9,"Gps GpsStatus");
				this.Add(0xA,"Gps GpsMeasureMode");
				this.Add(0xB,"Gps GpsDop");
				this.Add(0xC,"Gps SpeedRef");
				this.Add(0xD,"Gps Speed");
				this.Add(0xE,"Gps TrackRef");
				this.Add(0xF,"Gps Track");
				this.Add(0x10,"Gps ImgDirRef");
				this.Add(0x11,"Gps ImgDir");
				this.Add(0x12,"Gps MapDatum");
				this.Add(0x13,"Gps DestLatRef");
				this.Add(0x14,"Gps DestLat");
				this.Add(0x15,"Gps DestLongRef");
				this.Add(0x16,"Gps DestLong");
				this.Add(0x17,"Gps DestBearRef");
				this.Add(0x18,"Gps DestBear");
				this.Add(0x19,"Gps DestDistRef");
				this.Add(0x1A,"Gps DestDist");
			}
		}
		/// <summary>
		/// private class
		/// </summary>
		internal class Rational
		{
			private int n;
			private int d;
			public Rational(int n, int d)
			{
				this.n = n;
				this.d = d;
				simplify(ref this.n, ref this.d);
			}
			public Rational(uint n, uint d)
			{
				this.n = Convert.ToInt32(n);
				this.d = Convert.ToInt32(d);

				simplify(ref this.n, ref this.d);
			}
			public Rational()
			{
				this.n= this.d=0;
			}
			public string ToString(string sp)
			{
				if( sp == null ) sp = "/";
				return n.ToString() + sp + d.ToString();
			}
			public double ToDouble()
			{
				if( d == 0 )
					return 0.0;

				return Math.Round(Convert.ToDouble(n)/Convert.ToDouble(d),2);
			}
			private void simplify( ref int a, ref int b )
			{
				if( a== 0 || b == 0 )
					return;

				int	gcd = euclid(a,b);
				a /= gcd;
				b /= gcd;
			}
			private int euclid(int a, int b)
			{
				if(b==0)	
					return a;
				else		
					return euclid(b,a%b);
			}
		}
	}


Что я уже пробовал:

Я уже смотрел класс PropertyItem в msdn, но не знаю, с чего начать его реализацию для этой программы.

Что-то подсказывает мне, что я должен настроить оператор if else для тега в EXIFextractor.BuildDB(). Но, увы, математика не является моей сильной стороной. Как бы мне реализовать эту логику, пожалуйста?

Richard MacCutchan

Сообщение об ошибке совершенно ясно, ваш bmp переменная никогда не была установлена в допустимую ссылку на объект. Но где во всем этом коде возникает ошибка, не ясно.

Jordan Nash

Ах, да, я понимаю, что у меня была перегрузка метода точного метода, где была ошибка. Это здесь, в Эксифэкстракторе.

public void setTag(int id, int len, short type, byte [] data)
{
PropertyItem p = CreatePropertyItem(тип,идентификатор,len,данные);
this.bmp.SetPropertyItem( p );//ошибка в этой строке.
buildDB(this.bmp.PropertyItems);
}

Richard MacCutchan

Поэтому вам нужно выяснить, почему bmp не установлен в допустимую ссылку.

Jordan Nash

Я изменил метод loadImageMetaData() на этот. Метод setTag (), конечно, ожидал растрового изображения, поэтому я создал его экземпляр.

частный недействительными loadImageMetaData()
{
lstImageMetaData.Предметы.Четкий();
Bitmap bmp = новое растровое изображение(_big_fileName);
ЭКСИФ.EXIFextractor er2 = новый EXIF.EXIFextractor(ref bmp, "\n");
foreach (пара s в er2)
{
lstImageMetaData.Предметы.Добавить(s.First + " : "+ s.Second);
}
lstImageMetaData.Свойства selectedIndex = lstImageMetaData.Предметы.Количество - 1;
er2.setTag(0x5013,"ширина миниатюры");
}

Итак, я больше не получаю ошибку, но она по-прежнему не будет отображать метаданные “ширина миниатюры”. Вы знаете, что я делаю не так, пожалуйста?

Richard MacCutchan

Эта библиотека была написана членом CodeProject, поэтому вам нужно разместить свой вопрос на форуме в конце статьи.

Jordan Nash

Я уже сделал это 3 дня назад. Никто не ответил. Возможно, мне нужно больше терпения. Я поставлю свой предыдущий комментарий отсюда на тот вопрос, который я уже разместил на этом форуме.

Richard MacCutchan

Проблема в том, что человек, написавший эту статью, - единственный, кто действительно поймет, как она работает. Так что, спрашивая здесь, вы вряд ли получите ответ.

0 Ответов