A couple of days ago in the Web Dynpro ABAP forum, the question was posed, can we use WDA to create a thumbnail image of an uploaded image for use in indexes etc. I didn’t think ABAP had any image processing capability, so I was very happily surprised when Thomas Jung (http://www.sdn.sap.com/irj/scn/bc?u=5%2bhlk9c3p0q%3d) pointed out that he had written some code to use the functionality of the AGS to do some simple image manipulation. (ABAP Bitmap Image Processing Class)
Thomas hadn’t built in image resizing capabilities into his solution, so I decided to give it a go.
Before I show the resulting code, it is probably worth going over the concept of resampling/resizing images. There are many different ways in which you can skin this particular cat. Especially when you start thinking about enlarging images, the logic used can quickly become quite complex.
There are many different algorithms that you can use (a comparison of result linked here) (http://www.lassekolb.info/gim35_downsampling.htm), again like Thomas, I found Wikipedia (http://en.wikipedia.org/wiki/Category:Multivariate_interpolation) to be a good reference site. Because I just wanted to see if it were possible, I went with the simplest solution which is called Nearest-neighbor interpolation (also known as proximal interpolation or point sampling) (thank you to Wikipedia for further extending my vocabulary).
The nearest neighbour approach basically squashes, or expands, an image by throwing away data (when squashing) or adding more of the same data (when expanding). It results in really blocky images when you use it to scale up – but reasonable images when used to scale down. I found a
. I used this as the basis for my implementation.
OK, enough theory – here’s the results!
I extended Thomas’ class (ZCL_ABAP_BITMAP) to have one more method, called, unsurprisingly “TRANSFORM_RESIZE”. It takes two required input parameters:
!https://weblogs.sdn.sap.com/weblogs/images/251723740/method_signature.jpg|height=96|alt=image|width=568|src=https://weblogs.sdn.sap.com/weblogs/images/251723740/method_signature.jpg|border=0! And returns Thomas’s exception class if anything goes wrong.
And here’s the code – it isn’t pretty, I really should add some comments it – and you can blame the huge amount of hard coded constants on Thomas 😉 – I’m just copying his bitmap handling routines! But it works, and hopeful the theory links about can explain what is going on. = l_datal_counter(l_width).<br /> enddo.<br /><br /><br /><br /> l_mod = ( new_width * l_bytes_per_pixel ) mod 4.<br /> l_new_pad = 4 – l_mod.<br /> if l_new_pad = 4.<br /> l_new_pad = 0.<br /> endif.<br /><br /><br /><br /> loop at lt_rows assigning <wa_row>.<br /> clear l_new_row.<br /> do new_width times.<br /> l_counter2 = l_bytes_per_pixel * floor( ( sy-index – 1 ) * l_x_factor ).<br /> concatenate l_new_row <wa_row>l_counter2(l_bytes_per_pixel) into l_new_row in byte mode.
if l_new_pad > 0.
do l_new_pad times.
concatenate l_new_row l_null into l_new_row in byte mode.
concatenate l_new_data l_new_row into l_new_data in byte mode.
data x_new_image type xstring.
concatenate gx_content(data_offset) l_new_data into x_new_image in byte mode.
data x_header type xstring.
x_header = gx_content0(data_offset).<br /><br /> data x_size(4) type x.<br /> data i_size type i.<br /> i_size = xstrlen( x_new_image ).<br /> write4 i_size x_size.<br /> concatenate x_header0(2) x_size x_header6 into x_header in byte mode.<br /><br /> data x_data_size(4) type x.<br /> data i_data_size type i.<br /> i_data_size = xstrlen( l_new_data ).<br /> write4 i_data_size x_data_size.<br /> concatenate x_header0(34) x_data_size x_header38 into x_header in byte mode.<br /><br /> data x_width(4) type x.<br /> data x_height(4) type x.<br /> data i_width type i.<br /> data i_height type i.<br /> i_width = new_width.<br /> i_height = new_height.<br /> write4 i_width x_width.<br /> write4 i_height x_height.<br /><br /> concatenate x_header0(18) x_width x_height x_header26 into x_header in byte mode.<br /> data x_hres(4) type x.<br /> data x_vres(4) type x.<br /><br /> x_hres = x_header38(4).
x_vres = x_header42(4).<br /> concatenate x_header0(38) x_vres x_hres x_header+46 into x_header in byte mode.
concatenate x_header l_new_data into x_new_image in byte mode.
gx_content = x_new_image.
And the results
Slightly updating Thomas’s demo WDA, I added an additional option that resized the current image to 100px height and whatever appropriate width.
So first after loading the lovely double rainbow ( I can’t get the song out of my head!) (http://www.youtube.com/watch?v=MX0D4oZwCsA)
And then actually clicking that resize menu option, we have our image resized!