Skip to Main Content
  • Questions
  • Aggregate BLOBs? (aka making an image)

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Micheal.

Asked: January 06, 2011 - 4:04 pm UTC

Last updated: January 10, 2011 - 7:42 am UTC

Version: 11.2.0

Viewed 1000+ times

You Asked

I know, in 11g, I can use LISTAGG for varchar2(), but does there exist a way to aggregate BLOB data?
(also how do I convert 255 into a single byte== 0xFFh for the BLOB?)

I have an SQL statement that aggregates raw data and returns values that can be used for producing an image. (ie a heat map of the data)
I am currently stuck trying to aggregate the values into a single BLOB value that can then be used by ORDImage as a "foreign image type". (This way, I can then convert it into a standard format like GIF.)

I could use a "for loop dbms_lob.append()", but I figured that would be the wrong way to do it.

many thanks ahead of time.

Michael Kutz

/* simulate results */
create table t_image_raw as
with x_generator as (select level X from dual connect by level <= 100)
,y_generator as (select level Y from dual connect by level <= 30)
,id_generator as (select level img_id from dual connect by level <= 10)
select img_id, X, Y, floor( 255/100 * X ) RED, floor( 255/30 * Y ) GREEN, floor(255/10 * img_id) BLUE
from x_generator, y_generator, id_generator;


create type image_table_t as object (img_id int, img ORDImage, height int, width int);
/

create type image_table_tab as table of image_table_t;
/

create or replace procedure makeHeatMap
as
image_table image_table_tab;
begin
/* magic SQL Here*/
select image_table_t(img_id
,null -- ???
,max(x),max(Y) )
bulk collect into image_table
from (select img_id, x,y, red,green,blue
from T_image_raw order by img_id,x,y)
group by img_id;
-- i'm still working on the section below
for process_me in (select * from table(image_table))
loop
null;
/* process image here similar to this...
process_me.img.setProperties('height=' || process_me.height
|| ' width=' || process_me.width );
process_me.img.process('fileFormat=GIF');
*/
end loop;
/*
merge into report_image_table RT
using (select * from table(image_table)) X
blah ...
*/
end;
/


and Tom said...

... but does there exist a way to aggregate BLOB data? ...

no.

... I could use a "for loop dbms_lob.append()", but I figured that would be the wrong way to do it.
...

that would be the approach to take.

... (also how do I convert 255 into a single byte== 0xFFh for the BLOB?)
...

I don't know what that means.



Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

update

Micheal Kutz, January 07, 2011 - 7:45 pm UTC

Tom,
Thank you for your input.

More searching on the web, I found this:
http://asktom.oracle.com/pls/apexf?p=100:11:0::::P11_QUESTION_ID:229614022562#2081176199386

I tweaked it to take in ORDSYS.SI_COLOR and return ORDSYS.ORDImage format.
(I was having issues converting the INTEGERS into BLOBs appropriately in pure SQL.)
This method takes longer then I expected, but then again, I am calling dbms_lob.append() 30*100*10 times.
(averaging 20s on my server. I still have to benchmark it while not using the custom aggregate function.)

I'd post the code but it seems to have some mathematical bugs in it (and i'm sure there is potential for a memory leak somewhere)
If anybody is interested, let me know and I'll clean it up and post it.

For the other question:
Each pixel in the image (for 24bit color) needs a 1-byte representation for each color RED,GREEN, and BLUE.
I was trying to convert the INTEGERs to a BLOB and have each INTEGER (in BLOB format) take up only 1 byte each.

So, a more accurate question would be:
"How do I convert the three INTEGERs into the appropriate BLOB data format so that I can append it to the BLOB?"
The function CHR() seems to be the starting point I was looking for.
Right now, i'm creating a CLOB and then using dbms_lob.convertToBLOB();
(I have a feeling that some of the parameters are wrong)

If anyone has any better ideas of doing this, I'd be happy to here them.

again, thanks.

MK

Tom Kyte
January 08, 2011 - 12:38 pm UTC

how do the integers need to be represented? What is the format down to the bit level. I don't see how CHR() would be useful at all...

A reader, January 08, 2011 - 6:54 pm UTC

Tom,

As far as bit-level representation of the numbers goes, it should be how an x86/x86_64 CPU would represent the value in C/C++ (on an x86/x86_64 machine). (I have no way of testing on non intel/amd machine)

Example:
Integer 0 would be a byte with hex value 0x00h
Integer 1 would be a byte with hex value 0x01h
....
Integer 255 would be a byte with hex value 0xFFh
Integers >=256 are invalid (and should throw an error)
Integers < 0 are invalid (and should throw an error)

I've seen CHR(10) used for appending a new line character ('\n' which is ASCII decimal code 10, hex code 0x0Ah) to strings.
It seems to work for this application, but I do admit that my "spiderman senses are tingling" with the phrases "multi-byte character sets" and "character set conversion".

Since the values I need are just binary representation of the number, I'm now thinking of converting the INTEGER to BINARY_INTEGER and then using a LOB/RAW version of SUBSTR to get the one byte I need.

Thanks,

MK
Tom Kyte
January 10, 2011 - 7:42 am UTC

see, that is why I asked - because when you say "integer" and further when you say C/C++ - that is a 2 or 4 byte representation - period. A single byte is not an 'integer'.

Now I see how chr() could fit in


As long as you are treating these things as 'raw', you should be ok. I'd work in the code with raw and use

utl_raw.cast_to_raw( chr(n) )

don't use varchar in your code, use all raw/binary types.

Thank You

Micheal Kutz, January 10, 2011 - 10:23 am UTC

Tom,

As always, thank you for sharing your knowledge.

Sincerely,

Michael Kutz

More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here