Для работы с мультимедиа объектами в БД Oracle существует такая замечательная вещь как Oracle Multimedia(изначально interMedia). Это средство позволяет хранить, обрабатывать и использовать мультимедиа-информацию различной природы. Это могут быть изображения, аудио и видеоданные. Для работы с каждым видом информации в Oracle Multimedia присутсвуют специальные объектные типы, позволяющие хранить информацию непосредственно в ячейках обычных таблиц, а также выполнять некоторый набор преобразований.
Для обработки изображений предназначен объектный тип ORDImage. Объекты данного типа позволяют с легкостью загрузить изображение в БД из файловой системы, где функционирует БД Oracle. В таблицах возможно создание полей с типом ORDImage, а следовательно, и хранение данных. Набор методов позволяет извлекать информацию о различных параметрах изображения, например формат, размер, вид сжатия изображения и т.д., а также выполнять элементарные преобразования с помощью методов process() и processCopy() с той лишь разницей, что первый метод изменяет исходные данные, а второй – возвращает копию с выполненными изменениями.
Некоторые нюансы в работе с объектами ORDImage возникают при использовании их только для преобразования изображения. Например, исходная графическая информация хранится в таблице в поле blob. Требуется сделать уменьшенное изображение и записать его в другое поле.
Допустим, исходное изображение хранится в таблице EMPLOYEES, в поле PHOTO. В таблице THUMBS предполагается хранить уменьшенные изображения для использования в каких-либо списках.
Последовательность действий достаточно проста: выбрать из таблицы исходное изображение, создать на его основе объект ORDImage, с помощью processCopy создать уменьшенную копию и записать результат в таблицу назначения. Здесь легко получить ошибку:
ORA-29400: data cartridge error
IMG-00710: unable to write to destination image
ORA-22275: invalid LOB locator specified
Это говорит о том, что для новой копии изображения не было выделено места в памяти. Выделить требуемую память можно как минимум двумя способами.
- создать объект ORDImage на основе заранее выбранного пустого поля из таблицы назначения (THUMBS);
- выделить временную память для обработки с помощью процедуры пакета DBMS_LOB – dbms_lob.createTemporary.
Первый вариант удобен для случаев, аналогичных нашей задаче – извлечь данные, преобразовать, записать в таблицу. Если же результат записывать в таблицу не планируется (например, планируется выгрузка в файл), то предпочтителен второй вариант.
Итак, подводя итог, код для решения поставленной задачи выглядит следующим образом:
declare
oimg ORDImage;
oimg_100 ORDImage := ORDImage.init();
img blob;
img_100 blob;
v_emp number := 101;
begin
-- получение исходного изображения
select PHOTO into img from EMPLOYEES where employee_id = v_emp;
-- создание на основе исходного изображения объекта ORDImage
oimg := ORDSYS.ORDImage(img);
-- выборка записи, в которую предполагается записать копию изображения
-- запись должна быть выбрана в режиме FOR UPDATE
select THMB_100 into img_100 from THUMBS where employee_id = v_emp for update;
-- создание объекта ORDImage, связанного с полем назначения
oimg_100 := ORDSYS.ORDImage(img_100);
-- масштабирование изображения до размеров 100x100 с сохранением пропорций
oimg.processCopy('maxScale=100 100', oimg_100);
update THUMBS set
thmb_100 = oimg_100.getContent()
where employee_id = v_emp;
end;
Вариант для обработки во временной памяти:
declare
oimg ORDImage;
oimg_100 ORDImage := ORDImage.init();
img blob;
img_100 blob;
v_emp number := 101;
begin
-- получение исходного изображения
select PHOTO into img from EMPLOYEES where employee_id = v_emp;
-- создание на основе исходного изображения объекта ORDImage
oimg := ORDSYS.ORDImage(img);
-- выделение временной памяти
dbms_lob.createTemporary(oimg_100.source.localData, true);
oimg.processCopy('maxScale=100 100', oimg_100);
img_100 := oimg_100.getContent();
-- удаление выделенного временного пространства
dbms_lob.freeTemporary(oimg_100.source.localData);
end;
