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).

/wp-content/uploads/2014/06/1_481345.jpg

Then we put a graphic component in our smartform  parameters as below.

/wp-content/uploads/2014/06/2_481346.jpg

Here; &IPERNR& variable should have the name of an SE78 GRAPHICS file with ID = BMAP and type = BCOL (for Colored Images).

/wp-content/uploads/2014/06/3_481347.jpg

Below screenshots are smartform test screen and SE78 display screen, IPERNR parameter has the same name as image name in SE78.

/wp-content/uploads/2014/06/21_481364.jpg

/wp-content/uploads/2014/06/5_481348.jpg

We can see and print the image succesfully.

/wp-content/uploads/2014/06/6_481349.jpg

2. Converting External Image Formats (JPG/GIF/TIFF/PNG) to Bitmap

SAP has a class CL_IGS_IMAGE_CONVERTOR for these purposes.

/wp-content/uploads/2014/06/7_481350.jpg

This class has below public methods that all together used to set and convert image files with extensions JPG, GIF, TIFF and PNG.

/wp-content/uploads/2014/06/8_481351.jpg

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.

/wp-content/uploads/2014/06/9_481352.jpg /wp-content/uploads/2014/06/10_481353.jpg

/wp-content/uploads/2014/06/11_481354.jpg

If Connection Test is succesful than we can say the IGS is up and running.

/wp-content/uploads/2014/06/12_481355.jpg

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.

/wp-content/uploads/2014/06/13_481356.jpg

fetch_and_convert_emp_photo subroutine starts with employee photo check.

/wp-content/uploads/2014/06/14_481357.jpg

then we get the binary data for the file

/wp-content/uploads/2014/06/15_481358.jpg

then we write the binary file to /usr/sap/trans/ directory

/wp-content/uploads/2014/06/16_481359.jpg

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.

/wp-content/uploads/2014/06/17_481360.jpg

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.

/wp-content/uploads/2014/06/18_481361.jpg

/wp-content/uploads/2014/06/19_481362.jpg

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 w3paramcont_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 sysubrc 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

/wp-content/uploads/2014/06/20_481363.jpg

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 pernrpernr   TO imagename.
MOVE pernrpernr   TO imagedesc.

DATA: l_resolution  TYPE stxbitmapsresolution.
DATA: l_docid     TYPE stxbitmapsdocid.

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 stxbitmapswidthtw,
l_height_tw      
TYPE stxbitmapsheighttw,
l_width_pix      
TYPE stxbitmapswidthpix,
l_height_pix     
TYPE stxbitmapsheightpix.
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 sysubrc 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 sysubrc.
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 sysubrc <> 0.
PERFORM dequeue_graphic USING ‘GRAPHICS’
imagename
‘BMAP’
‘BCOL’.
MESSAGE ID symsgid TYPE symsgty NUMBER symsgno
WITH symsgv1 symsgv2 symsgv3 symsgv4
RAISING conversion_failed.
ENDIF.

* Save bitmap in BDS
CREATE OBJECT l_bds_object.

wa_bds_componentsdoc_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_signaturedoc_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 sysubrc <> 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 sysubrc = 0.
l_docid
= wa_bds_signaturedoc_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’
AND tdid     = ‘BMAP’
AND tdname   = imagename
AND tdbtype  = ‘BCOL’.
SELECT SINGLE tabname FROM bds_locl INTO l_tab
WHERE classname = c_bds_classname
AND classtype = c_bds_classtype.
IF sysubrc = 0.
SELECT SINGLE object_key FROM (l_tab) INTO l_object_key
WHERE loio_id = wa_stxbitmapsdocid+10(32)
AND classname = c_bds_classname
AND classtype = 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 sysubrc = 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 sysubrc <> 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 sysubrc = 0.
l_docid
= wa_bds_signaturedoc_id.
ELSE.
PERFORM dequeue_graphic USING ‘GRAPHICS’
imagename
‘BMAP’
‘BCOL’.
MESSAGE e285(td) WITH imagename ‘BDS’.
ENDIF.

ELSEIF sysubrc = 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 sysubrc <> 0.
UPDATE stxbitmaps FROM wa_stxbitmaps.
IF sysubrc <> 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

To report this post you need to login first.

7 Comments

You must be Logged on to comment or reply to a post.

  1. Tyu Lssss

    thanks for sharing.

    i have a question about it.

    after we convert the jpg photos to bmp, do we still need to upload photos via se78 ? or it would automatically proccess this step?

    (0) 

Leave a Reply