#include #include #include #include #include "alp.h" #include #include #include #include #include #include #include #pragma pack(push, 1) struct BMPHeader { uint16_t fileType; uint32_t fileSize; uint16_t reserved1; uint16_t reserved2; uint32_t offsetData; }; struct DIBHeader { uint32_t size; int32_t width; int32_t height; uint16_t planes; uint16_t bitCount; uint32_t compression; uint32_t sizeImage; int32_t xPelsPerMeter; int32_t yPelsPerMeter; uint32_t colorsUsed; uint32_t colorsImportant; }; #pragma pack(pop) int readBMPFile(const std::string& filePath, std::vector& bImage, BMPHeader& bmpHeader, DIBHeader& dibHeader) { std::ifstream file(filePath, std::ios::binary); if (!file) { std::cerr << "ファイルを開けません: " << filePath << std::endl; return 1; } file.read(reinterpret_cast(&bmpHeader), sizeof(BMPHeader)); file.read(reinterpret_cast(&dibHeader), sizeof(DIBHeader)); if (bmpHeader.fileType != 0x4D42) { std::cerr << "有効なBMPファイルではありません: " << filePath << std::endl; return 1; } if (dibHeader.width != 1920 || dibHeader.height != 1080 || dibHeader.bitCount != 8) { std::cerr << "BMPの仕様が正しくありません (1920x1080, 8bit 必須): " << filePath << std::endl; return 1; } file.seekg(bmpHeader.offsetData, std::ios::beg); bImage.resize(dibHeader.sizeImage); file.read(reinterpret_cast(bImage.data()), dibHeader.sizeImage); std::cout << "BMP読み込み成功: " << filePath << std::endl; return 0; } // 画像を (mx, my) ピクセルだけシフトする関数 void shiftImage(std::vector& image, int width, int height, int mx, int my) { std::vector shiftedImage(width * height, 0); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int newX = x + mx; int newY = y + my; if (newX >= 0 && newX < width && newY >= 0 && newY < height) { shiftedImage[newY * width + newX] = image[y * width + x]; } } } image = shiftedImage; // シフト後のデータをコピー } int binary(int& PicTime, int &numImages, int &mx, int &my, std::vector &bmpFiles) { ALP_ID nDevId, nSeqId; long nSizeX, nSizeY, nReturn; if (ALP_OK != AlpDevAlloc(ALP_DEFAULT, ALP_DEFAULT, &nDevId)) { std::cerr << "error(AlpDevAlloc)" << std::endl; return 1; } if (ALP_OK != AlpDevInquire(nDevId, ALP_DEV_DISPLAY_WIDTH, &nSizeX) || ALP_OK != AlpDevInquire(nDevId, ALP_DEV_DISPLAY_HEIGHT, &nSizeY)) { std::cerr << "error(AlpDevInquire)" << std::endl; return 1; } if (ALP_OK != AlpSeqAlloc(nDevId, 1, numImages, &nSeqId)) { std::cerr << "error(AlpSeqAlloc)" << std::endl; return 1; } std::vector pImageData(nSizeX * nSizeY * numImages); for (int imgIdx = 0; imgIdx < numImages; imgIdx++) { std::vector bImage; BMPHeader bmpHeader; DIBHeader dibHeader; if (readBMPFile(bmpFiles[imgIdx], bImage, bmpHeader, dibHeader) != 0) { return 1; } shiftImage(bImage, nSizeX, nSizeY, mx, my); // 同一の mx, my を適用 for (long nXY = 0; nXY < nSizeX * nSizeY; nXY++) { pImageData[imgIdx * nSizeX * nSizeY + nXY] = (bImage[nXY] == 0) ? 0x00 : 0x80; } } nReturn = AlpSeqPut(nDevId, nSeqId, 0, numImages, pImageData.data()); if (ALP_OK != nReturn) { std::cerr << "error(AlpSeqPut)" << std::endl; return 1; } if (ALP_OK != AlpSeqControl(nDevId, nSeqId, ALP_BIN_MODE, ALP_BIN_UNINTERRUPTED)) { std::cerr << "error(AlpSeqControl)" << std::endl; return 1; } if (ALP_OK != AlpSeqTiming(nDevId, nSeqId, PicTime, PicTime, ALP_DEFAULT, ALP_DEFAULT, ALP_DEFAULT)) { std::cerr << "error(AlpSeqTiming)" << std::endl; return 1; } if (ALP_OK != AlpProjStart(nDevId, nSeqId)) { std::cerr << "error(AlpProjStart)" << std::endl; return 1; } /* std::cout << "投影中... 任意のキーを押して停止してください。" << std::endl; do { _getch(); } while (_kbhit());*/ //Sleep(numImages * PicTime / 1000); std::cout << "投影中... 任意のキーを押すと中断します。" << std::endl; // 別スレッドでキー入力を監視 while (true) { if (_kbhit()) { //_getch(); // キーを読み捨てる std::cout << "キー入力により投影を中断します。" << std::endl; AlpDevHalt(nDevId); break; } // シーケンスの終了を待つ if (ALP_OK == AlpProjWait(nDevId)) { return 0; } Sleep(10); } AlpDevHalt(nDevId); AlpDevFree(nDevId); std::cout << "投影終了" << std::endl; return 0; } int binary_with_key(int& PicTime, int& numImages, int& mx, int& my, std::vector& bmpFiles) { ALP_ID nDevId, nSeqId; long nSizeX, nSizeY; if (ALP_OK != AlpDevAlloc(ALP_DEFAULT, ALP_DEFAULT, &nDevId)) { std::cerr << "error(AlpDevAlloc)" << std::endl; return 1; } AlpDevInquire(nDevId, ALP_DEV_DISPLAY_WIDTH, &nSizeX); AlpDevInquire(nDevId, ALP_DEV_DISPLAY_HEIGHT, &nSizeY); if (ALP_OK != AlpSeqAlloc(nDevId, 1, numImages, &nSeqId)) { std::cerr << "error(AlpSeqAlloc)" << std::endl; return 1; } std::vector pImageData(nSizeX * nSizeY * numImages); for (int imgIdx = 0; imgIdx < numImages; imgIdx++) { std::vector bImage; BMPHeader bmpHeader; DIBHeader dibHeader; if (readBMPFile(bmpFiles[imgIdx], bImage, bmpHeader, dibHeader) != 0) { return 1; } shiftImage(bImage, nSizeX, nSizeY, mx, my); for (long nXY = 0; nXY < nSizeX * nSizeY; nXY++) { pImageData[imgIdx * nSizeX * nSizeY + nXY] = (bImage[nXY] == 0) ? 0x00 : 0x80; } } AlpSeqPut(nDevId, nSeqId, 0, numImages, pImageData.data()); // ★ ポイント:シーケンス終了後も最後の画像を保持 AlpSeqControl(nDevId, nSeqId, ALP_BIN_MODE, ALP_BIN_UNINTERRUPTED); AlpSeqTiming(nDevId, nSeqId, PicTime, PicTime, ALP_DEFAULT, ALP_DEFAULT, ALP_DEFAULT); std::atomic stopRequested(false); // 別スレッドでキー入力を監視 std::thread inputThread([&]() { while (!stopRequested.load()) { if (_kbhit()) { _getch(); // 入力を消費 std::cout << "\nキー入力検出 → 投影を中止します。" << std::endl; stopRequested.store(true); AlpDevHalt(nDevId); // 即OFF break; } Sleep(10); } }); std::cout << "投影中...(キーを押すと中止)" << std::endl; AlpProjStart(nDevId, nSeqId); // ★ 投影が自然終了するまで待つ AlpProjWait(nDevId); // ★ ここに到達した時点で最後の画像が表示されたままになっている std::cout << "最後の画像を保持中... キーを押すと停止します。" << std::endl; // stopRequested が true になるまで待つ(キー押下を待つ) while (!stopRequested.load()) { Sleep(10); } inputThread.join(); AlpDevFree(nDevId); std::cout << "投影終了" << std::endl; return 0; } int repeat(int &PicTime, int &numImages, int &mx, int &my, std::vector &bmpFiles) { ALP_ID nDevId, nSeqId; long nSizeX, nSizeY, nReturn; if (ALP_OK != AlpDevAlloc(ALP_DEFAULT, ALP_DEFAULT, &nDevId)) { std::cerr << "error(AlpDevAlloc)" << std::endl; return 1; } if (ALP_OK != AlpDevInquire(nDevId, ALP_DEV_DISPLAY_WIDTH, &nSizeX) || ALP_OK != AlpDevInquire(nDevId, ALP_DEV_DISPLAY_HEIGHT, &nSizeY)) { std::cerr << "error(AlpDevInquire)" << std::endl; return 1; } if (ALP_OK != AlpSeqAlloc(nDevId, 1, numImages, &nSeqId)) { std::cerr << "error(AlpSeqAlloc)" << std::endl; return 1; } std::vector pImageData(nSizeX * nSizeY * numImages); for (int imgIdx = 0; imgIdx < numImages; imgIdx++) { std::vector bImage; BMPHeader bmpHeader; DIBHeader dibHeader; if (readBMPFile(bmpFiles[imgIdx], bImage, bmpHeader, dibHeader) != 0) { return 1; } shiftImage(bImage, nSizeX, nSizeY, mx, my); // 同一の mx, my を適用 for (long nXY = 0; nXY < nSizeX * nSizeY; nXY++) { pImageData[imgIdx * nSizeX * nSizeY + nXY] = (bImage[nXY] == 0) ? 0x00 : 0x80; } } nReturn = AlpSeqPut(nDevId, nSeqId, 0, numImages, pImageData.data()); if (ALP_OK != nReturn) { std::cerr << "error(AlpSeqPut)" << std::endl; return 1; } if (ALP_OK != AlpSeqControl(nDevId, nSeqId, ALP_SEQ_REPEAT, 1)) { std::cerr << "error(AlpSeqControl)" << std::endl; return 1; } if (ALP_OK != AlpSeqTiming(nDevId, nSeqId, ALP_DEFAULT, PicTime, ALP_DEFAULT, ALP_DEFAULT, ALP_DEFAULT)) { std::cerr << "error(AlpSeqTiming)" << std::endl; return 1; } if (ALP_OK != AlpProjStart(nDevId, nSeqId)) { std::cerr << "error(AlpProjStart)" << std::endl; return 1; } /* std::cout << "投影中... 任意のキーを押して停止してください。" << std::endl; do { _getch(); } while (_kbhit());*/ //Sleep(numImages * PicTime / 1000); std::cout << "投影中... 任意のキーを押すと中断します。" << std::endl; // 別スレッドでキー入力を監視 while (true) { if (_kbhit()) { //_getch(); // キーを読み捨てる std::cout << "キー入力により投影を中断します。" << std::endl; AlpDevHalt(nDevId); break; } // シーケンスの終了を待つ if (ALP_OK == AlpProjWait(nDevId)) { return 0; } Sleep(10); } AlpDevHalt(nDevId); AlpDevFree(nDevId); std::cout << "投影終了" << std::endl; return 0; } int main(int argc, char* argv[]) { if (argc < 4) { std::cerr << "使用方法: " << argv[0] << " ..." << std::endl; return 1; } int PicTime = std::atoi(argv[4]); int numImages = argc - 5; int mx = std::atoi(argv[1]); int my = std::atoi(argv[2]); std::string mode = argv[3]; std::vector bmpFiles; for (int i = 0; i < numImages; i++) { bmpFiles.push_back(argv[5 + i]); // BMPファイル名 } if(mode == "b") { binary(PicTime, numImages, mx, my, bmpFiles); } else if (mode == "b_key") { binary_with_key(PicTime, numImages, mx, my, bmpFiles); } else if(mode == "r") { repeat(PicTime, numImages, mx, my, bmpFiles); } else { std::cerr << "error(mode)" << std::endl; return 1; } return 0; }