21. ПРЕОБРАЗОВАНИЕ КАРТИНОК

В главе 8 написано, что среди операций с файлами есть операции, позволяющие получать картинки в сыром виде, то есть в виде матрицы точек, где каждая точка определяется одним (для серых картинок) или тремя (для цветных картинок) байтами. Для получения файла картинки в сыром виде из стандартного графического формата (jpg, gif, png) нужно воспользоваться операциями #f [op=tobm;] и #f [op=tocm;]. А для того, чтобы конвертировать матрицу точек опять в формат jpg можно воспользоваться командами #w [op=im; mod=8; sav=-1;] и #w [op=im; mod=24; sav=-1;]. Для конвертирования картинки в png формат нужно спасти ее в память и затем воспользоваться командой #f [op=topng;]. Формат картинки в виде матрицы точек позволяет выполнять над ней побайтные математические операции. Точнее, операции производятся над файлами и какую картинку они содержат не имеет значения. Такая команда называется #bi (byte image). Она имеет несколько операций.

Перед операцией байты конвертируются в целые числа в диапазоне от 0 до 255. Хотя байты считываются и записываются правильным образом, мы здесь для простоты будем называть байтами именно положительные целые числа в указанном диапазоне, то есть ASCII-коды. После операции все отрицательные числа обнуляются, а все числа больше 255 принимают значение 255. Случаи, не соответствующие этому правилу, будут оговариваться особо. Естественно, что операции имеют смысл лишь в том случае, когда файл содержит данные картинки. Другие применения пока не просматриваются. Картинка может быть либо цветной (три байта на одну точку), либо серой (один байт на одну точку). Для данных операций это не существенно. Побайтные операции не меняют содержание картинки, но позволяют существенно изменить общее освещение. Можно изменить яркость, контраст и т. д. На данный момент реализованы операции, описание которых следует ниже в порядке от простого к сложному. В имени операции учитываются только первые 3 знака. Итак

.

 #bi [op=add; rat=; file=; form=;]

Эта операция считывает байты из файла с названием [file], затем прибавляет к каждому байту число, равное значению параметра [rat] и записывает новую картинку в файл с именем [form]. При этом исходный файл не изменяется. Параметр может иметь как положительное, так и отрицательное значение.

.

 #bi [op=mul; rat=; file=; form=;]

Эта операция считывает байты из файла с названием [file], затем умножает значение каждого байта на число, равное значению параметра [rat], затем делит на 1000 и берет ближайшее целое значение. Новая картинка записывается в файл с именем [form]. При этом исходный файл не изменяется. Очевидно [rat=1000;] ничего не меняет. Отрицательные значения тоже допустимы. В этом случае выделяется интервал (-255,0) и затем прибавляется 255. Такая операция инверсирует контраст.

.

 #bi [op=inc; file=; form=; bot=; top=;]

Эта операция считывает байты из файла с названием [file], затем изменяет градиент цвета таким образом, что интервал ([bot], [top]) превращается в интервал (0, 255). Предполагается, что 0 < [bot] < [top] < 255. Соответственно числа, значения которых выходят за пределы интервала (0, 255) после преобразования приравниваются граничным значениям - это общее правило. Новая картинка записывается в файл с именем [form]. При этом исходный файл не изменяется.

.

 #bi [op=dec; file=; form=; bot=; top=;]

Эта операция считывает байты из файла с названием [file], затем изменяет градиент цвета таким образом, что интервал (0, 255) превращается в интервал ([bot], [top]). Предполагается, что 0 < [bot] < [top] < 255, поэтому все числа картинки не выходят на пределы интервала (0, 255) после преобразования. Новая картинка записывается в файл с именем [form]. При этом исходный файл не изменяется.

.

 #bi [op=cha; rat=; file=; form=;]

Эта операция считывает байты из файла с названием [file], затем умножает значение контраста каждого байта на число, равное значению параметра [rat], деленному на 1000 и берет ближайшее целое значение. Контрастом называется отклонение значения байта от среднего значения. Новое значение контраста прибавляется к среднему значению и новая картинка записывается в файл с именем [form]. При этом исходный файл не изменяется. Очевидно [rat=1000;] ничего не меняет. Отрицательные значения тоже допустимы.

.

 #bi [op=pow; rat=; file=; form=;]

Эта операция считывает байты из файла с названием [file]. Новая картинка записывается в файл с именем [form]. Операция вычисляет функцию f = 255*(b/255)^(p/1000), где b - исходное значение байта, f - новое значение байта, p - значение параметра [rat], которое должно быть равно 1000 для тождественного преобразования. Значения p меньшие или большие 1000 приводят к неоднородному градиенту цвета, но не меняют интервал изменения значений цветов.

.

 #bi [op=log; bot=; top=; file=; form=;]

Эта операция считывает байты из файла с названием [file]. Новая картинка записывается в файл с именем [form]. Операция вычисляет функцию f = (log(b+p1)-log(255+p2-b)+f1)*f2, где b - исходное значение байта, f - новое значение байта, f1=log(255+p2)-log(p1), f2=255/(log(255+p1)-log(p2)+f1), p1 - значение параметра [bot], p2 - значение параметра [top]. Оба значения должны быть больше 0. Эта операция не меняет интервал изменения значений, но неоднородно меняет градиент цвета, причем она как бы уменьшает градиент в центральной части значений, что соответсвует гладкому варианту операции "dec".

.

 #bi [op=exp; bot=; top; file=; form=;]

