EMPLOYEE PHOTO - BITMAP AUTOMATION
( TO BE DISPLAYED ON SMARTFORMS )
Recently we needed the functionality to print Employee Photos on smartforms. As smartforms only show BMP files uploaded via SE78 and employee photos are mostly JPG files with different stories we had to make some sort of automation that gets the employee photo, converts it to bitmap file and upload this BMP file to SE78 via background processing.
1. Displaying Pictures Dynamically in Smartforms
First we create a dummy smartform and an input parameter for SE78 file name (IPERNR in our case).
Then we put a graphic component in our smartform parameters as below.
Here; &IPERNR& variable should have the name of an SE78 GRAPHICS file with ID = BMAP and type = BCOL (for Colored Images).
Below screenshots are smartform test screen and SE78 display screen, IPERNR parameter has the same name as image name in SE78.
We can see and print the image succesfully.
2. Converting External Image Formats (JPG/GIF/TIFF/PNG) to Bitmap
SAP has a class CL_IGS_IMAGE_CONVERTOR for these purposes.
This class has below public methods that all together used to set and convert image files with extensions JPG, GIF, TIFF and PNG.
There is a prerequisite to use this class properly and that is IGS (Internet Graphics Server) must be up and running. If IGS is not installed and configured, you should receive RFC Destination error. IGS is explained below.
3. IGS (Internet Graphics Server)
"Execute" method of class CL_IGS_IMAGE_CONVERTER uses below RFC destination as default to send file to IGS for conversion so if IGS is not up and running you should get an RFC error and conversion process will not work.
If Connection Test is succesful than we can say the IGS is up and running.
4. Note 454042 - IGS: Installing and Configuring the IGS
If IGS is not running than BASIS should apply this note which explains the steps clearly.
454042 - IGS: Installing and Configuring the IGS
5. Programming Step
Some number of approaches can be used to develop this kind of program. As SE78 and similar tcodes work on frontend services like GUI_UPLOAD, I used DATASET logic to handle data uploading and data storing. (Complete source code added at the end of the document.)
I used PNP logical database as I want to fetch Employee Photo. The logic of the program goes like this.
fetch_and_convert_emp_photo subroutine starts with employee photo check.
then we get the binary data for the file
then we write the binary file to /usr/sap/trans/ directory
then we read this file into an xstring typed variable and delete the JPG file from directory. Here I used FM - ZBMP_CREATE_FROM_EXT_FORMAT which gets the xstring file and converts to bitmap.
Thomas Jung has a nice article about ABAP Bitmap Image Processing Class which tells us about ZCL_ABAP_BITMAP class. This class has a method CREATE_FROM_EXT_FORMAT which this function is derived from.
The method uses standard components so you may directly create this simple FM instead of Implementing whole ZCL_ABAP_BITMAP and call this FM instead of using ZCL_ABAP_BITMAP class methods.
Source Code is as follows;
|
---|
|
FUNCTION ZBMP_CREATE_FROM_EXT_FORMAT. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" REFERENCE(XSTREAM) TYPE XSTRING *" REFERENCE(FORMAT) TYPE STRING DEFAULT 'JPG' *" EXPORTING *" REFERENCE(BITMAP) TYPE W3MIMETABTYPE *"---------------------------------------------------------------------- DATA: l_igs_imgconv TYPE REF TO cl_igs_image_converter, l_img_blob TYPE w3mimetabtype, l_img_size TYPE w3param-cont_len, l_bmp_xstream TYPE xstring. CREATE OBJECT l_igs_imgconv. l_img_size = XSTRLEN( xstream ). CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = xstream TABLES binary_tab = l_img_blob. CALL METHOD l_igs_imgconv->set_image EXPORTING blob = l_img_blob blob_size = l_img_size. DATA l_format TYPE string. l_format = format. CASE l_format. WHEN 'TIF'. l_igs_imgconv->input = 'image/tiff'. WHEN 'JPG'. l_igs_imgconv->input = 'image/jpeg'. WHEN 'PNG'. l_igs_imgconv->input = 'image/png'. WHEN 'GIF'. l_igs_imgconv->input = 'image/gif'. WHEN OTHERS. EXIT. ENDCASE. l_igs_imgconv->output = 'image/x-ms-bmp'. CALL METHOD l_igs_imgconv->execute EXCEPTIONS OTHERS = 1. IF sy-subrc IS INITIAL. CALL METHOD l_igs_imgconv->get_image IMPORTING blob = l_img_blob blob_size = l_img_size. CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' EXPORTING input_length = l_img_size IMPORTING buffer = l_bmp_xstream TABLES binary_tab = l_img_blob EXCEPTIONS failed = 1 OTHERS = 2. bitmap = l_img_blob. ENDIF. ENDFUNCTION. |
then we write this converted bitmap file to the same directory like this
at this point we have the bmp formatted employee photo and can upload this to Document Server. there is the subroutine "import_bitmap_bds " in standard report "saplstxbitmaps" which asks for the user for the file to be uploaded. I converted the subroutine to work with file in usr/sap/trans directory.
Here is the modified subroutine;
|
---|
FORM import_bitmap_bds_local.
MOVE list_filename TO imagefile. MOVE pernr-pernr TO imagename. MOVE pernr-pernr TO imagedesc.
DATA: l_resolution TYPE stxbitmaps-resolution. DATA: l_docid TYPE stxbitmaps-docid.
DATA: l_object_key TYPE sbdst_object_key. DATA: l_tab TYPE ddobjname. DATA: BEGIN OF l_bitmap OCCURS 0, l(64) TYPE x, END OF l_bitmap. DATA: l_filename TYPE string, l_bytecount TYPE i, l_bds_bytecount TYPE i. DATA: l_color(1) TYPE c, l_width_tw TYPE stxbitmaps-widthtw, l_height_tw TYPE stxbitmaps-heighttw, l_width_pix TYPE stxbitmaps-widthpix, l_height_pix TYPE stxbitmaps-heightpix. DATA: l_bds_object TYPE REF TO cl_bds_document_set, l_bds_content TYPE sbdst_content, l_bds_components TYPE sbdst_components, wa_bds_components TYPE LINE OF sbdst_components, l_bds_signature TYPE sbdst_signature, wa_bds_signature TYPE LINE OF sbdst_signature, l_bds_properties TYPE sbdst_properties, wa_bds_properties TYPE LINE OF sbdst_properties. DATA wa_stxbitmaps TYPE stxbitmaps.
* Enqueue PERFORM enqueue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'.
*** Read BMP File CLEAR list_filename. MOVE imagefile TO list_filename. OPEN DATASET list_filename IN BINARY MODE FOR INPUT. IF sy-subrc EQ 0. CLEAR xstr1. *** Read BMP File READ DATASET list_filename INTO xstr1.
**** Delete BMP File DELETE DATASET list_filename.
CLEAR l_bitmap. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = xstr1 IMPORTING output_length = l_bytecount TABLES binary_tab = l_bitmap.
CASE sy-subrc. WHEN 0. WHEN 2. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'. MESSAGE e811(td) WITH imagefile.
WHEN 3. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'. MESSAGE e812(td) WITH imagefile.
WHEN OTHERS. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'.
MESSAGE e813(td) WITH imagefile.
ENDCASE.
l_color = c_true.
* Bitmap conversion CALL FUNCTION 'SAPSCRIPT_CONVERT_BITMAP_BDS' EXPORTING color = l_color format = 'BMP' resident = space bitmap_bytecount = l_bytecount compress_bitmap = space IMPORTING width_tw = l_width_tw height_tw = l_height_tw width_pix = l_width_pix height_pix = l_height_pix dpi = l_resolution bds_bytecount = l_bds_bytecount TABLES bitmap_file = l_bitmap bitmap_file_bds = l_bds_content EXCEPTIONS format_not_supported = 1 no_bmp_file = 2 bmperr_invalid_format = 3 bmperr_no_colortable = 4 bmperr_unsup_compression = 5 bmperr_corrupt_rle_data = 6 OTHERS = 7. IF sy-subrc <> 0. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 RAISING conversion_failed. ENDIF.
* Save bitmap in BDS CREATE OBJECT l_bds_object.
wa_bds_components-doc_count = '1'. wa_bds_components-comp_count = '1'. wa_bds_components-mimetype = c_bds_mimetype. wa_bds_components-comp_size = l_bds_bytecount. APPEND wa_bds_components TO l_bds_components.
IF l_docid IS INITIAL. " graphic is new
wa_bds_signature-doc_count = '1'. APPEND wa_bds_signature TO l_bds_signature.
CALL METHOD l_bds_object->create_with_table EXPORTING classname = c_bds_classname classtype = c_bds_classtype components = l_bds_components content = l_bds_content CHANGING signature = l_bds_signature object_key = l_object_key EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'.
MESSAGE e285(td) WITH imagename 'BDS'.
ENDIF. READ TABLE l_bds_signature INDEX 1 INTO wa_bds_signature TRANSPORTING doc_id. IF sy-subrc = 0. l_docid = wa_bds_signature-doc_id. ELSE. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'.
MESSAGE e285(td) WITH imagename 'BDS'.
ENDIF.
ELSE. " graphic already exists ********* read object_key for faster access ***** CLEAR l_object_key. SELECT SINGLE * FROM stxbitmaps INTO wa_stxbitmaps WHERE tdobject = 'GRAPHICS' ANDtdid = 'BMAP' ANDtdname = imagename ANDtdbtype = 'BCOL'. SELECT SINGLE tabname FROM bds_locl INTO l_tab WHERE classname = c_bds_classname ANDclasstype = c_bds_classtype. IF sy-subrc = 0. SELECT SINGLE object_key FROM (l_tab) INTO l_object_key WHERE loio_id = wa_stxbitmaps-docid+10(32) ANDclassname = c_bds_classname ANDclasstype = c_bds_classtype. ENDIF. ******** read object_key end ********************
CALL METHOD l_bds_object->update_with_table EXPORTING classname = c_bds_classname classtype = c_bds_classtype object_key = l_object_key doc_id = l_docid doc_ver_no = '1' doc_var_id = '1' CHANGING components = l_bds_components content = l_bds_content EXCEPTIONS nothing_found = 1 OTHERS = 2. IF sy-subrc = 1. " inconsistency STXBITMAPS - BDS; repeat check in wa_bds_signature-doc_count = '1'. APPEND wa_bds_signature TO l_bds_signature.
CALL METHOD l_bds_object->create_with_table EXPORTING classname = c_bds_classname classtype = c_bds_classtype components = l_bds_components content = l_bds_content CHANGING signature = l_bds_signature object_key = l_object_key EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'.
MESSAGE e285(td) WITH imagename 'BDS'. ENDIF. READ TABLE l_bds_signature INDEX 1 INTO wa_bds_signature TRANSPORTING doc_id. IF sy-subrc = 0. l_docid = wa_bds_signature-doc_id. ELSE. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'. MESSAGE e285(td) WITH imagename 'BDS'. ENDIF.
ELSEIF sy-subrc = 2. PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'. MESSAGE e285(td) WITH imagename 'BDS'. ENDIF.
ENDIF.
* Save bitmap header in STXBITPMAPS wa_stxbitmaps-tdname = imagename. wa_stxbitmaps-tdobject = 'GRAPHICS'. wa_stxbitmaps-tdid = 'BMAP'. wa_stxbitmaps-tdbtype = 'BCOL'. wa_stxbitmaps-docid = l_docid. wa_stxbitmaps-widthpix = l_width_pix. wa_stxbitmaps-heightpix = l_height_pix. wa_stxbitmaps-widthtw = l_width_tw. wa_stxbitmaps-heighttw = l_height_tw. wa_stxbitmaps-resolution = l_resolution. wa_stxbitmaps-resident = space. wa_stxbitmaps-autoheight = 'X'. wa_stxbitmaps-bmcomp = space. INSERT INTO stxbitmaps VALUES wa_stxbitmaps. IF sy-subrc <> 0. UPDATE stxbitmaps FROM wa_stxbitmaps. IF sy-subrc <> 0. MESSAGE e285(td) WITH imagename 'STXBITMAPS'. ENDIF. ENDIF.
* Set description in BDS attributes wa_bds_properties-prop_name = 'DESCRIPTION'. wa_bds_properties-prop_value = imagedesc. APPEND wa_bds_properties TO l_bds_properties.
CALL METHOD l_bds_object->change_properties EXPORTING classname = c_bds_classname classtype = c_bds_classtype object_key = l_object_key doc_id = l_docid doc_ver_no = '1' doc_var_id = '1' CHANGING properties = l_bds_properties EXCEPTIONS OTHERS = 1.
PERFORM dequeue_graphic USING 'GRAPHICS' imagename 'BMAP' 'BCOL'.
ENDIF.
ENDFORM. "import_bitmap_bds_local |
With the use of this modified subroutine, we can batch upload converted BMP files to Document Server. We can run this report as scheduled job so that it gets the employee photo, converts it to BMP format and uploads it to Document Server.
You can find the source code of the sample report as attachment (bitmap automization.txt) to this document.
Hope this document helps.
Murat Kaya - 2014