This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DLP9000: RLE Pattern Image Compression

Part Number: DLP9000
Other Parts Discussed in Thread: DLPC900,

I'm trying to implement Run-Length Encoding according to section 2.4.3 (Pattern Image Compression) of the DLPC900 Programmer's Guide (Rev. E). Even thought it looks quite straightforward, I face the following problem.

After implementing RLE encoding of the test pattern, I followed the standard routine of displaying the image in pattern on-the-fly mode (according to the Section 5.3 (Pattern On-The-Fly Example) of the DLPC900 Programmer's Guide (Rev. E):

- Stop running the previous pattern (1A24)

- Set on-the-fly pattern mode (1A1B)

- Pattern LUT Definition (1A34)

- Initialize Pattern BMP Load (1A2A)

- Load compressed BMP Data (1A2B)

- Configure Pattern LUT (1A31)

- Start running the pattern (1A24)

Data transmission is done with no errors generated. The device, first, responds as intended: it stops displaying the default pattern. Then, after a few seconds of data encoding and transfer, it displays the pattern. However, instead of the desired one, the projector displays the default pre-stored startup pattern.

Displaying the image in the on-the-fly pattern mode using DLP LCR6500 & LCR9000 GUI 4.0.1, works totally fine.

I assume, the problem is in the encoding logics. Instead of me posting here the code snippets, I'd like to confirm with you a couple of aspects of the RLE compression according to the section 2.4.3 (Pattern Image Compression) of the DLPC900 Programmer's Guide (Rev. E).

1. According to the Table 2-98. RLE Control Bytes: The control byte n > 0 defines the number of times the next RGB pixel has to be repeated. Let's say, I want to repeat the next RGB pixel 2560 times. This value cannot be represented by one byte. How to handle this situation? (Should these 2560 identical pixels be compressed as: 255 RR GG BB ...<8 more times>... 255 RR GG BB 10 RR GG BB? Or is there a smarter trick, such as two byte encoding? The manual does not address this scenario for the Run-Length Encoding)

2. Could you please confirm if the End-of-Line padding should be '00 00 00' and the End-of-Image Padding '00 01 00 00 00 00 00 00 00 00' (as mentioned in the Table 2-99. RLE Compression Example)?

3. Could you please refer to any sources that explicitly demonstrate the algorithm of RLE encoding (or Enhanced RLE) according to the Control Bytes definitions and examples in the DLPC900 Programmer's Guide? I tried to use the logic from the Pycrafter6500 package (https://github.com/csi-dcsc/Pycrafter6500),

Please let me know if I should provide more information to the problem described here.

  • Hello Again Roman,

    Please try inserting a PAT_CONFIG command [Configure Pattern LUT (1A31) - same as your next to last step] immediately after your MBOX_DATA [Pattern LUT Definition (1A34)] in addition to the one at the next to last step.

    Let me know if that works.

    FIzix

  • Hello Fizix,

    Once again, thank you for your feedback. Unfortunately, it didn't help: introducing (1A31) additionally after (1A34) had no effect. Here I would like to go deeper into what's going on when I try to display an image compressed using RLE.

    Similar to my recent update to the question "DLP9000: The projector displays half of the image" (https://e2e.ti.com/support/dlp/f/94/t/845716?tisearch=e2e-quicksearch&keymatch=half-image), I decided to display an empty image, represented as a 3d numpy array of a size (1600, 2560, 3) (height, width, 'depth').

    In the end of the message, you can find a log file that contains the OUT and IN messages sent to and received from the DLP.

    The sequence of executed commands is similar to that described in "DLP9000: The projector displays half of the image" (please, refer to the post if you have not checked it yet).

    If you compare the log files from both trials to display the empty image (I will remind, there I used Enhanced RLE compression, whereas here I'm trying to compress using RLE), the difference in payloads will be only in the following steps:

    5. I initialize Pattern BMP Load (0x1A2A) with the following payload:

    - 0,   0,                 # image index: 0

    - 119,  50,   1,   0 # Number of bytes in the compressed image including the 48 byte header: 78455

    6. Pattern BMP Load (0x1A2B). I will talk about payload later below.

    This time, when I start Pattern Sequence (0x1A24, data [2]), I see the default pre-stored pattern with a corrupted bottom right corner:

    I assume, the problem is in the way the image is encoded. Here is the encoded data of an empty image (int representation):

    ### Image header (48 bytes):

    - 83, 112, 108, 100,                  # Signature bytes: 53 70 6C 64

    - 0,  10,                                       # Image width: 2560

    - 64,   6,                                      # Image height: 1600

    - 119,  50,   1,   0,                      # Number of bytes in the encoded image data: 78455

    - 255, 255, 255, 255, 255, 255, 255, 255,   # Reserved bytes: FF FF FF FF FF FF FF FF)

    - 0,   0,   0,   0,                           # Background color (BB GG RR 00)

    - 0,                                              # Reserved: 0x00

    - 1,                                              # Compression: RLE compression

    - 1,                                              # Reserved: 0x01

    - 0, ..., 0                                      # Reserved: 21 of zero bytes 0x00

    ### Image data:

    # Encoding the rows #1 - 1599 (49 bytes per row x 1599 rows = 78 351 bytes):

    - 255,   0,   0,   0,                     # Repeat the following pixels 255 times: (0, 0, 0) .

    <....the same bytes.. repeated 9 times.>       # Repeat the following pixels 255 times: (0, 0, 0) .

    - 10, 0, 0, 0                                                          # Repeat the following pixels 10 times: (0, 0, 0) .

    - 0, 0                                                                      # (End-of-Line Command)

    - 0, 0, 0                                                                 # (End-of-Line Padding)

    # Encoding the row #1600 (56 bytes):

    - 255,   0,   0,   0,                                                  # Repeat the following pixels 255 times: (0, 0, 0) .

    <....the same bytes.. repeated 9 times.>        # Repeat the following pixels 255 times: (0, 0, 0) .

    - 10, 0, 0, 0                                                           # Repeat the following pixels 10 times: (0, 0, 0) .

    - 0, 1                                                                     # (End-of-File command)

    - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0                                  # (End-of-Image Padding)

    So in total, 78455 bytes were needed to RLE-encode an empty image of a size 1600 x 2560.

    I have a feeling, that RLE encoding, even thought perform according to the Section 2.4.3.1 (Run-Length Encoding) of the Programmer's Guide is not correct, which results in the fact that the image cannot be displayed correctly. 

    What else can we try to figure out the reasons of such a problem?

    The questions from my previous post in this thread are still open:

    1. According to the Table 2-98. RLE Control Bytes: The control byte n > 0 defines the number of times the next RGB pixel has to be repeated. What is the maximum value of  'n' allowed?

    2. Could you please confirm if the End-of-Line padding should be '00 00 00' and the End-of-Image Padding '00 01 00 00 00 00 00 00 00 00' (as mentioned in the Table 2-99. RLE Compression Example)?

    3. Should the (End-of-Line Command) and (End-of-Line Padding) be added after the last row, right before the (End-of-File Command) and (End-of-Image Padding)?

    Best regards,

    Roman

    ID_00002_Log_file_191009150104_f125_b2.log

  • Roman,

    You list the following commands:

    - Initialize Pattern BMP Load (1A2A) - Init Master Load

    - Load compressed BMP Data (1A2B) - Master Load

    But I do not see:

    - Initialize Pattern BMP Load (1A2C) - Init Slave Load

    - Load compressed BMP Data (1A2D) - Slave Load

    You must split the image in half (master half and slave half) and set the width to [- 0,  5,] for each half.

    WIthout the slave portion only the side fed by the Master DLPC900 will display the new image since that is all you are sending the image to.  Since you are sending twice the width, I have no idea what it will do to the compression schema.

    Try correcting this first and then we will look at compression.

    You can look at what the GUI generates to get an idea of what should be being sent by the Python scripts.

    Fizix

  • Hello Fizix,

    I think we are getting closer. You're right, I communicated to the master only, and not to the slave. Before I try it, could you please provide the following information:

    1. Does it matter in which order the commands are executed? 1A2A, 1A2C (initialize both) then 1A2B, 1A2D (load both) OR  1A2A, 1A2B (initialize and load master), then 1A2C, 1A2D (initialize and load slave)?

    2. Where can I find the data which is generated by the GUI software when I add a new pattern and update LUT? This would really help me get an idea how the image data has to be split/compressed/etc.

  • Hello Fizix,

    In the meantime, I found answers to both of my questions above:

    1. The LightCrafter first executes 1A2A, 1A2B (initialize and load master), then 1A2C, 1A2D (initialize and load slave).

    2.. The command logging from the LightCrafter I enabled in the Batch Files tab by checking Enable Command Logging, followed by loading a test image, configuring LUT and starting the sequencer.

    I will need some time to go through the byte code sent by the LightCrafter, to implement changes in my code and run test once again.

    By the way., could you please refer to the documentation which states that one 'must split the image in half (master half and slave half) and set the width to [- 0,  5,] for each half.' I found that the Programmer's Guide does not cover thoroughly this topic. I would also suggest to consider expanding the sections on RLE and E-RLE compression of images.

    Regards,

    Roman

  • Hello Roman,

    Please go to the "Batch Files" tab and "Enable Command Logging" (red rectangle) and then go to the "Pattern On-The-Fly" tab and select and set your parameters for the pattern(s) and then press "Update LUT" - this will record everything that the GUI puts out to the controller over USB (it does not record API read requests).  

    This stream can be saved to a text file by using the "Save Batch File" button (magenta rectangle).

    The documentation can be found on page 59 of the Programmer's Guide":

    And of course 0x0500 is 1280 which is the width of half of the WQXGA image which is 2560 (0x0A00). 

    You can sort of consider each half of the DMD as a separate device that is 1/2 the width of WQXGA (1280 x 1600).

    Fizix

  • Hello Fizix,

    Just an update from my side. I went through the bytes sent to the projector by the LightCrafter software and adjusted my code.

    Good news is that the image displayed from LightCrafter and from the python code are now identical. Bad news is that both are corrupt: the right side is displayed as intended, the left side not:

    Please refer to another thread of mine: DLP9000: LightCrafter 6500 & 9000 - 4.0.1: Error on uploading firmware file & Error on image display.

    I saw you posted your feedback there. On Monday I'll try to implement what you suggested and if the image is fine, I will resolve three open threads.

    Regards,

    Roman

  • Hello Roman,

    Let's go ahead and mark this complete and continue with the other thread.

    Fizix