En las siguientes lineas veremos como mostrar images almacenadas en columnas BLOB o tambien en algunos casos usando una URL.
La demo de estas diferentes formas la pueden encontrar aqui.


1 Region FORM (blob)
Empezaremos usando la region tipo FORM, el cual hace uso de cosas nativas para el tipo de Item es display image.
Lo importante sera definir el source de la imagen, file name y mime type.

2. HTML <img> y APEX item
Para esta forma necesitaremos un item adicional y un computation, el Item servira para guardar la URL, el computation deberá tener el siguiente código:
select apex_util.get_blob_file_src('P1080_PRODUCT_IMAGE', product_id )
from demo_product_info
where product_id = :P1080_PRODUCT_ID;
Y la region mostrara la informacion de la imagen de la siguiente forma
<img src="&P1080_IMAGE_URL.">

3. APEX Item con URL (no blob)
Ya que tenemos un ITEM con la URL de la imagen, usaremos esto para mostrarlo en un ITEM normal.
Lo principal es seleccionar el source del item y el typo de item

4. Imagen en Reporte
En esta forma mostraremos la imagen en un reporte
En esta forma, la imagen sera mostrada en un report. De igual forma que la primera podriamos usar el source de blob directo del query o si tenemos un ITEM con el URL tambien es valido, veamos.
select PRODUCT_ID,
PRODUCT_NAME,
dbms_lob.getlength(PRODUCT_IMAGE) PRODUCT_IMAGE,
null product_image_url_2,
'f?p='|| v('APP_ID') ||':1:'||v('APP_SESSION')||':APPLICATION_PROCESS=AJAX_GET_PRODUCT_IMAGE:::G_PRODUCT_IMAGE_ID:'||PRODUCT_ID product_3,
null product_4
from DEMO_PRODUCT_INFO
where product_id = :P1080_PRODUCT_ID


5. Usando Application Process
Esta form para mi la considero mas eficiente, mas customizable y mas facil de usar en varios sitios.
Sin embargo podria requerir un poco mas de trabajo en la implementación.
Primero necesitamos un Application Item, por ejemplo G_PRODUCT_IMAGE_ID y la seguridad unrestricted, por que se enviara a travez de URl el valor.
Segundo necesitaremos un proceso ajax a nivel de applicacion, con el siguiente código.

Como pueden ver agrege un select adicional que me permite tener una imagen default en caso no exista la primera, aqui se pueden trabajar mas customizaciones a nivel PLSQL
declare
l_lob BLOB;
l_length NUMBER;
l_mimetype VARCHAR2(2000);
l_filename VARCHAR2(2000);
l_product_id number;
begin
l_product_id := v('G_PRODUCT_IMAGE_ID');
begin
select product_image
, null mimetype
, null filename
into l_lob
, l_mimetype
, l_filename
from demo_product_info
where nvl(dbms_lob.getlength(product_image),0) > 0
and product_id = l_product_id;
exception
when no_data_found then
null;
/* select file_content
, mime_type
, file_name
into l_lob
, l_mimetype
, l_filename
from APEX_WORKSPACE_STATIC_FILES
where FILE_NAME = 'xxxxxx'; */
end;
--
l_length := DBMS_LOB.getlength(l_lob);
--
htp.flush;
htp.init;
--
owa_util.mime_header(nvl(l_mimetype,'application/octet'), FALSE);
htp.p('Content-length:' || l_length);
htp.p('Content-Disposition:inline;filename="' || l_filename || '"');
--
-- close the headers
owa_util.http_header_close;
--
-- download the BLOB
wpg_docload.download_file(l_lob);
apex_application.stop_apex_engine;
--
exception
WHEN apex_application.e_stop_apex_engine THEN
NULL;
when OTHERS then
null;
end;
Y ahora solo nos falta hacer uso de esta application process de la siguiente forma en cualquier item que soporte la URL
<img src="f?p=&APP_ID.:1:&APP_SESSION.:APPLICATION_PROCESS=AJAX_GET_PRODUCT_IMAGE:::G_PRODUCT_IMAGE_ID:&P1080_PRODUCT_ID.">
o en un reporte


Las referencias que use estan aqui:
https://docs.oracle.com/en/database/oracle/apex/22.1/aeapi/GET_BLOB_FILE_SRC-Function.html
https://joelkallman.blogspot.com/2014/03/yet-another-post-how-to-link-to.html