DLPC900: DLP670S: In DLPC900 + DLP670S, according to the official provided API, when performing image writing in the On-The-Fly mode, only one image can be written.

Part Number: DLPC900

Here is the image download function that I wrote based on 6500. Since the code I wrote was for a single image, I first expanded the single image into a 24-bit image before proceeding with the download:

int DownloadCompressedImage(const std::string& bmpPath, unsigned char imageIndex, int dmd_width, int dmd_height)
{
    //检查文件是否存在
    if (!dlp::File::Exists(bmpPath)) {
        std::cerr << "File does not exist: " << bmpPath << std::endl;
        return -1;
    }

    // 读取 BMP 信息
    BMPInfo info = ReadBMP(bmpPath);
    if (info.width == 0 || info.height == 0) {
        std::cerr << "Failed to read BMP or unsupported format." << std::endl;
        return -2;
    }
    if (info.bitCount != 1 && info.bitCount != 24) {
        std::cerr << "Only supporte 1-bit and 24-bit BMP" << info.bitCount << " bits." << std::endl;
        return -3;
    }

    int imgWidth  = info.width;
    int imgHeight = abs(info.height);
    if (imgWidth != dmd_width || imgHeight != dmd_height) {
        std::cerr << "Resolution mismatch: " << imgWidth << "x" << imgHeight
            << " vs " << dmd_width << "x" << dmd_height << std::endl;
        return -4;
    }

    // 如果1位图像为24位图像,如果是24位图像直接使用原始数据
    std::vector<uint8_t> rgb24Buffer;
    const uint8_t* imageDataForCompression = nullptr;
    size_t dataSize = 0;

    if (info.bitCount == 1) {
        rgb24Buffer = Convert1To24Bit(info);
        imageDataForCompression = rgb24Buffer.data();
        dataSize = rgb24Buffer.size();
        std::cout << "Converted 1-bit BMP to 24-bit RGB." << std::endl;
    }
    else { 
        // 直接使用 info.rawData(注意 BMP 存储为 BGR,Splash_createImage 内部会做 BGR->RGB 和垂直翻转)
        imageDataForCompression = info.rawData.data();
        dataSize = info.rawData.size();
    }

    // 构造虚拟的 BMP 完整文件缓冲区(用于 Splash_createImage)为了
    // 使用 Splash_createImage,需要构造一个临时的 24 位 BMP 内存镜像
    // 构造 BMP 文件头(14字节)+ 信息头(40字节)+ 像素数据
    int bmpHeaderSize = 14 + 40;
    int rowSize24 = (imgWidth * 3 + 3) & ~3;
    int pixelDataSize = rowSize24 * imgHeight;
    std::vector<uint8_t> fakeBMP(bmpHeaderSize + pixelDataSize);

    // 文件头
    uint16_t bfType = 0x4D42;
    uint32_t bfSize = bmpHeaderSize + pixelDataSize;
    uint32_t bfOffBits = bmpHeaderSize;
    memcpy(fakeBMP.data(), &bfType, 2);
    memcpy(fakeBMP.data() + 2, &bfSize, 4);
    memcpy(fakeBMP.data() + 10, &bfOffBits, 4);

    // 信息头
    uint32_t biSize = 40;
    int32_t biWidth = imgWidth;
    int32_t biHeight = imgHeight;
    uint16_t biPlanes = 1;
    uint16_t biBitCount = 24;
    uint32_t biCompression = 0;
    uint32_t biSizeImage = pixelDataSize;
    int32_t biXPelsPerMeter = 0;
    int32_t biYPelsPerMeter = 0;
    uint32_t biClrUsed = 0;
    uint32_t biClrImportant = 0;
    uint8_t* header = fakeBMP.data() + 14;
    memcpy(header, &biSize, 4);
    memcpy(header + 4, &biWidth, 4);
    memcpy(header + 8, &biHeight, 4);
    memcpy(header + 12, &biPlanes, 2);
    memcpy(header + 14, &biBitCount, 2);
    memcpy(header + 16, &biCompression, 4);
    memcpy(header + 20, &biSizeImage, 4);
    memcpy(header + 24, &biXPelsPerMeter, 4);
    memcpy(header + 28, &biYPelsPerMeter, 4);
    memcpy(header + 32, &biClrUsed, 4);
    memcpy(header + 36, &biClrImportant, 4);

    // 填入像素数据(需要保持每一行对齐到4字节,且BGR顺序)
    const uint8_t* src = (info.bitCount == 1) ? imageDataForCompression : imageDataForCompression;
    for (int y = 0; y < imgHeight; ++y) {
        int srcRow = y; 
        // 如果原始数据是自顶向下,需要翻转?我们根据 BMP 规范:当 biHeight >0 时,数据存储为自底向上。
        // 为了简单,我们假设原始数据已经是自顶向下(第一行对应图像顶部)。
        // 我们构造标准的自底向上 BMP:最后一行放在数据开头。
        int dstY = y;
        uint8_t* dstRow = fakeBMP.data() + bmpHeaderSize + dstY * rowSize24;
        const uint8_t* srcRowPtr = src + y * imgWidth * 3;
        for (int x = 0; x < imgWidth; ++x) {
            dstRow[x * 3 + 0] = srcRowPtr[x * 3 + 0]; // B
            dstRow[x * 3 + 1] = srcRowPtr[x * 3 + 1]; // G
            dstRow[x * 3 + 2] = srcRowPtr[x * 3 + 2]; // R
        }
    }

    int32_t* pWidth = (int32_t*)(fakeBMP.data() + 18);
    int32_t* pHeight = (int32_t*)(fakeBMP.data() + 22);
    std::cout << "Fake BMP width = " << *pWidth << ", height = " << *pHeight << std::endl;

    //获取图像splash数据
    COMPRESSED_BITMAPIMAGES images = { nullptr, 0, nullptr, 0 };
    int  compression_format = 0xF;
    bool split = true;
    int ret = Splash_createImage(fakeBMP.data(), &images, &compression_format, split);
    if (ret != 0) {
        std::cerr << "Splash_createImage failed with error " << ret << std::endl;
        return -5;
    }

    unsigned char* leftData = images.bitmapImage1;
    unsigned char* rightData = images.bitmapImage2;
    int leftSize  = images.sizeBitmap1;
    int rightSize = images.sizeBitmap2;
    if (!leftData || !rightData || leftSize == 0 || rightSize == 0) {
        std::cerr << "Compressed image data is empty" << std::endl;
        // 注意需要释放可能已分配的内存
        if (leftData)  free(leftData);
        if (rightData) free(rightData);
        return -6;
    }

    // 上传主控制器(左半图)
    bool master = true;
    if (DLPC900_InitPatternMemLoad(master, imageIndex, leftSize) < 0) 
    {
        std::cerr << "Master InitPatternMemLoad failed" << std::endl;
        free(leftData); free(rightData);
        return -7;
    }
    int left_offset = 0;
    int left_remaining = leftSize;

    while (left_remaining > 0) {
        int sent = DLPC900_pattenMemLoad(master, leftData + leftSize - left_remaining, left_remaining);
        if (sent < 0) {
            std::cerr << "Master pattenMemLoad failed" << std::endl;
            free(leftData); free(rightData);
            return -8;
        }
        left_offset += sent;
        left_remaining -= sent;
        std::cout << "Master upload: " << (left_offset * 100 / leftSize) << "%\r" << std::flush;
    }
    std::cout << std::endl << "Master image uploaded." << std::endl;

    // 上传从控制器(右半图)
    master = false;
    if (DLPC900_InitPatternMemLoad(master, imageIndex, rightSize) < 0)
    {
        std::cerr << "Slave InitPatternMemLoad failed" << std::endl;
        free(leftData); free(rightData);
        return -9;
    }
    int right_offset = 0;
    int right_remaining = rightSize;

    while (right_remaining > 0) {
        int sent = DLPC900_pattenMemLoad(master, rightData + rightSize - right_remaining, right_remaining);
        if (sent < 0) {
            std::cerr << "Slave pattenMemLoad failed" << std::endl;
            free(leftData); free(rightData);
            return -10;
        }
        right_offset += sent;
        right_remaining -= sent;
        std::cout << "Slave upload: " << (right_offset * 100 / rightSize) << "%\r" << std::flush;
    }
    std::cout << std::endl << "Slave image uploaded." << std::endl;

    free(leftData);
    free(rightData);
    return 0;
}

