Share via


Найти изображение наибольшей площади

Развлекаюсь с игрушкой, которую изготовил в предыущем посте (Как переложить файловую папку в базу) и не могу нарадоваться (как известно, сам себя не похвалишь... 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, но полагаю, что не всякий Коммандер умеет рыть в глубину.

Или рассмотрим вот еще пример – см. сабж. Предположим, требуется отыскать в архивном загашнике максимально масштабное полотно. Известно, что у любой картинки есть ширина и высота, и эти свойства доступны в эксплорере наравне с массой других, не менее интересных.

image001

рис.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

image003

рис.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, получает из ширины и высоты численные значения и упорядочивает результат по убыванию площади, сиречь произведения ширины на высоту.

 

image005

рис.3

В качестве закрепления материала в качестве самостоятельного упражнения в целях повышения качества усвоения предлагается посчитать площадь, взяв ширину и высоту из атрибута Dimensions.

Попутно сделайте то же на Powershell, не прибегая к загрузке данных в SQL Server.