Найти изображение наибольшей площади
Развлекаюсь с игрушкой, которую изготовил в предыущем посте (Как переложить файловую папку в базу) и не могу нарадоваться (как известно, сам себя не похвалишь... J). Загрузил в базу фотоархив (покамест без содержания, только метаданные файлов):
select * into t from Dir('\\192.168.0.1\c$\My Documents\Photos\MS', 0)
Скрипт 1
Так находится самая здоровая картинка:
select top 1 fullName, size from t order by size desc
Скрипт 2
Ба, скажете вы, она и в эксплорере находится влет. В текущем фолдере – да. А если брать scope со вложенными подфолдерами? Я человек аскетичный и привык пользоваться только штатным Windows Explorer, но полагаю, что не всякий Коммандер умеет рыть в глубину.
Или рассмотрим вот еще пример – см. сабж. Предположим, требуется отыскать в архивном загашнике максимально масштабное полотно. Известно, что у любой картинки есть ширина и высота, и эти свойства доступны в эксплорере наравне с массой других, не менее интересных.
рис.1
Можно упорядочить фотки по ширине, можно по высоте, но сделать вычисляемое поле в виде произведения, чтобы упорядочить по нему, к сожалению, не представляется возможным. Есть еще замечательное поле Dimensions, но оно строковое, а хотелось бы иметь численный результат этого произведения. Однако если это невозможно в эксплорере, давайте сделаем в SQL Server, ибо собирая файлы в базу (Скрипт 1), функция Dir, яже писана в предыдущем посте, до кучи зачерпнула эти свойства и теперь они лежат в XML-колонке Properties:
select properties.query('for $x in ("Bit depth", "Camera maker", "Camera model", "Dimensions", "Exposure time", "Flash mode", "Focal length", "F-stop", "Height", "Horizontal resolution", "ISO speed", "Max aperture", "Width")
return /Props/Prop[@Name = $x]') from t where fullName like '%p7200124.jpg'
Скрипт 3
рис.2
Не составляет труда их оттеда достать:
select
properties.value('(/Props/Prop[@Name="Width"])[1]', 'nvarchar(30)'),
properties.value('(/Props/Prop[@Name="Height"])[1]', 'nvarchar(30)')
from t
where fullName like '%p7200124.jpg'
------------------------------ ------------------------------
1024 pixels 768 pixels
(1 row(s) affected)
Скрипт 4
Сзади им надо отрезать слово pixels, а спереди – какую-то непонятную порнографию, которая на Скрипт 4 не видна, потому что отвалилась при копировании, но просматривается на рис.2. В итоге получаем:
;with
cte1([file], width, height) as (
select top 100 FullName,
properties.value('(/Props/Prop[@Name="Width"])[1]', 'nvarchar(30)'),
properties.value('(/Props/Prop[@Name="Height"])[1]', 'nvarchar(30)')
from t
where isDir = 0 and id.IsDescendantOf((select id from t where fullname = '\\192.168.0.1\c$\My Documents\Photos\MS\MGB''01 Miami')) = 1
)
, cte2([file], width, height) as (
select [file], cast(substring(width, 2, charindex(' ', width) - 2) as int),
cast(substring(height, 2, charindex(' ', height) - 2) as int)
from cte1
where width <> '' and height <> ''
)
select * from cte2 order by width * height desc
Скрипт 5
Запрос достает файлы (isDir = 0) из заданного фолдера (IsDescendantOf), лежащие непосредственно под ним или в подфолдерах какой угодно глубины (потому что я не ставил ограничения на GetLevel), имеющие непустоты в атрибутах width и height, получает из ширины и высоты численные значения и упорядочивает результат по убыванию площади, сиречь произведения ширины на высоту.
рис.3
В качестве закрепления материала в качестве самостоятельного упражнения в целях повышения качества усвоения предлагается посчитать площадь, взяв ширину и высоту из атрибута Dimensions.
Попутно сделайте то же на Powershell, не прибегая к загрузке данных в SQL Server.