Below is the code for my main program. The current issue is that when I download these three images, only the third image can be displayed. The first two images have a display time, but no patterns are shown. There is a 4-second period where there is no image, and then the third image starts to be displayed in 2 seconds. Is this a problem with my LUT configuration or with the download function?

        //只有暂停显示的情况下才允许配置 LUT 和显示图形
        result[4] = DLPC900_PatternDisplay(0);
        if (result[4] < 0)
        {
            std::cout << "Error sending pattern display command" << std::endl;
            return -1;
        }

        std::vector<std::string> imagePaths =
        {
            "C:\\Users\\leaper\\Desktop\\DLPC900\\DLPC900REF-SW-5.3.0\\DLPC900REF-SW-5.3.0\\DLPC900REF-GUI\\Images and Batch files\\LCR670S_Images\\0101.bmp",
            "C:\\Users\\leaper\\Desktop\\DLPC900\\DLPC900REF-SW-5.3.0\\DLPC900REF-SW-5.3.0\\DLPC900REF-GUI\\Images and Batch files\\LCR670S_Images\\0098.bmp",
            "C:\\Users\\leaper\\Desktop\\DLPC900\\DLPC900REF-SW-5.3.0\\DLPC900REF-SW-5.3.0\\DLPC900REF-GUI\\Images and Batch files\\LCR670S_Images\\0303.bmp",
        };

        // 通用参数(可根据需要调整)
        int ExpUs = 2000000;         // 曝光时间
        int DarkTime = 0;            // 黑暗时间
        int BitDepth = 1;            // 图像深度
        int LEDSelect = 7;           // LED颜色
        bool ClearPat = false;       // 显示后是否清除图案
        bool WaitForTrigger = false; // 是否需要外部触发(内部触发连续播放)
        bool TrigOut2 = true;        // 是否启用 Trigger2 输出

        for(int i = 0; i < imagePaths.size(); i++)
        {
            result[5] = DLPC900_AddToPatLut(i, ExpUs, ClearPat, BitDepth, LEDSelect, WaitForTrigger, DarkTime, TrigOut2, i, 0);
            if (result[5] != 0)
            {
                std::cout << "Error adding pattern " << i + 1 << " to LUT" << std::endl;
            }
        }

        result[6] = DLPC900_SendPatLut();
        if (result[6] != 0)
        {
            std::cout << "Error sending pattern LUT" << std::endl;
        }

        unsigned int numLutEntries = imagePaths.size();
        unsigned int repeat = 0;
        result[7] = DLPC900_SetPatternConfig(numLutEntries, repeat);
        if (result[7] < 0)
        {
            std::cout << "Error setting pattern config" << std::endl;
            return -1;
        }
       
        for (int i = 0; i < imagePaths.size(); i++) 
        {
            result[8] = DownloadCompressedImage(imagePaths[i], i, 2716, 1600);
            if (result[8] == 0) 
            {
                std::cout << "Image " << std::filesystem::path(imagePaths[i]).filename() << " Download completed." << std::endl;
            }
            else {
                std::cout << "Image " << std::filesystem::path(imagePaths[i]).filename() << " Download failed with code " << result[9] << std::endl;
            }
        }