Как я могу узнать, когда на самом деле был сделан снимок в C #, работающем в Vista? - PullRequest
43 голосов
/ 07 октября 2008

В Windows XP FileInfo.LastWriteTime возвращает дату, когда был сделан снимок - независимо от того, сколько раз файл перемещался в файловой системе.

В Vista вместо этого возвращается дата копирования изображения с камеры.

Как узнать, когда в Vista сделан снимок? В проводнике Windows это поле называется «Дата съемки».

Ответы [ 8 ]

91 голосов
/ 10 октября 2011

Вот так быстро и чисто, как вы можете его получить. Используя FileStream, вы можете указать GDI + не загружать все изображение для проверки. На моей машине он работает в 10 раз быстрее.

    //we init this once so that if the function is repeatedly called
    //it isn't stressing the garbage man
    private static Regex r = new Regex(":");

    //retrieves the datetime WITHOUT loading the whole image
    public static DateTime GetDateTakenFromImage(string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
        using (Image myImage = Image.FromStream(fs, false, false))
        {
            PropertyItem propItem = myImage.GetPropertyItem(36867);
            string dateTaken = r.Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
            return DateTime.Parse(dateTaken);
        }
    }

И да, правильный идентификатор - 36867, а не 306.

Другие проекты с открытым исходным кодом, приведенные ниже, должны принять это к сведению. это ОГРОМНЫЙ удар производительности при обработке тысяч файлов!

10 голосов
/ 08 октября 2008
Image myImage = Image.FromFile(@"C:\temp\IMG_0325.JPG");
PropertyItem propItem = myImage.GetPropertyItem(306);
DateTime dtaken;

//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
string secondhalf = sdate.Substring(sdate.IndexOf(" "), (sdate.Length - sdate.IndexOf(" ")));
string firsthalf = sdate.Substring(0, 10);
firsthalf = firsthalf.Replace(":", "-");
sdate = firsthalf + secondhalf;
dtaken = DateTime.Parse(sdate);
7 голосов
/ 03 октября 2016

С 2002 года я поддерживал простую библиотеку с открытым исходным кодом для извлечения метаданных из файлов изображений / видео.

// Read all metadata from the image
var directories = ImageMetadataReader.ReadMetadata(stream);

// Find the so-called Exif "SubIFD" (which may be null)
var subIfdDirectory = directories.OfType<ExifSubIfdDirectory>().FirstOrDefault();

// Read the DateTime tag value
var dateTime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTimeOriginal);

В моих тестах этот код работает в 12 раз быстрее, чем Image.GetPropertyItem, и примерно в 17 раз быстрее, чем WPF JpegBitmapDecoder / BitmapMetadata API.

В библиотеке доступно множество дополнительной информации, такой как настройки камеры (F-стоп, ISO, выдержка, режим вспышки, фокусное расстояние, ...), свойства изображения (размеры, конфигурации пикселей) и другие вещи, такие как как позиции GPS, ключевые слова, информация об авторских правах и т. д.

Если вас интересуют только метаданные, то использовать эту библиотеку очень быстро, поскольку она не декодирует изображение (то есть растровое изображение). Вы можете отсканировать тысячи изображений за несколько секунд, если у вас достаточно быстрое хранилище.

ImageMetadataReader понимает многие типы файлов (JPEG, PNG, GIF, BMP, TIFF, PCX, WebP, ICO, ...). Если вы знаете , что имеете дело с JPEG, а вам только нужны данные Exif, то вы можете ускорить процесс с помощью следующего:

var directories = JpegMetadataReader.ReadMetadata(stream, new[] { new ExifReader() });

Библиотека извлечения метаданных доступна через NuGet и код на GitHub . Спасибо всем замечательным авторам, которые улучшили библиотеку и представили тестовые изображения за эти годы.

5 голосов
/ 07 октября 2008

С WPF и C # вы можете получить свойство Date Taken, используя класс BitmapMetadata:

MSDN - BitmapMetada

WPF и BitmapMetadata

2 голосов
/ 08 октября 2008

В Windows XP "FileInfo.LastWriteTime" вернет дату, когда изображение взят - независимо от того, сколько раз файл перемещается в файловая система.

У меня есть большие сомнения, XP действительно делал это. Скорее всего, инструмент, который вы использовали для копирования изображения с камеры на жесткий диск, сбрасывал дату изменения файла в дату создания изображения.

1 голос
/ 07 октября 2008

Там будут данные EXIF, встроенные в изображение. В Интернете есть множество примеров, если вы ищете EXIF ​​и C #.

1 голос
/ 07 октября 2008

вам нужно будет проверить информацию EXIF ​​с картинки. Я не думаю, что с обычными функциями .Net вы будете знать, когда был сделан снимок.

Это может быть немного сложнее ...

0 голосов
/ 06 февраля 2016
    //retrieves the datetime WITHOUT loading the whole image
    public static DateTime GetDateTakenFromImage(string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
        using (Image myImage = Image.FromStream(fs, false, false))
        {
            PropertyItem propItem = null;
            try
            {
                propItem = myImage.GetPropertyItem(36867);
            }
            catch { }
            if (propItem != null)
            {
                string dateTaken = r.Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
                return DateTime.Parse(dateTaken);
            }
            else
                return new FileInfo(path).LastWriteTime;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...