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;
}
}