private void /*List<ImageInformation>*/ GetImagesUponMyCriteria(string path, ISO iso, Date date, ExposureTime et, ExposureProgram ep, Orientation or, bool isDSC, string camName, bool isManualWhiteBalance, bool isFlash, bool isGeo, bool isEdit, CancellationToken token) { Debug.Assert(String.IsNullOrWhiteSpace(path) == false, "Передана пустая строка в GetAllImages()"); // List<ImageInformation> result = new List<ImageInformation>(); string[] dirs = null; string[] files = null; try { /* string[]*/ dirs = System.IO.Directory.GetDirectories(path); /* string[]*/ files = System.IO.Directory.GetFiles(path, "*.*").Where((s) => s.ToLower().EndsWith(".jpg") || s.ToLower().EndsWith(".jpeg")).ToArray(); } catch (IOException ioe) { Console.WriteLine(ioe.Message); Trace.WriteLine(ioe.Message); //выясним, не извлекли ли съемный диск DriveInfo drive = new DriveInfo(System.IO.Path.GetPathRoot(path)); if (!drive.IsReady) { Console.WriteLine("Диск " + drive.Name + " был извлечен, или содержит ошибки, мешаюшие поиску"); Trace.WriteLine("Диск " + drive.Name + " был извлечен, или содержит ошибки, мешаюшие поиску"); return /*result*/; } if (dirs == null || files == null) { Trace.WriteLine("Массивы со списком файлов или папок - null"); return /*result*/; } } ChangeFolder?.Invoke(new SearchChangeFolderEventArgs(path, files.Length)); foreach (var f in files) { if (token.IsCancellationRequested) { return;// result; } try { var dirsPhoto = MetadataExtractor.ImageMetadataReader.ReadMetadata(Path.GetFullPath(f)); if (isMatch(f, dirsPhoto, iso, date, et, ep, or, isDSC, camName, isManualWhiteBalance, isFlash, isGeo, isEdit)) { ImageInformation ciexif = new ImageInformation(f, dirsPhoto); // result.Add(ciexif); NewFile?.Invoke(new SearchNewFileEventArgs(ciexif)); } } catch (ImageProcessingException ipe) { Console.WriteLine(ipe.Message); Trace.WriteLine(ipe.Message); } catch (IOException ioe) { Console.WriteLine(ioe.Message); Trace.WriteLine(ioe.Message); //выясним, не извлекли ли съемный диск DriveInfo drive = new DriveInfo(System.IO.Path.GetPathRoot(f)); if (!drive.IsReady) { Console.WriteLine("Диск " + drive.Name + " был извлечен, или содержит ошибки, мешаюшие поиску"); Trace.WriteLine("Диск " + drive.Name + " был извлечен, или содержит ошибки, мешаюшие поиску"); IOFatalError?.Invoke(this, new EventArgs()); return; //result; } } catch (UnauthorizedAccessException uae) { Trace.WriteLine(uae.Message); } } foreach (var d in dirs) { if ((windirSkipFlag == false) && (systemDirectoryScan == false)) { if (d.Contains(Environment.GetFolderPath(Environment.SpecialFolder.Windows))) { Trace.WriteLine("Пропуск системного каталога..."); windirSkipFlag = true; continue; } } if (token.IsCancellationRequested) { return;// result; } try { //result.AddRange(GetImagesUponMyCriteria(d,iso,date,et,ep,or,isDSC, camName, isManualWhiteBalance,isFlash,isGeo,isEdit, token)); GetImagesUponMyCriteria(d, iso, date, et, ep, or, isDSC, camName, isManualWhiteBalance, isFlash, isGeo, isEdit, token); } catch (UnauthorizedAccessException uae) { Trace.WriteLine(uae.Message); } } // return result; }
//---bool-версия 27.08.18 public bool isMatch(string fileName, IReadOnlyList <MetadataExtractor.Directory> imgExif, ISO iso, Date date, ExposureTime et, ExposureProgram ep, Orientation or, bool isDSC, string camName, bool isManualWhiteBalance, bool isFlash, bool isGeo, bool isEdit /* CancellationToken token*/) { if (iso == null && date == null && et == null && camName == null && isDSC == false && isManualWhiteBalance == false && isFlash == false && isGeo == false && isEdit == false && ep == ExposureProgram.Any && or == Orientation.Any) { return(true); // критериев нет, подойдет любое } var subdir = imgExif.OfType <ExifSubIfdDirectory>().FirstOrDefault(); var dir = imgExif.OfType <ExifIfd0Directory>().FirstOrDefault(); if (subdir == null && dir == null) // нет нужных метаданыых { Trace.WriteLine(fileName + ": нет метаданных"); return(false); } if (iso != null) //ISO { if (subdir == null) { return(false); } Debug.Assert(iso.minISO <= iso.maxISO, "Минимальное ISO больше максимального"); try { if (!subdir.ContainsTag(ExifDirectoryBase.TagIsoEquivalent)) { return(false); } ushort iIso = subdir.GetUInt16(ExifDirectoryBase.TagIsoEquivalent); if (!((iIso >= iso.minISO) && (iIso <= iso.maxISO))) { return(false); } } catch (MetadataException me) { Trace.WriteLine(fileName + " " + me.Message); return(false); } } if (et != null) //время выдержки { if (subdir == null) { return(false); } try { if (!subdir.ContainsTag(ExifDirectoryBase.TagExposureTime)) { return(false); } Rational expTime = subdir.GetRational(ExifDirectoryBase.TagExposureTime); double dExpTime = expTime.ToDouble(); double dMinET = et.minET.ToDouble(); double dMaxET = et.maxET.ToDouble(); Debug.Assert(dMinET <= dMaxET, "Минимальная выдержка больше минимальной"); if (!((dExpTime >= dMinET) && (dExpTime <= dMaxET))) { return(false); } } catch (MetadataException me) { Trace.WriteLine(fileName + " " + me.Message); return(false); } } if (ep != ExposureProgram.Any) //программа экспозиции { if (subdir == null) { return(false); } try { ushort eProgram = subdir.GetUInt16(ExifDirectoryBase.TagExposureProgram); if (eProgram != (ushort)ep) { return(false); } } catch (MetadataException me) { Trace.WriteLine(fileName + " " + me.Message); return(false); } } if (or != Orientation.Any) //ориентация изображения { if (dir == null) { return(false); } try { // var ifd0dir = imgExif.OfType<ExifIfd0Directory>().FirstOrDefault(); if (!dir.ContainsTag(ExifDirectoryBase.TagOrientation)) { return(false); } ushort orient = dir.GetUInt16(ExifDirectoryBase.TagOrientation); if (or == Orientation.Horizonatal) { if (!(orient > 0 && orient <= 4)) { return(false); } } if (or == Orientation.Vertical) { if (!(orient > 4 && orient <= 8)) { return(false); } } } catch (Exception e) { Trace.WriteLine(fileName + " " + e.Message); return(false); } } if (isDSC) //источник сканирования { if (subdir == null) { return(false); } try { if (!subdir.ContainsTag(ExifDirectoryBase.TagFileSource)) { return(false); } ushort fs = subdir.GetUInt16(ExifDirectoryBase.TagFileSource); if (fs != 3) { return(false); } } catch (Exception e) { Trace.WriteLine(fileName + " " + e.Message); return(false); } } if (camName != null) //камера { Debug.Assert(!string.IsNullOrWhiteSpace(camName), "Пришло пустое имя камеры"); if (dir == null) { return(false); } try { // var subifd0dir = imgExif.OfType<ExifIfd0Directory>().FirstOrDefault(); if (!dir.ContainsTag(ExifIfd0Directory.TagMake)) { return(false); } string cam = dir.GetDescription(ExifIfd0Directory.TagMake).ToLower(); if (!(cam.Contains(camName.ToLower()))) { return(false); } } catch (Exception e) { Trace.WriteLine(fileName + " " + e.Message); return(false); } } if (date != null) //дата { Debug.Assert(date.minDT <= date.maxDT, "Конечная дата раньше начальной"); if (subdir == null) { return(false); } try { if (!subdir.ContainsTag(ExifDirectoryBase.TagDateTimeOriginal)) { return(false); } DateTime dDate = subdir.GetDateTime(ExifDirectoryBase.TagDateTimeOriginal); dDate = dDate.Date; if (!((dDate >= date.minDT) && (dDate <= date.maxDT))) { return(false); } } catch (MetadataException me) { Trace.WriteLine(fileName + " " + me.Message); return(false); } } if (isManualWhiteBalance) //баланс белого { if (subdir == null) { return(false); } try { if (!subdir.ContainsTag(ExifDirectoryBase.TagWhiteBalanceMode)) { return(false); } ushort whiteBalance = subdir.GetUInt16(ExifDirectoryBase.TagWhiteBalanceMode); if (!(whiteBalance == 1)) { return(false); } } catch (MetadataException me) { Trace.WriteLine(fileName + " " + me.Message); return(false); } } if (isFlash) //наличие вспышки { if (subdir == null) { return(false); } try { if (!subdir.ContainsTag(ExifDirectoryBase.TagFlash)) { return(false); } ushort iFlash = subdir.GetUInt16(ExifDirectoryBase.TagFlash); if (!((iFlash & 0x1) == 1)) { return(false); } } catch (MetadataException me) { Trace.WriteLine(fileName + " " + me.Message); return(false); } } if (isGeo) //наличие геометки { var gpsdir = imgExif.OfType <GpsDirectory>().FirstOrDefault(); if (gpsdir == null) { return(false); } else { if (gpsdir.GetGeoLocation() == null) { return(false); } } } if (isEdit) //редактирован { try { if (!dir.ContainsTag(ExifDirectoryBase.TagSoftware)) { return(false); } string softWare = dir?.GetDescription(ExifDirectoryBase.TagSoftware); string[] soft = { "gimp", "photoshop", "lightroom", "luminar", "affinity", "paint", "krita", "pinta", "picasa", "movavi", "pixbuilder" }; if (softWare == null) { return(false); } else { bool edit_flag = false; foreach (var s in soft) { if (softWare.ToLower().Contains(s) == true) { edit_flag = true; continue; } } if (edit_flag == false) { return(false); } } } catch (MetadataException me) { Trace.WriteLine(fileName + " " + me.Message); return(false); } } return(true); }
/* главная функция поиска всех изображений по заданному пути */ public async Task /*Task<List<ImageInformation>>*/ GetImagesWithMyParams(ISO iso, Date date, ExposureTime et, ExposureProgram ep, Orientation or, bool isDSC, string camName, bool isManualWhiteBalance, bool isFlash, bool isGeo, bool isEdit, CancellationToken token) { if (!allDrives) { Trace.WriteLine("Начат поиск в " + path); /* return*/ await Task.Run(() => /*ImageList = */ GetImagesUponMyCriteria(path, iso, date, et, ep, or, isDSC, camName, isManualWhiteBalance, isFlash, isGeo, isEdit, token), token); } else { Trace.WriteLine("Начат поиск по всему компьютеру"); DriveInfo[] readyDrives = DriveInfo.GetDrives().Where((d) => d.IsReady).ToArray(); // ImageList = new List<ImageInformation>(50); /*return*/ await Task.Run(() => { foreach (var d in readyDrives) { if (token.IsCancellationRequested) { break; } if (d.IsReady) { Trace.WriteLine("Поиск по диску " + d.RootDirectory.FullName); // ImageList.AddRange(GetImagesUponMyCriteria(d.RootDirectory.FullName, iso, date, et, ep, or, isDSC, camName, isManualWhiteBalance, isFlash, isGeo, isEdit, token)); GetImagesUponMyCriteria(d.RootDirectory.FullName, iso, date, et, ep, or, isDSC, camName, isManualWhiteBalance, isFlash, isGeo, isEdit, token); } else { Trace.WriteLine("Диск " + d.Name + " был доступен в начале сканирования, но оказался недоступен в дальнейшем. Не сканировался."); } } // return ImageList; }, token); } }
private async void StartSearch(object sender, EventArgs e) { if (System.IO.Directory.Exists(pathTextBox.Text) || allDrivesCheckBox.Checked) { //формирование критериев поиска Date date = null; ISO iso = null; ExposureProgram ep = ExposureProgram.Any; Orientation or = Orientation.Any; ExposureTime et = null; bool isDSC = false; string camName = null; bool isManualWhiteBalance = false; bool isFlashOn = false; bool isGPS = false; bool isEdit = false; //--------------------------------- searchSettings.Clear(); //------ДАТА if (datesCheckBox.Checked == true) { if (endDateTimePicker.Value.Date < startDateTimePicker.Value.Date) { MessageBox.Show("Неверно выставлены настройки поиска по дате. Пожалуйста исправьте."); return; } searchSettings.AppendLine("Поиск по датам: " + startDateTimePicker.Value.ToShortDateString() + " - " + endDateTimePicker.Value.ToShortDateString()); date = new Date(startDateTimePicker.Value.Date, endDateTimePicker.Value.Date); } //-----ISO if (ISOCheckBox.Checked) { uint minISO; uint maxISO; bool isMinISOCorrect = uint.TryParse(minISOTextBox.Text, out minISO); bool isMaxISOCorrect = uint.TryParse(maxISOTextBox.Text, out maxISO); if (isMinISOCorrect == true && isMaxISOCorrect == true) { if (maxISO < minISO) { MessageBox.Show("Неверно выставлены настройки поиска по ISO. Пожалуйста исправьте."); return; } if (maxISO > uint.MaxValue) { MessageBox.Show("Неверно выставлены настройки поиска по ISO. Пожалуйста исправьте."); return; } searchSettings.AppendLine("Поиск по ISO: " + minISO + " - " + maxISO); iso = new ISO(minISO, maxISO); } else { MessageBox.Show("Неверно выставлены настройки поиска по ISO. Пожалуйста исправьте."); return; } } //-----ВЫДЕРЖКА if (ExposureTimeCheckBox.Checked) { Rational minExposureTime; Rational maxExposureTime; bool isMinValueCorrect = GetRationalFromString(minExposureTimeTextBox.Text, out minExposureTime); bool isMaxValueCorrect = GetRationalFromString(maxExposureTimeTextBox.Text, out maxExposureTime); if (isMinValueCorrect == true && isMaxValueCorrect == true) { //теперь проверим на нижние и верхние границы double min = minExposureTime.ToDouble(); double max = maxExposureTime.ToDouble(); if (!(min <= max + double.Epsilon)) { MessageBox.Show("Неверно выставлены настройки поиска по выдержке. Пожалуйста исправьте."); return; } searchSettings.AppendLine("Поиск по выдержке: " + minExposureTime.ToSimpleString() + " - " + maxExposureTime.ToSimpleString()); et = new ExposureTime(minExposureTime, maxExposureTime); } else { MessageBox.Show("Неверно выставлены настройки поиска по выдержке. Пожалуйста исправьте."); return; } } //---МОДЕЛЬ КАМЕРЫ if (cameraCheckBox.Checked) { if (!string.IsNullOrWhiteSpace(CameraTextBox.Text)) { camName = CameraTextBox.Text.Trim().Split(' ')[0]; searchSettings.AppendLine("Поиск по модели камеры: " + camName); } else { MessageBox.Show("Неверно выставлены настройки поиска по производителю камеры. Пожалуйста исправьте."); return; } } if (WhiteBalanceСheckBox.Checked) { isManualWhiteBalance = true; searchSettings.AppendLine("Поиск снимков с ручным балансом белого"); } if (flashOnCheckBox.Checked) { isFlashOn = true; searchSettings.AppendLine("Поиск снимков со вспышкой"); } if (gpsCheckBox.Checked) { isGPS = true; searchSettings.AppendLine("Поиск снимков с геоданными"); } if (EditCheckBox.Checked) { isEdit = true; searchSettings.AppendLine("Поиск редактированных снимков"); } if (ExposureProgramCheckBox.Checked) { if (exposureProgramComboBox.SelectedIndex == -1) { MessageBox.Show("Неверно выставлены настройки поиска по программе управления экспозицией. Пожалуйста исправьте."); return; } ep = (ExposureProgram)exposureProgramComboBox.SelectedIndex + 1; } //источник изображения if (DSCCheckBox.Checked) { isDSC = true; searchSettings.AppendLine("Поиск изображений сделанных только на фотоаппарат"); } if (orientationСheckBox.Checked) { int sel = orientationComboBox.SelectedIndex; if (sel == -1) { MessageBox.Show("Неверно выставлены настройки поиска по ориентации. Пожалуйста исправьте."); return; } switch (sel) { case 0: or = Orientation.Horizonatal; break; case 1: or = Orientation.Vertical; break; } } if (allDrivesCheckBox.Checked) { searchSettings.AppendLine("Поиск изображений: весь компьютер"); finder = new Search(!skipWinDirectoryCheckBox.Checked); } else { searchSettings.AppendLine("Поиск изображений в: " + pathTextBox.Text); finder = new Search(pathTextBox.Text, !skipWinDirectoryCheckBox.Checked); } finder.ChangeFolder += ChangeStatus; finder.NewFile += newFileFinded; status.Text = "Выполняется поиск..."; //---кнопка меняется на "стоп" startButton.Text = "Остановить поиск"; startButton.Click -= StartSearch; startButton.Click += Stop; searchToolStripMenuItem.Text = "Остановить поиск"; searchToolStripMenuItem.Click -= StartSearch; searchToolStripMenuItem.Click += Stop; filesListBox.Items.Clear(); imageInformationTextBox.Clear(); pictureBox.Image = null; imageWorks?.img?.Dispose(); //---пуск задачи---// cancelTokenSource = new CancellationTokenSource(); token = cancelTokenSource.Token; isWorking = true; await finder.GetImagesWithMyParams(iso, date, et, ep, or, isDSC, camName, isManualWhiteBalance, isFlashOn, isGPS, isEdit, token); isWorking = false; // MessageBox.Show(searchSettings.ToString() + "\nНайдено изображений: " + imagesBindingSource.Count); //------------------// status.Text = "Поиск окончен"; // imagesBindingSource.DataSource = images; //---кнопка меняется на старт startButton.Text = "Начать поиск"; startButton.Click += StartSearch; startButton.Click -= Stop; searchToolStripMenuItem.Text = "Начать поиск"; searchToolStripMenuItem.Click += StartSearch; searchToolStripMenuItem.Click -= Stop; if (WindowState == FormWindowState.Minimized) { //мигание значка на панели задач, когда поиск завершен (если окно свернуто) FLASHWINFO fwi = new FLASHWINFO(); fwi.cbSize = Marshal.SizeOf(fwi); fwi.hwnd = Handle; fwi.dwFlags = 0x00000002; fwi.dwTimeout = 0; fwi.uCount = 5; FlashWindowEx(ref fwi); } #if DEBUG #region Tests Console.WriteLine("Tests..."); //---тестируем поиск по датам, удалить в релизе if (datesCheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); var dbdate = sdir.GetDateTime(ExifDirectoryBase.TagDateTimeOriginal).Date; Debug.Assert((dbdate >= startDateTimePicker.Value.Date) && (dbdate <= endDateTimePicker.Value.Date), "DateTime Bug: " + ((ImageInformation)i).FileName); } } //---тестируем баланс белого (ручной) if (WhiteBalanceСheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); var wb = sdir.GetUInt16(ExifDirectoryBase.TagWhiteBalanceMode); Debug.Assert(wb == 1, "White Balance Bug: " + ((ImageInformation)i).FileName); } } //---тестируем источник снимка if (DSCCheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); var dsc = sdir.GetUInt16(ExifDirectoryBase.TagFileSource); Debug.Assert(dsc == 3, " DSC Bug: " + ((ImageInformation)i).FileName); } } //---тестируем модель камеры, удалить в релизе if (cameraCheckBox.Checked) { foreach (var x in filesListBox.Items) { if (x is ImageInformation) { var sdir = ((ImageInformation)x).Directories.OfType <ExifIfd0Directory>().FirstOrDefault(); var cam = sdir.GetDescription(ExifIfd0Directory.TagMake); cam = cam.ToLower(); Debug.Assert(cam.Contains(camName.ToLower()), "Неверно отработал поиск по камере" + ((ImageInformation)x).FileName); } } } //---тестируем выдержку, удалить в релизе if (ExposureTimeCheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); Rational minExposureTime; Rational maxExposureTime; bool isMinValueCorrect = GetRationalFromString(minExposureTimeTextBox.Text, out minExposureTime); bool isMaxValueCorrect = GetRationalFromString(maxExposureTimeTextBox.Text, out maxExposureTime); if (isMinValueCorrect == true && isMaxValueCorrect == true) { double min = minExposureTime.ToDouble(); double max = maxExposureTime.ToDouble(); double exptime = sdir.GetRational(ExifDirectoryBase.TagExposureTime).ToDouble(); Debug.Assert((exptime >= min - double.Epsilon) && (exptime <= max + double.Epsilon), "Exposure Bug: " + ((ImageInformation)i).FileName + " " + exptime); } } } //тестируем ISO if (ISOCheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); var dbiso = sdir.GetUInt16(ExifDirectoryBase.TagIsoEquivalent); Debug.Assert((dbiso >= ushort.Parse(minISOTextBox.Text)) && (dbiso <= ushort.Parse(maxISOTextBox.Text)), "ISO Bug: " + ((ImageInformation)i).FileName); } } //тестируем вспышку if (flashOnCheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); ushort flash = sdir.GetUInt16(ExifDirectoryBase.TagFlash); Debug.Assert((flash & 0x1) != 0, "Flash Bug: " + ((ImageInformation)i).FileName + "Flash value: " + flash); } } //тестируем программу экспозиции if (ExposureProgramCheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); ushort eProgram = sdir.GetUInt16(ExifDirectoryBase.TagExposureProgram); Debug.Assert(eProgram == (int)exposureProgramComboBox.SelectedIndex + 1, "Exposure Program Bug: " + ((ImageInformation)i).FileName + " EP Value: " + eProgram); } } //тестируем ориентацию if (ExposureProgramCheckBox.Checked) { foreach (var i in filesListBox.Items) { var sdir = ((ImageInformation)i).Directories.OfType <ExifIfd0Directory>().FirstOrDefault(); ushort orient = sdir.GetUInt16(ExifDirectoryBase.TagOrientation); if (or == Orientation.Horizonatal) { Debug.Assert(orient <= 4, "Orientation bug"); } if (or == Orientation.Vertical) { Debug.Assert(orient > 4, "Orientation bug"); } } } #endregion #endif } else { MessageBox.Show("Путь указан неверно!", "WhereIsMyPhoto"); } }