ABAP Bitmap Image Processing Class
Last week Alvaro Tejada (Blag) posted a The specified item was not found.. Well I got all caught up in the fun challenge and now here are the results for your downloading pleasure.
What Blag wanted to do was simply flip an existing Bitmap that he was reading out of the BDS (Business Document Store). The problem that he was facing is that there is no easy method for doing this in ABAP. He tried just reversing the Byte Stream, but quickly found out that this corrupted the image. A bitmap isn’t just stored as a simple data stream – it has header information and a complex structure that must be taken into consideration when doing any manipulations on it.
But many other languages have simple processes for working with Bitmaps – what was wrong with ABAP. Well these other languages just have libraries that have already been created that abstract the actual process of working with the Bitmap. These libraries directly expose attributes like the bitmap height and width, so that programmers don’t have to know the detailed structure of the Bitmap header. They also usually have methods to allow for basic manipulation of the Bitmap.
To my best knowledge, no one in ABAP had created such a library. So while it was perfectly possible to manipulate the Bitmap at a low level in ABAP, it was more tedious than necessarily because it didn’t have one of these helper libraries. Historically ABAP has been all about processing business data, so it hasn’t been a big issue that you couldn’t flip bitmaps or convert them to grey scale. But with ABAP being used increasingly for forms output and web pages, this is functionality that might be useful from time to time. So I decided to take the rough solution that I built for Blag and turn it into a reusable bitmap class.
Before we get into the actual solution of the ABAP Bitmap Library, I thought I would cover some basics of the processing that is going on within the library. If you are interested in how Bitmaps are stored and processed then keep reading this section. If you really couldn’t care less and just want to get started using the library, then skip down to the next section (after all the purpose of creating this library was so people wouldn’t have to care how a bitmap works internally).
When I started looking into Blag’s problem, I had no real experience with how bitmaps are structured. So I started my investigation via the internet. I found lots of good articles on Bitmaps, but probably the best summary of information I found was on Wikipedia.
The linked Wikipedia article does an excellent job of describing the inner layout of the Bitmap – how you have a section for the header information and then a separate section for the data. It also describes for each pixel is stored. The color of the pixel (in 24 bits per pixel) is stored as three separate integers – one each for Red, Green, and Blue. It is important to understand that you can’t just manipulate data within the Bitmap at the byte level, but instead the pixel level so you can keep from altering the RGB color as you move bytes around.
The second complexity is that bitmaps are not stored top to bottom within the data area. Instead the first visible row of data on the screen is stored as the list “line” in the bitmap data area. All the data is also stored together in a single stream. Therefore for easier processing you generally break the stream down by horizontal row. But because processing is easier if divisible by 4, null-bytes are added to the end of the line to pad the file. All of these aspects are especially important when trying to rotate a bitmap.
The final complexity that I faced in my processing was that much of the data in the bitmap header was stored as either 2 or 4 byte DWORDs. This meant that I couldn’t just cast these byte values into ABAP Integers. Instead I had to create small macros to change the byte order.
The ABAP Bitmap Library
OK, enough of the deep stuff. Now it is time to see just how easy we can make working with Bitmaps in ABAP. For that purpose I have created a Class called ZCL_ABAP_BITMAP.
As you can see there are plenty of methods in this class. Let’s start with the Static methods. You see the class is marked as Private Instantiation only, therefore the static methods are the only way to create an instance of the class.
Each of the static methods is a path to provide the bitmap source and return an instance of the class. We have the basic create from bitmap methods like CREATE_FROM_BYTESTEAM (type XSTRING) and CREATE_FROM_BYTETABLE (type standard table of line 255 x). These are generic and support reading the bitmap content from outside the library – providing flexibility.
But I also wanted to make it easy to read the bitmap content from the most common locations. Therefore we have the CREATE_FROM_MIME_REPOSITORY, CREATE_FROM_BDS_GRAPHIC, and CREATE_FROM_FRONTEND_UPLOAD methods. These methods contain the necessarily logic to process images from their various sources. But many of these sources also support graphic formats other than bitmaps. Internally this class must process everything in bitmaps, but I wanted to support the conversion from other popular formats (like GIFs and JPEGs). Luckily this functionality already is provided by the IGS and I just reused the existing class, CL_IGS_IMAGE_CONVERTER, to do the processing.
The method CREATE_FROM_EXT_FORMAT provides the logic to interact with the IGS and perform the conversion. It supports conversions to/from JPEG, TIFF, PNG, GIF, and of course Bitmap. There is one common static method than can be used inside the class and by calling programs named CHECK_IGS_SETUP to test to see if the IGS is present, configured and of a late enough release level to support image conversion. That way if there is any problem with the IGS setup, exceptions can be thrown gracefully and the alternative image types simply aren’t supported.
There are also similar methods for outputting the bitmap image – including outbound format conversion and Zip compression- GET_CONTENT_ZIP_BYTESTREAM, GET_CONTENT_BYTESTREAM, GET_CONTENT_EXT_FORMAT, and GET_CONTENT_BYTETABLE.
Next are the methods that help to display the bitmap in different environments. First is the method DISPLAY_IN_SAPGUI. This is designed for Classic Dynpro. You can pass in the hosting container element – or if you want the ZCL_ABAP_BITMAP to control the image, it can provide its own Dialog Container Control. This was very helpful for debugging, because it makes it possible to test the class and display the results without any wrapper program.
The other display helper method is the PUSH_CONTENT_INTO_ICM_CACHE. This places the content for the image into the ICM content cache for the specified amount of time and returns the unique URL to this cached object. This is a great way to manipulate the image, and then display it in an image element using BSP or Web Dynpro ABAP without ever having to permanently store the image.
We have one method, GET_HEADER_INFORMATION, that reads the Bitmap header and returns all the most important information (like width, height, color depth, etc).
Finally we have the really fun methods: the transformations. These are the methods that directly manipulate the Bitmap Content. The names of the methods do a rather good job of describing exactly what they do to the image: TRANSFORM_ROTATE_CLOCKWISE, TRANSFORM_ROTATE_COUNTER_CLOCK, TRANSFORM_FLIP, TRANSFORM_MIRROR, TRANSFORM_INVERSION, TRANSFORM_GREYSCALE.
No library would really be complete without some nice test and demo applications. For this purpose I built two different test suites. The first is classic dynpro based. The application lets you load images from the Frontend. It displays the results using the DISPLAY_IN_SAPGUI method and has buttons to activate the Transformations.
Just to demonstrate how (hopefully) easy this class is to use, here is the source code of the classic dynpro test application:
DATA bitmap TYPE REF TO zcl_abap_bitmap. DATA custom_container TYPE REF TO cl_gui_custom_container. DATA okcode TYPE syucomm.
CALL SCREEN 100. *&---------------------------------------------------------------------* *& Module STATUS_0100 OUTPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE status_0100 OUTPUT. SET PF-STATUS 'MAIN'. SET TITLEBAR '100'. IF custom_container IS INITIAL. CREATE OBJECT custom_container EXPORTING container_name = 'CUSTOM_CONTAINER'. ENDIF.
IF bitmap IS INITIAL. TRY. bitmap = zcl_abap_bitmap=>create_from_frontend_upload( ). bitmap->display_in_sapgui( i_container = custom_container ). CATCH zcx_abap_bitmap . ENDTRY. ENDIF. ENDMODULE. " STATUS_0100 OUTPUT *&---------------------------------------------------------------------* *& Module USER_COMMAND_0100 INPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE user_command_0100 INPUT. TRY. CASE okcode. WHEN 'BACK' OR 'CANCEL' OR 'EXIT'. LEAVE PROGRAM. WHEN 'NEW'. bitmap->free( ). CLEAR bitmap. WHEN 'CLOCK'. bitmap->transform_rotate_clockwise( ). bitmap->refresh_sapgui_display( ). WHEN 'COUNTER'. bitmap->transform_rotate_counter_clock( ). bitmap->refresh_sapgui_display( ). WHEN 'GRAY'. bitmap->transform_greyscale( ). bitmap->refresh_sapgui_display( ). WHEN 'INVERSE'. bitmap->transform_inversion( ). bitmap->refresh_sapgui_display( ). WHEN 'MIRROR'. bitmap->transform_mirror( ). bitmap->refresh_sapgui_display( ). WHEN 'FLIP'. bitmap->transform_flip( ). bitmap->refresh_sapgui_display( ). ENDCASE. CATCH zcx_abap_bitmap . CLEAR okcode. ENDTRY. CLEAR okcode. ENDMODULE. " USER_COMMAND_0100 INPUT
But the more full featured test application is actually the Web Dynpro ABAP version. It has all the same functionality to load existing images, display them, and perform transformations:
However it also has functionality to export the manipulated image in several formats (as well as zip compression):
Now for the downloads. I have broken them out into separate parts and pieces so people can grab just what they need.
(!!!Downloadlinks do not work anymore!!!) added by moderator
- Just the Class (and support exception class) in SAPLink format
- The Dynpro Test application in SAPLink format
- The Web Dynpro ABAP Test application in SAPLink format
- All the objects together in SAPLink format
- All the objects together in a Transport file (good for importing the entire package- ZBITMAP_SERVICES – into a NSP system).
I was waiting for this magical moment -;) This class is just awesome! You really took my problem and take it to a whole new level! I feel happy to know that thanks to my humble blog you made an incredible tool! -:D I love that kind of collaboration that can be produced here on SDN...
Can't wait to test the class and hopefully add some methods -:P
P.S: This will go to my SDN Blogs Vault... -:D
This is quite simply the kind of stuff that I love doing in a language, and I guess people who think it's difficult to build libraries/APIs in ABAP will not say much after reading this!
thank you for sharing!
Is also a possibility to execute OPenGL in SAP enviroment?
Regards & Thanks & All the best & Nice weekend,
if you are still interested in this topic I can tell you that you can use OpenGL in the SAPGUI.
I just created an AxtiveX control and could use it in a custom control. The interaction with the mouse is also supported.
I test it yesterday on my NSP...It works like a charm -:D Now I got some idea to update the class -;) Sometime ago I developed an Visual Basic application with 32 filters...Just to adapt them to ABAP and to your class...Any update will go on SAPLink format of course...Hope I can make it -:P
Does your coding work on a SAP 4.7?
Thanks for the answer.
i just wonder to know how can i upload the file i downloaded here(especially the class object) into sap and make it work
additionally,i have ECC 5.0 and XI system at present
thanks for your help
SAPlink is not an SAP product. It is a community project designed to help facilitate the exchange for ABAP development objects. It exports and imports objects based upon XML. Therefore it bypasses the Transport Mechanism. It allows you to import most objects by simply running an ABAP program. It imports all objects into $TMP and Inactive so that you can review them before activation.
Here is a link where you read more about SAPlink:
The last option in the list is a transport file.
This is the same mechanism that you use today to move programs through your normal landscape. This has the advantage that you can import all developments objects (unlike SAPlink that needs plugins to support different object types). The only downside is that developers generally won’t have access to perform the transport yourself. You will have to go to your Basis Administrator and request that they import the transport file for you.
The exception here is if you use the SDN Trial Version system. In this case you have full control over using the transport mechanism. There is even a blog on SDN that discusses how to setup and use the transport system in the Trial Version.
ABAP Trial Version for Newbies: Part 9 ' Importing a transport into SP11/12 '
With some help from Thomas (thanks again Thomas) I made the following changes;
1. Changed the constructor to PUBLIC.
2. Replaced both REGEX calls with SPLIT to get the type of file extension.
your class is just awesone! After working with it for a while now I'm just missing one little thing:
Is it possible to change the color depth of a picture (f.e. from 24bit to 256 colors)?
Great work by the way. See you at Teched.
If I'm not wrong (I didn't test), there's a just one mistake about the Endianness of the X to I conversion, that is, it works only in a Little Endian system. For instance, the READ4 macro should be modified this way:
And IS_LITTLE_ENDIAN method may be created this way:
Thanks for sharing this great work. My question is not completely relevant to this doc but I will be really grateful if you can help me out if possible. Is there a way to download a scriptform in '.bmp' format like we download in '.pdf' format using the program 'RSTXPDFT4'. Thanks in advance.
I need to convert a bmp picture in local pc to 8-bit bmp and i found the method - TRANSFORM_GREYSCALE in your class could return a 8-bit bmp gray graphics, not colored.
So could i know how to update this method to return a 8-bit bmp colored graphics?
Could please help on this? it is very urgent for me. very appreciate!
Great work but thelinks are broken .Could you upload them again?
Sorry but the content is more than 9 years old now. I no longer have the original content.
Here is a link to the original NUGG file if someone needs it:
Hi Shai Sinai,
Link which you provide is not working, can you please upload the file again.
A great 2018 to everyone !
Although old, this content is still very useful !!
PLEASE, could someone who has this source code kindly share it somewhere ?
That would be of GREAT help for many !
Image resolution for 24bit BMP is still a big problem for many, I guess. So far this seems to be the only available solution on SAP communities.
Thak you very much !!
Hey Thomas Jung I found it 🙂 https://code.google.com/archive/p/abap-sdn-examples-tpj/downloads
I downloaded them, in case someone will need.
2018 and still someone needs to play with bytes 🙂
Hope to help and thanks for your precious work.
Hi Roberto Vacca / Thomas Jung ,
For our requirement, we need to convert the Tiff of little-endian type to Tiff of big-endian type. It would be very helpful, if you can help us on this.
We tried to find the source code on the below mentioned link, as mentioned in the Roberto Vacca 's comment. But I think it is missing.
So request your kind input on the same.
Thank you so much in advance.
You might notice that this blog was published nearly 11 years ago. I clicked the link above and the code is there but its in SAPLINK format, which I don't believe is widely used any longer. I don't work on the ABAP topic any longer and no longer maintain these old projects.
Yes it's all in SAPLINK format, so you'll need to implement this tool in your sap system before go ahead.
You probably should be able to use ImageMagick from command line . You can try any others free commercial tools.
Hope to help
Is there any way I can resize my image to 50% , 150% using this class .
Can you please guide me through the process of knowing what to do when trying to increase size of the image.
I have checked wikipedia but it does not have anything related to scaling image.
Please guide me with IMAGE ZOOMIN/ZOOMOUT of Bitmaps.
Thanks in Advance
Hi Roberto Vacca / Thomas Jung ,
Thank you very much for the quick feedback. We'll try implementing it and check it
Thank you very much once again.
Do you have a sample code to Image transform?