Эта операция считывает байты из файла с названием [file]. Новая картинка записывается в файл с именем [form]. Эта операция вычисляет функцию f = 255/(1+exp((p2-b)/p1)), где b - исходное значение байта, f - новое значение байта, p2-p1 - значение параметра [bot], p2+p1 - значение параметра [top]. Предполагается, что 0 < bot < top < 255 и что разность [top] - [bot] является четным числом. Эта операция не меняет интервал изменения значений, но неоднородно меняет градиент цвета, причем она как бы увеличивает градиент в центральной части значений, что соответствует гладкому аналогу операции "inc".

Следующие операции выполняются сразу над несколькими файлами. Они позволяют реализовать комплексное преобразование картинки.

.

 #bi [op=sup; mo=; file=; form=; bot=; top=; b=;] FT

Эта операция вычисляет суперпозицию нескольких картинок, записанных в несколько файлов. Новая картинка записывается в файл с именем [form]. Размер этого файла равен размеру первого файла в суперпозиции. Исходно все байты этого файла до суммирования равны байтам первого файла, умноженного на первый коэффициент. Другие исходные файлы могут иметь разные размеры. Если размер файла меньше первого, то весь файл целиком умножится на его коэффициент и прибавится. Если, наоборот, он больше, то будет взята только часть файла, равная размеру первого, которая умножится на свой коэффициент и прибавится. Коэффициенты суперпозиции должны быть записаны в целый массива i(), причем параметр [b] указывает на индекс первого элемента, отрицательные числа возможны и указывают на вычитание. Имена исходных файлов могут быть заданы двумя способами.
Если [file=list;], то список всех имен файлов должен быть задан в аргументе команды - форматированном тексте. Имена файлов разделяются символом вертикальной черты [|], соответственно число файлов равно числу разделителей плюс 1. Имена могут быть произвольными. Например, команда
#d 3 i(1) 1 2 3 #bi [op=sup; mo=0; file=list; form=sum.rif; b=1;] 1.rif|2.rif|3.rif\E
будет складывать байты по правилу bs = b1*1 + b2*2 + b3*3. Результат суммирования всех картинок зависит от значения параметра [mod]. Если [mo=0;], то все отрицательные значения, если они есть, обнуляются, а все положительные значения умножаются на коэффициент таким образом, чтобы максимальное значение равнялось 255. Если [mo=1;], то весь интервал значений, включая и отрицательные, линейно масштабируется на интервал (0, 255).
Если [file=order;], то способ задания имен файлов отличается от указанного выше. Предполагается, что все имена различаются целыми номерами, например, my05.rif, my06.rif, my07.rif и так далее. Поэтому в аргументе команды задается только базовое имя файла, то есть для указанного выше примера, это my00.rif, а первый и последний номера задаются параметрами [bot] и [top]. Номера автоматически вставляются в имена файлов перед точкой. Все остальное делается так же, как и в указанном выше случае. Пример
#d 3 i(1) 1 2 3 #bi [op=sup; mo=0; file=order; form=sum.mcm; b=1; bot=1; top=3;] my00.rif\E
Суммирование файлов, например, удобно при обработке экспериментальных данных, когда детектор не может делать большую экспозицию и приходиться много раз снимать одно и то же. В этом случае все файлы имеют одинаковый размер. Эта операция также может быть использована для создания спец-эффектов на картинках при смешивании разных картинок. Реальный интерес представляет сложение картинок с одинаковым числом пикселей по ширине. Если картинки имеют разную ширину, то более мелкие картинки "размазываются" по более крупным и теряют свою информативность. В этом случае надо действовать более сложным образом, а именно, вырезать фрагмент из большой картинки с таким же размером как и маленькая, проводить сложение с фрагментом, а потом накладывать результат на большую картинку.

.

 #bi [op=pro; file=; form=; bot=; top=;] FT

Эта операция производит перемножение нескольких картинок, записанных в несколько файлов. Новая картинка записывается в файл с именем [form]. Размер этого файла равен размеру первого файла в списке исходных файлов. Исходно все байты этого файла до операции равны байтам первого файла. Другие исходные файлы могут иметь разные размеры. Если размер файла меньше первого, то весь файл целиком побайтно умножится на новую картинку. Если, наоборот, он больше, то будет взята только часть файла, равная размеру первого, побайтно умножится на новую картинку. После перемножения всех картинок значения новой картинки умножаются на множитель таким образом, чтобы максимальное значение равнялось 255. Способы задания исходных файлов такие же, как и в предыдущей операции.

.

 #bi [op=div; file=; form=; bot=; top=;] FT

Эта операция производит деление двух картинок, записанных в два исходных файла. Новая картинка записывается в файл с именем [form]. Размер этого файла равен размеру первого файла в списке исходных файлов. Исходно все байты этого файла до операции равны байтам первого файла. Второй исходный файл может иметь разные размеры. Если размер файла меньше первого, новая картинка разделится на все байты файла целиком. Если, наоборот, он больше, то будет взята только часть файла, равная размеру первого, и новая картинка разделится на все байты этой части. После деления картинок значения новой картинки умножаются на множитель таким образом, чтобы максимальное значение равнялось 255. Способы задания исходных файлов такие же, как и в предыдущих операциях, но учитываются только первые два файла. Если какой-либо байт второй картинки равен 0, то его значение заменяется на 1, чтобы исключить деление на 0.

Умножение файлов можно использовать для выделения каких-то кусков, если во втором файле будут только нули и единицы. Какие эффекты можно получить при делении пока не ясно, но была бы возможность, а применение всегда найдется.
.