Для работы с мультимедиа объектами в БД 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;