├── Makefile ├── PhotonAaMatrix.h ├── PhotonCpp.cpp ├── PhotonCpp.sln ├── PhotonCpp.vcxproj ├── PhotonCpp.vcxproj.filters ├── PhotonDot.h ├── PhotonFileHeader.h ├── PhotonFileLayer.h ├── PhotonFilePreview.h ├── PhotonFilePrintParameters.h ├── PhotonInputStream.h ├── PhotonLayer.h ├── PhotonLine.h ├── PhotonMatrix.h ├── PhotonOutputStream.h ├── PhotonProjectType.h ├── PhotonRow.h ├── README.md ├── _model.photon ├── model.scad ├── model.stl ├── pch.cpp ├── pch.h └── stb_image.h /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CC=g++ 5 | CPPFLAGS=-I. 6 | DEPS = pch.h PhotonAaMatrix.h PhotonDot.h PhotonFileHeader.h \ 7 | PhotonFileLayer.h PhotonFilePreview.h PhotonFilePrintParameters.h \ 8 | PhotonInputStream.h PhotonLayer.h PhotonLine.h PhotonMatrix.h \ 9 | PhotonOutputStream.h PhotonProjectType.h PhotonRow.h stb_image.h 10 | 11 | PngToPhoton: 12 | $(CC) -std=c++11 -o PngToPhoton PhotonCpp.cpp $(CPPFLAGS) 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /PhotonAaMatrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | class PhotonAaMatrix { 27 | 28 | public: 29 | std::array, 5> aaMatrix_; 30 | 31 | private: 32 | std::array hasDivisor_; 33 | 34 | public: 35 | void clear() { 36 | for (int y = 0; y < 5; y++) { 37 | for (int x = 0; x < 5; x++) { 38 | aaMatrix_[y][x] = 0; 39 | } 40 | } 41 | } 42 | 43 | void set(int x, int y, int val) { 44 | aaMatrix_[y-1][x-1] = val; 45 | } 46 | 47 | photoncpp::MatrixInt calc(const photoncpp::MatrixInt & source) { 48 | photoncpp::MatrixInt target; 49 | 50 | if (!source.empty()) { 51 | target = source; 52 | 53 | int divisor = 0; 54 | for (int y = 0; y < 5; y++) { 55 | int rowDivistor = 0; 56 | for (int x = 0; x < 5; x++) { 57 | rowDivistor += aaMatrix_[y][x]; 58 | } 59 | hasDivisor_[y] = (rowDivistor>0); 60 | divisor += rowDivistor; 61 | } 62 | 63 | if (divisor >0) { 64 | int height = source.size(); 65 | if (height > 0) { 66 | int width = source[0].size(); 67 | if (width > 0) { 68 | int sum;; 69 | int dy; 70 | int dx; 71 | for (int y = 0; y < height; y++) { 72 | for (int x = 0; x < width; x++) { 73 | sum = 0; 74 | for (int cy = -2; cy <= 2; cy++) { 75 | if (hasDivisor_[2+cy]) 76 | for (int cx = -2; cx <= 2; cx++) { 77 | dy = y+cy; 78 | dx = x+cx; 79 | if (dy>=0 && dy< height) { 80 | if (dx>=0 && dx< width) { 81 | sum += source[dy][dx] * aaMatrix_[2+cy][2+cx]; 82 | } else { 83 | sum += source[y][x] * aaMatrix_[2+cy][2+cx]; 84 | } 85 | } else { 86 | sum += source[y][x] * aaMatrix_[2+cy][2+cx]; 87 | } 88 | } 89 | } 90 | target[y][x] = sum / divisor; 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } 97 | return target; 98 | } 99 | }; 100 | 101 | 102 | -------------------------------------------------------------------------------- /PhotonCpp.cpp: -------------------------------------------------------------------------------- 1 | // PhotonCpp.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | // 3 | 4 | #include "pch.h" 5 | 6 | #define STB_IMAGE_IMPLEMENTATION 7 | #define STBI_ONLY_PNG 8 | #include "stb_image.h" 9 | 10 | 11 | std::pair png2layer(const std::string & bufferPng) 12 | { 13 | char* img = nullptr; 14 | int w = 0; 15 | int h = 0; 16 | int n = 0; 17 | img = (char*)stbi_load_from_memory((unsigned char*)bufferPng.data(), bufferPng.length(), &w, &h, &n, 4); 18 | PhotonLayer res(w, h); 19 | 20 | if (!img) 21 | return {"Invalid PNG file format", res}; 22 | 23 | if (w != 1440 || h != 2560) 24 | return { "Invalid PNG image size: (" + std::to_string(w) + "x" + std::to_string(h) + " instead of 1440x2560)", res }; 25 | 26 | for (int j = 0; j < h; j++) 27 | for (int i = 0; i < w; i++) 28 | { 29 | int pos = ((w * j) + i) * 4; 30 | bool present = (img[pos + 3] != 0 /* not alpha transparent */) && (img[pos] == 0 /* probably black */); 31 | if (present) 32 | res.supported(i, j); 33 | } 34 | 35 | stbi_image_free(img); 36 | return { "", res }; 37 | } 38 | 39 | std::string getModel() 40 | { 41 | const unsigned char gz[] = { 42 | 120, 94, 147, 100, 248, 43, 196, 196, 192, 192, 80, 45, 210, 225, 212, 250, 43 | 250, 163, 19, 3, 131, 152, 51, 3, 18, 56, 123, 198, 199, 150, 129, 97, 44 | 129, 35, 3, 3, 11, 80, 220, 193, 129, 3, 40, 183, 128, 21, 72, 112, 45 | 49, 48, 20, 0, 169, 43, 64, 205, 204, 64, 186, 133, 145, 129, 225, 25, 46 | 144, 1, 164, 24, 102, 0, 197, 108, 128, 98, 32, 246, 127, 134, 255, 200, 47 | 198, 49, 232, 2, 121, 32, 60, 1, 72, 127, 97, 192, 4, 58, 201, 219, 48 | 140, 252, 163, 11, 189, 57, 13, 78, 71, 233, 36, 43, 24, 108, 81, 230, 49 | 2, 179, 228, 13, 206, 121, 109, 81, 230, 52, 184, 32, 5, 18, 13, 244, 50 | 6, 177, 59, 4, 33, 42, 64, 162, 32, 182, 188, 1, 68, 252, 130, 20, 51 | 50, 175, 67, 16, 194, 131, 232, 238, 16, 228, 50, 210, 73, 150, 67, 82, 52 | 9, 225, 131, 236, 1, 169, 4, 241, 100, 145, 100, 33, 234, 97, 34, 190, 53 | 82, 32, 53, 93, 94, 58, 201, 178, 96, 151, 173, 16, 100, 50, 0, 241, 54 | 100, 12, 252, 163, 13, 193, 174, 131, 137, 200, 26, 156, 137, 234, 177, 210, 55 | 145, 226, 48, 56, 37, 8, 211, 35, 111, 208, 227, 165, 35, 197, 9, 20, 56 | 1, 233, 81, 52, 120, 19, 197, 105, 160, 147, 28, 110, 36, 15, 12, 6, 57 | 16, 94, 2, 12, 48, 236, 97, 194, 98, 136, 8, 19, 33, 120, 152, 8, 58 | 34, 133, 137, 144, 1, 34, 76, 64, 42, 96, 97, 34, 136, 18, 38, 130, 59 | 112, 85, 160, 48, 17, 52, 64, 14, 19, 1, 180, 48, 17, 48, 64, 14, 60 | 19, 126, 140, 48, 129, 137, 32, 194, 132, 31, 37, 76, 248, 48, 194, 132, 61 | 31, 75, 152, 8, 162, 132, 137, 48, 52, 76, 14, 26, 48, 48, 60, 112, 62 | 96, 96, 104, 2, 166, 199, 5, 80, 90, 204, 217, 108, 71, 190, 89, 203, 63 | 141, 102, 179, 26, 197, 103, 198, 12, 12, 14, 14, 32, 204, 193, 128, 11, 64 | 64, 210, 171, 3, 48, 77, 154, 21, 99, 170, 129, 164, 107, 136, 154, 178, 65 | 50, 6, 6, 236, 106, 206, 216, 194, 210, 253, 154, 151, 216, 213, 212, 142, 66 | 130, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 67 | 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 68 | 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 69 | 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 70 | 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 71 | 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 72 | 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 73 | 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 74 | 24, 13, 129, 209, 16, 24, 13, 129, 209, 16, 24, 13, 1, 66, 33, 144, 75 | 209, 140, 164, 194, 174, 121, 52, 192, 70, 67, 96, 52, 4, 70, 67, 96, 76 | 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 77 | 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 78 | 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 79 | 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 80 | 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 81 | 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 82 | 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 83 | 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 67, 96, 52, 4, 70, 84 | 67, 96, 52, 4, 8, 134, 64, 250, 104, 24, 141, 134, 192, 104, 8, 140, 85 | 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 86 | 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 87 | 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 88 | 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 89 | 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 90 | 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 91 | 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 92 | 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 93 | 8, 140, 134, 192, 104, 8, 16, 12, 129, 204, 38, 36, 37, 246, 77, 163, 94 | 33, 54, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 95 | 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 96 | 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 97 | 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 98 | 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 99 | 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 100 | 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 101 | 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 102 | 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 64, 48, 4, 103 | 70, 111, 205, 28, 77, 36, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 104 | 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 105 | 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 106 | 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 107 | 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 108 | 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 109 | 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 110 | 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 111 | 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 48, 26, 2, 163, 33, 64, 112 | 56, 4, 178, 26, 145, 212, 56, 52, 142, 6, 217, 104, 8, 140, 134, 192, 113 | 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 114 | 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 115 | 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 116 | 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 117 | 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 118 | 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 119 | 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 120 | 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 134, 192, 104, 8, 140, 121 | 134, 192, 104, 8, 140, 134, 0, 193, 16, 72, 7, 0, 143, 56, 126, 118 122 | }; 123 | 124 | std::string res; 125 | res.resize(100*1024); 126 | 127 | int len = stbi_zlib_decode_buffer(&res[0], res.length(), (const char*)gz, sizeof gz); 128 | 129 | res.resize(len); 130 | return res; 131 | } 132 | 133 | int main(int argc, char * argv[]) 134 | { 135 | if (argc != 3) 136 | { 137 | std::cerr << "\nUsage: PngToPhoton \n" 138 | "To read data from STDIN use '-' as filename.\n" 139 | "To write data to STDOUT use '-' as filename.\n\n" 140 | "White and transparent areas of the image are treated as voids.\n" 141 | "Check with Photon File Validator after conversion. Use output at your own risk.\n"; 142 | return -1; 143 | } 144 | 145 | #ifdef WIN32 146 | _setmode(_fileno(stdout), _O_BINARY); 147 | _setmode(_fileno(stdin), _O_BINARY); 148 | #endif // WIN32 149 | 150 | std::string bufferModel = getModel(); 151 | 152 | PhotonFileHeader photonFileHeader(bufferModel); 153 | PhotonFilePreview previewOne(photonFileHeader.getPreviewOneOffsetAddress(), bufferModel); 154 | PhotonFilePreview previewTwo(photonFileHeader.getPreviewTwoOffsetAddress(), bufferModel); 155 | 156 | PhotonFilePrintParameters photonFilePrintParameters; 157 | if (photonFileHeader.getVersion() > 1) 158 | { 159 | PhotonFilePrintParameters dummy(photonFileHeader.getPrintParametersOffsetAddress(), bufferModel); 160 | photonFilePrintParameters = std::move(dummy); 161 | } 162 | 163 | int margin = 0; 164 | 165 | std::vector layers = PhotonFileLayer::readLayers(photonFileHeader, bufferModel, margin); 166 | 167 | // PhotonFileLayer::calculateLayers(photonFileHeader,layers, 0); 168 | 169 | // load png 170 | std::string bufferPng; 171 | 172 | if (std::string("-") == argv[1]) 173 | { 174 | std::string tmp(std::istreambuf_iterator(std::cin), {}); 175 | bufferPng = std::move(tmp); 176 | } 177 | else 178 | { 179 | std::ifstream ifPng(argv[1], std::ios_base::binary); 180 | 181 | if (ifPng.fail()) 182 | { 183 | std::cerr << "Error opening input file.\n"; 184 | return -1; 185 | } 186 | 187 | ifPng.seekg(0, std::ios::end); 188 | std::streamoff size = 0; 189 | size = ifPng.tellg(); 190 | bufferPng.resize((unsigned int)size); 191 | ifPng.seekg(0); 192 | ifPng.read(&bufferPng[0], size); 193 | ifPng.close(); 194 | } 195 | 196 | std::pair rle = png2layer(bufferPng); 197 | if (!rle.first.empty()) 198 | { 199 | std::cerr << rle.first << "\n"; 200 | return -1; 201 | } 202 | 203 | PhotonLayer & layerPng = rle.second; 204 | int antiAliasLevel = 1; 205 | if (photonFileHeader.getVersion() > 1) { 206 | antiAliasLevel = photonFileHeader.getAntiAliasingLevel(); 207 | } 208 | 209 | for (int i = 0; i < photonFileHeader.getNumberOfLayers(); i++) { 210 | PhotonFileLayer & layer = layers.at(i); 211 | layer.saveLayer(layerPng); 212 | if (antiAliasLevel > 1) { 213 | for (int a = 0; a < (antiAliasLevel - 1); a++) { 214 | layer.getAntiAlias(a).saveLayer(layerPng); 215 | } 216 | } 217 | } 218 | 219 | 220 | 221 | 222 | // writing is here: 223 | int headerPos = 0; 224 | int previewOnePos = headerPos + photonFileHeader.getByteSize(); 225 | int previewTwoPos = previewOnePos + previewOne.getByteSize(); 226 | int layerDefinitionPos = previewTwoPos + previewTwo.getByteSize(); 227 | 228 | int parametersPos = 0; 229 | if (photonFileHeader.getVersion() > 1) { 230 | parametersPos = layerDefinitionPos; 231 | layerDefinitionPos = parametersPos + photonFilePrintParameters.getByteSize(); 232 | } 233 | 234 | int dataPosition = layerDefinitionPos + (PhotonFileLayer::getByteSize() * photonFileHeader.getNumberOfLayers() * antiAliasLevel); 235 | 236 | 237 | std::ofstream ofs; 238 | if (std::string("-") != argv[2]) 239 | { 240 | ofs.open(argv[2], std::ios_base::binary); 241 | if (ofs.fail()) 242 | { 243 | std::cerr << "Error opening output file.\n"; 244 | return -1; 245 | } 246 | } 247 | 248 | PhotonOutputStream os( std::string("-") != argv[2] ? ofs : std::cout); 249 | photonFileHeader.save(os, previewOnePos, previewTwoPos, layerDefinitionPos, parametersPos); 250 | previewOne.save(os, previewOnePos); 251 | previewTwo.save(os, previewTwoPos); 252 | 253 | if (photonFileHeader.getVersion() > 1) { 254 | photonFilePrintParameters.save(os); 255 | } 256 | 257 | // Optimize order for speed read on photon 258 | for (int i = 0; i < photonFileHeader.getNumberOfLayers(); i++) { 259 | PhotonFileLayer & layer = layers.at(i); 260 | dataPosition = layer.savePos(dataPosition); 261 | if (antiAliasLevel > 1) { 262 | for (int a = 0; a < (antiAliasLevel - 1); a++) { 263 | dataPosition = layer.getAntiAlias(a).savePos(dataPosition); 264 | } 265 | } 266 | } 267 | 268 | // Order for backward compatibility with photon/cbddlp version 1 269 | for (int i = 0; i < photonFileHeader.getNumberOfLayers(); i++) { 270 | layers.at(i).save(os); 271 | } 272 | 273 | if (antiAliasLevel > 1) { 274 | for (int a = 0; a < (antiAliasLevel - 1); a++) { 275 | for (int i = 0; i < photonFileHeader.getNumberOfLayers(); i++) { 276 | layers.at(i).getAntiAlias(a).save(os); 277 | } 278 | } 279 | } 280 | 281 | // Optimize order for speed read on photon 282 | for (int i = 0; i < photonFileHeader.getNumberOfLayers(); i++) { 283 | PhotonFileLayer & layer = layers.at(i); 284 | layer.saveData(os); 285 | if (antiAliasLevel > 1) { 286 | for (int a = 0; a < (antiAliasLevel - 1); a++) { 287 | layer.getAntiAlias(a).saveData(os); 288 | } 289 | } 290 | } 291 | 292 | return 0; 293 | } 294 | -------------------------------------------------------------------------------- /PhotonCpp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.705 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PngToPhoton", "PhotonCpp.vcxproj", "{73A1723A-15E8-4177-A26A-E1F251E0F6B9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Debug|x64.ActiveCfg = Debug|x64 17 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Debug|x64.Build.0 = Debug|x64 18 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Debug|x86.ActiveCfg = Debug|Win32 19 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Debug|x86.Build.0 = Debug|Win32 20 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Release|x64.ActiveCfg = Release|x64 21 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Release|x64.Build.0 = Release|x64 22 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Release|x86.ActiveCfg = Release|Win32 23 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {E7D9C908-27E0-4E92-BAF5-47E1E065EE69} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /PhotonCpp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {73A1723A-15E8-4177-A26A-E1F251E0F6B9} 24 | Win32Proj 25 | PhotonCpp 26 | 10.0.17763.0 27 | PngToPhoton 28 | 29 | 30 | 31 | Application 32 | true 33 | v141 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v141 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v141 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v141 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | false 85 | 86 | 87 | 88 | Use 89 | Level3 90 | Disabled 91 | true 92 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | true 94 | pch.h 95 | MultiThreadedDebug 96 | 97 | 98 | Console 99 | true 100 | 101 | 102 | 103 | 104 | Use 105 | Level3 106 | Disabled 107 | true 108 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | true 110 | pch.h 111 | 112 | 113 | Console 114 | true 115 | 116 | 117 | 118 | 119 | Use 120 | Level3 121 | MaxSpeed 122 | true 123 | true 124 | true 125 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | true 127 | pch.h 128 | MultiThreaded 129 | 130 | 131 | Console 132 | true 133 | true 134 | true 135 | 136 | 137 | 138 | 139 | Use 140 | Level3 141 | MaxSpeed 142 | true 143 | true 144 | true 145 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 146 | true 147 | pch.h 148 | 149 | 150 | Console 151 | true 152 | true 153 | true 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | Create 176 | Create 177 | Create 178 | Create 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /PhotonCpp.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | -------------------------------------------------------------------------------- /PhotonDot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * by bn on 02/07/2018. 27 | */ 28 | class PhotonDot { 29 | public: 30 | const static char OFF = 0x00; 31 | const static char SUPPORTED = 0x01; 32 | const static char ISLAND = 0x02; 33 | const static char CONNECTED = 0x03; 34 | 35 | int x_; 36 | int y_; 37 | 38 | PhotonDot(int x, int y) { 39 | x_ = x; 40 | y_ = y; 41 | } 42 | 43 | bool equals(const PhotonDot & photonDot) { 44 | 45 | return x_ == photonDot.x_ && y_ == photonDot.y_; 46 | 47 | } 48 | 49 | int hashCode() { 50 | int result = x_; 51 | result = 31 * result + y_; 52 | return result; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /PhotonFileHeader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * by bn on 30/06/2018. 28 | */ 29 | class PhotonFileHeader { 30 | private: 31 | int32_t header1_; 32 | int32_t version_; 33 | float bedXmm_; 34 | float bedYmm_; 35 | float bedZmm_; 36 | int32_t unknown1_; 37 | int32_t unknown2_; 38 | int32_t unknown3_; 39 | float layerHeightMilimeter_; 40 | float exposureTimeSeconds_; 41 | float exposureBottomTimeSeconds_; 42 | float offTimeSeconds_; 43 | int32_t bottomLayers_; 44 | uint32_t resolutionX_; 45 | uint32_t resolutionY_; 46 | 47 | int32_t previewOneOffsetAddress_; 48 | int32_t layersDefinitionOffsetAddress_; 49 | int32_t numberOfLayers_; 50 | 51 | int32_t previewTwoOffsetAddress_; 52 | 53 | int32_t printTimeSeconds_; 54 | PhotonProjectType projectType_; 55 | 56 | int32_t printParametersOffsetAddress_; 57 | int32_t printParametersSize_; 58 | int32_t antiAliasingLevel_; 59 | 60 | short lightPWM_; 61 | short bottomLightPWM_; 62 | 63 | int32_t unknown4_; 64 | int32_t unknown5_; 65 | int32_t unknown6_; 66 | 67 | public: 68 | PhotonFileHeader(const std::string & fileContent) { 69 | std::stringstream ss(fileContent); 70 | PhotonInputStream ds(ss); 71 | 72 | header1_ = ds.readInt(); 73 | version_ = ds.readInt(); 74 | 75 | bedXmm_ = ds.readFloat(); 76 | bedYmm_ = ds.readFloat(); 77 | bedZmm_ = ds.readFloat(); 78 | 79 | unknown1_ = ds.readInt(); 80 | unknown2_ = ds.readInt(); 81 | unknown3_ = ds.readInt(); 82 | 83 | layerHeightMilimeter_ = ds.readFloat(); 84 | exposureTimeSeconds_ = ds.readFloat(); 85 | exposureBottomTimeSeconds_ = ds.readFloat(); 86 | 87 | offTimeSeconds_ = ds.readFloat(); 88 | bottomLayers_ = ds.readInt(); 89 | 90 | resolutionX_ = ds.readInt(); 91 | resolutionY_ = ds.readInt(); 92 | 93 | previewOneOffsetAddress_ = ds.readInt(); 94 | layersDefinitionOffsetAddress_ = ds.readInt(); 95 | 96 | numberOfLayers_ = ds.readInt(); 97 | 98 | previewTwoOffsetAddress_ = ds.readInt(); 99 | printTimeSeconds_ = ds.readInt(); 100 | 101 | projectType_ = (ds.readInt() ? PhotonProjectType::lcdMirror : PhotonProjectType::cast); 102 | 103 | printParametersOffsetAddress_ = ds.readInt(); 104 | printParametersSize_ = ds.readInt(); 105 | antiAliasingLevel_ = ds.readInt(); 106 | 107 | lightPWM_ = ds.readShort(); 108 | bottomLightPWM_ = ds.readShort(); 109 | 110 | unknown4_ = ds.readInt(); 111 | unknown5_ = ds.readInt(); 112 | if (version_>1) { 113 | unknown6_ = ds.readInt(); 114 | } 115 | } 116 | 117 | int getByteSize() { 118 | return 4+4 + 4+4+4 + 4+4+4 + 4+4+4 + 4+4 + 4+4 + 4+4 + 4 + 4+4 + 4 + 4+4+4 +2+2 +4+4+ (version_>1?4:0); 119 | } 120 | 121 | void save(PhotonOutputStream os, int previewOnePos, int previewTwoPos, int layerDefinitionPos, int parametersPos) { 122 | previewOneOffsetAddress_ = previewOnePos; 123 | previewTwoOffsetAddress_ = previewTwoPos; 124 | layersDefinitionOffsetAddress_ = layerDefinitionPos; 125 | printParametersOffsetAddress_ = parametersPos; 126 | 127 | os.writeInt(header1_); 128 | os.writeInt(version_); 129 | 130 | os.writeFloat(bedXmm_); 131 | os.writeFloat(bedYmm_); 132 | os.writeFloat(bedZmm_); 133 | 134 | os.writeInt(unknown1_); 135 | os.writeInt(unknown2_); 136 | os.writeInt(unknown3_); 137 | 138 | os.writeFloat(layerHeightMilimeter_); 139 | os.writeFloat(exposureTimeSeconds_); 140 | os.writeFloat(exposureBottomTimeSeconds_); 141 | 142 | os.writeFloat(offTimeSeconds_); 143 | os.writeInt(bottomLayers_); 144 | 145 | os.writeInt(resolutionX_); 146 | os.writeInt(resolutionY_); 147 | 148 | os.writeInt(previewOneOffsetAddress_); 149 | os.writeInt(layersDefinitionOffsetAddress_); 150 | 151 | os.writeInt(numberOfLayers_); 152 | 153 | os.writeInt(previewTwoOffsetAddress_); 154 | os.writeInt(printTimeSeconds_); 155 | 156 | os.writeInt(projectType_); 157 | 158 | os.writeInt(printParametersOffsetAddress_); 159 | os.writeInt(printParametersSize_); 160 | os.writeInt(antiAliasingLevel_); 161 | 162 | os.writeShort(lightPWM_); 163 | os.writeShort(bottomLightPWM_); 164 | 165 | os.writeInt(unknown4_); 166 | os.writeInt(unknown5_); 167 | if (version_>1) { 168 | os.writeInt(unknown6_); 169 | } 170 | } 171 | 172 | 173 | int getPreviewOneOffsetAddress() const { 174 | return previewOneOffsetAddress_; 175 | } 176 | 177 | int getPreviewTwoOffsetAddress() const { 178 | return previewTwoOffsetAddress_; 179 | } 180 | 181 | int getNumberOfLayers() const { 182 | return numberOfLayers_; 183 | } 184 | 185 | int getLayersDefinitionOffsetAddress() const { 186 | return layersDefinitionOffsetAddress_; 187 | } 188 | 189 | float getNormalExposure() const { 190 | return exposureTimeSeconds_; 191 | } 192 | 193 | float getOffTime() const { 194 | return offTimeSeconds_; 195 | } 196 | 197 | uint32_t getResolutionX() const { 198 | return resolutionX_; 199 | } 200 | 201 | uint32_t getResolutionY() const { 202 | return resolutionY_; 203 | } 204 | 205 | float getBuildAreaX() const { 206 | return bedXmm_; 207 | } 208 | 209 | float getBuildAreaY() const { 210 | return bedYmm_; 211 | } 212 | 213 | float getLayerHeight() const { 214 | return layerHeightMilimeter_; 215 | } 216 | 217 | int getBottomLayers() const { 218 | return bottomLayers_; 219 | } 220 | 221 | float getBottomExposureTimeSeconds() const { 222 | return exposureBottomTimeSeconds_; 223 | } 224 | 225 | float getOffTimeSeconds() const { 226 | return offTimeSeconds_; 227 | } 228 | 229 | float getExposureTimeSeconds() const { 230 | return exposureTimeSeconds_; 231 | } 232 | 233 | void unLink() { 234 | } 235 | 236 | void setExposureTimeSeconds(float exposureTimeSeconds) { 237 | exposureTimeSeconds_ = exposureTimeSeconds; 238 | } 239 | 240 | void setExposureBottomTimeSeconds(float exposureBottomTimeSeconds) { 241 | exposureBottomTimeSeconds_ = exposureBottomTimeSeconds; 242 | } 243 | 244 | void setOffTimeSeconds(float offTimeSeconds) { 245 | offTimeSeconds_ = offTimeSeconds; 246 | } 247 | 248 | void setBottomLayers(int bottomLayers) { 249 | bottomLayers_ = bottomLayers; 250 | } 251 | 252 | int getVersion() const { 253 | return version_; 254 | } 255 | 256 | int getPrintParametersOffsetAddress() const { 257 | return printParametersOffsetAddress_; 258 | } 259 | 260 | int getPrintParametersSize() const { 261 | return printParametersSize_; 262 | } 263 | 264 | int getAntiAliasingLevel() const { 265 | return antiAliasingLevel_; 266 | } 267 | 268 | void setAntiAliasingLevel(int antiAliasingLevel) { 269 | antiAliasingLevel_ = antiAliasingLevel; 270 | } 271 | 272 | void makeVersion(int i) { 273 | version_ = i; 274 | antiAliasingLevel_ = 1; 275 | lightPWM_ = 255; 276 | bottomLightPWM_ = 255; 277 | } 278 | }; 279 | -------------------------------------------------------------------------------- /PhotonFileLayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * by bn on 01/07/2018. 27 | */ 28 | class PhotonFileLayer { 29 | private: 30 | float layerPositionZ_; 31 | float layerExposure_; 32 | float layerOffTimeSeconds_; 33 | int32_t dataAddress_; 34 | int32_t dataSize_; 35 | int32_t unknown1_; 36 | int32_t unknown2_; 37 | int32_t unknown3_; 38 | int32_t unknown4_; 39 | 40 | std::string imageData_; 41 | 42 | std::string packedLayerImage_; 43 | 44 | std::vector islandRows_; 45 | int32_t isLandsCount_; 46 | uint64_t pixels_; 47 | 48 | std::vector antiAliasLayers_; 49 | 50 | bool extendsMargin_; 51 | // PhotonFileHeader photonFileHeader_; 52 | int32_t width_; 53 | int32_t height_; 54 | bool isCalculated_; 55 | 56 | // PhotonFileLayer(PhotonInputStream & ds, PhotonFileHeader & photonFileHeader) : photonFileHeader_(photonFileHeader) { 57 | public: 58 | PhotonFileLayer() = default; 59 | // PhotonFileLayer(const PhotonFileLayer &) = default; 60 | PhotonFileLayer(PhotonInputStream & ds, int32_t width, int32_t height) { 61 | width_ = width; 62 | height_ = height; 63 | layerPositionZ_ = ds.readFloat(); 64 | layerExposure_ = ds.readFloat(); 65 | layerOffTimeSeconds_ = ds.readFloat(); 66 | 67 | dataAddress_ = ds.readInt(); 68 | dataSize_ = ds.readInt(); 69 | 70 | unknown1_ = ds.readInt(); 71 | unknown2_ = ds.readInt(); 72 | unknown3_ = ds.readInt(); 73 | unknown4_ = ds.readInt(); 74 | } 75 | 76 | PhotonFileLayer(float layerPositionZ, int32_t width, int32_t height) { 77 | width_ = width; 78 | height_ = height; 79 | layerPositionZ_ = layerPositionZ; 80 | layerExposure_ = 60.f; 81 | layerOffTimeSeconds_ = 3.f; 82 | 83 | dataAddress_ = 0; 84 | dataSize_ = 0; 85 | 86 | unknown1_ = 0; 87 | unknown2_ = 0; 88 | unknown3_ = 0; 89 | unknown4_ = 0; 90 | } 91 | 92 | 93 | PhotonFileLayer(PhotonFileLayer & photonFileLayer, int32_t width, int32_t height) { 94 | width_ = width; 95 | height_ = height; 96 | layerPositionZ_ = photonFileLayer.layerPositionZ_; 97 | layerExposure_ = photonFileLayer.layerExposure_; 98 | layerOffTimeSeconds_ = photonFileLayer.layerOffTimeSeconds_; 99 | dataAddress_ = photonFileLayer.dataAddress_; 100 | dataAddress_ = photonFileLayer.dataSize_; 101 | 102 | 103 | 104 | // Dont copy data, we are building new AA layers anyway 105 | //imageData = copy(); 106 | //packedLayerImage = copy(); 107 | } 108 | 109 | int savePos(int dataPosition) { 110 | dataAddress_ = dataPosition; 111 | return dataPosition + dataSize_; 112 | } 113 | 114 | void save(PhotonOutputStream & os) { 115 | os.writeFloat(layerPositionZ_); 116 | os.writeFloat(layerExposure_); 117 | os.writeFloat(layerOffTimeSeconds_); 118 | 119 | os.writeInt(dataAddress_); 120 | os.writeInt(dataSize_); 121 | 122 | os.writeInt(unknown1_); 123 | os.writeInt(unknown2_); 124 | os.writeInt(unknown3_); 125 | os.writeInt(unknown4_); 126 | } 127 | 128 | void saveData(PhotonOutputStream & os) { 129 | os.write(imageData_, 0, dataSize_); 130 | } 131 | 132 | static int getByteSize() { 133 | return 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4; 134 | } 135 | 136 | std::vector unpackImage(int resolutionX_) { 137 | pixels_ = 0; 138 | resolutionX_ = resolutionX_ - 1; 139 | std::vector unpackedImage; 140 | photoncpp::BitSet currentRow; 141 | int x = 0; 142 | for (char rle : imageData_) { 143 | int length = rle & 0x7F; 144 | bool color = (rle & 0x80) == 0x80; 145 | if (color) { 146 | pixels_ += length; 147 | } 148 | int endPosition = x + (length - 1); 149 | int lineEnd = std::min(endPosition, resolutionX_); 150 | if (color) { 151 | currentRow.resize(1 + lineEnd); 152 | std::fill(currentRow.begin() + x, currentRow.begin() + 1 + lineEnd, true); 153 | } 154 | if (endPosition > resolutionX_) { 155 | unpackedImage.push_back(currentRow); 156 | currentRow.clear(); // GLS 157 | lineEnd = endPosition - (resolutionX_ + 1); 158 | if (color) { 159 | currentRow.resize(1 + lineEnd); 160 | std::fill(currentRow.begin(), currentRow.begin() + 1 + lineEnd, true); 161 | } 162 | } 163 | x = lineEnd + 1; 164 | if (x > resolutionX_) { 165 | unpackedImage.push_back(currentRow); 166 | currentRow.clear();// GLS = new BitSet(); 167 | x = 0; 168 | } 169 | } 170 | if(0 != x) 171 | unpackedImage.push_back(currentRow); 172 | return unpackedImage; 173 | } 174 | 175 | void aaPixels(std::vector & unpackedImage, PhotonLayer & photonLayer) { 176 | photonLayer.clear(); 177 | 178 | for (size_t y = 0; y < unpackedImage.size(); y++) { 179 | photoncpp::BitSet & currentRow = unpackedImage.at(y); 180 | if (!currentRow.empty()) { 181 | for (size_t x = 0; x < currentRow.size(); x++) { 182 | if (currentRow.at(x)) { 183 | photonLayer.unSupported(x, y); 184 | } 185 | } 186 | } 187 | } 188 | } 189 | 190 | void unknownPixels(std::vector & unpackedImage, PhotonLayer & photonLayer) { 191 | photonLayer.clear(); 192 | 193 | for (size_t y = 0; y < unpackedImage.size(); y++) { 194 | photoncpp::BitSet & currentRow = unpackedImage.at(y); 195 | if (!currentRow.empty()) { 196 | for (size_t x = 0; x < currentRow.size(); x++) { 197 | if (currentRow.at(x)) { 198 | photonLayer.supported(x, y); 199 | } 200 | } 201 | } 202 | } 203 | } 204 | 205 | void calculate(std::vector & unpackedImage, std::vector & previousUnpackedImage, PhotonLayer & photonLayer) { 206 | //islandRows_; 207 | isLandsCount_ = 0; 208 | 209 | photonLayer.clear(); 210 | 211 | for (size_t y = 0; y < unpackedImage.size(); y++) { 212 | photoncpp::BitSet & currentRow = unpackedImage.at(y); 213 | photoncpp::BitSet prevRow; 214 | if(!previousUnpackedImage.empty()) 215 | prevRow = previousUnpackedImage.at(y); 216 | if (!currentRow.empty()) { 217 | for (size_t x = 0; x < currentRow.size(); x++) { 218 | if (currentRow.at(x)) { 219 | if (prevRow.empty() || prevRow.at(x)) { 220 | photonLayer.supported(x, y); 221 | } else { 222 | photonLayer.island(x, y); 223 | } 224 | } 225 | } 226 | } 227 | } 228 | 229 | photonLayer.reduce(); 230 | 231 | isLandsCount_ = photonLayer.setIslands(islandRows_); 232 | } 233 | 234 | 235 | static std::vector readLayers(const PhotonFileHeader & photonFileHeader_, const std::string & fileContent, int margin/*, IPhotonProgress & iPhotonProgress*/) { 236 | PhotonLayer photonLayer(photonFileHeader_.getResolutionX(), photonFileHeader_.getResolutionY()); 237 | 238 | std::vector layers; 239 | 240 | int antiAliasLevel = 1; 241 | if (photonFileHeader_.getVersion() > 1) { 242 | antiAliasLevel = photonFileHeader_.getAntiAliasingLevel(); 243 | } 244 | 245 | int layerCount = photonFileHeader_.getNumberOfLayers(); 246 | 247 | std::string data(fileContent.begin() + photonFileHeader_.getLayersDefinitionOffsetAddress(), fileContent.end()); 248 | std::stringstream ss(data); 249 | PhotonInputStream ds(ss); 250 | 251 | { 252 | std::map layerMap; 253 | for (int i = 0; i < layerCount; i++) { 254 | 255 | //iPhotonProgress.showInfo("Reading photon file layer " + (i + 1) + "/" + photonFileHeader_.getNumberOfLayers()); 256 | 257 | PhotonFileLayer layer(ds, photonFileHeader_.getResolutionX(), photonFileHeader_.getResolutionY()); 258 | layer.imageData_.assign(fileContent.begin() + layer.dataAddress_, fileContent.begin() + layer.dataAddress_ + layer.dataSize_); 259 | layers.push_back(layer); 260 | layerMap[i] = layer; 261 | } 262 | 263 | if (antiAliasLevel > 1) { 264 | for (int a = 0; a < (antiAliasLevel - 1); a++) { 265 | for (int i = 0; i < layerCount; i++) { 266 | //iPhotonProgress.showInfo("Reading photon file AA " + (2 + a) + "/" + antiAliasLevel + " layer " + (i + 1) + "/" + photonFileHeader_.getNumberOfLayers()); 267 | 268 | PhotonFileLayer layer(ds, photonFileHeader_.getResolutionX(), photonFileHeader_.getResolutionY()); 269 | layer.imageData_.assign(fileContent.begin() + layer.dataAddress_, fileContent.begin() + layer.dataAddress_ + layer.dataSize_); 270 | 271 | layerMap[i].addAntiAliasLayer(layer); 272 | } 273 | } 274 | } 275 | } 276 | 277 | photonLayer.unLink(); 278 | //System.gc(); 279 | 280 | return layers; 281 | } 282 | 283 | 284 | /* static std::vector cloneLayers(const PhotonFileHeader & photonFileHeader_, const std::string & dataLayer) { 285 | PhotonLayer photonLayer(photonFileHeader_.getResolutionX(), photonFileHeader_.getResolutionY()); 286 | 287 | std::vector layers; 288 | 289 | int antiAliasLevel = 1; 290 | if (photonFileHeader_.getVersion() > 1) { 291 | antiAliasLevel = photonFileHeader_.getAntiAliasingLevel(); 292 | } 293 | 294 | int layerCount = photonFileHeader_.getNumberOfLayers(); 295 | 296 | { 297 | std::map layerMap; 298 | for (int i = 0; i < layerCount; i++) { 299 | 300 | //iPhotonProgress.showInfo("Reading photon file layer " + (i + 1) + "/" + photonFileHeader_.getNumberOfLayers()); 301 | 302 | PhotonFileLayer layer(0.05f * i, photonFileHeader_.getResolutionX(), photonFileHeader_.getResolutionY()); 303 | layer.imageData_ = dataLayer; 304 | layer.dataSize_ = dataLayer.length(); 305 | layers.push_back(layer); 306 | layerMap[i] = layer; 307 | } 308 | 309 | if (antiAliasLevel > 1) { 310 | for (int a = 0; a < (antiAliasLevel - 1); a++) { 311 | for (int i = 0; i < layerCount; i++) { 312 | //iPhotonProgress.showInfo("Reading photon file AA " + (2 + a) + "/" + antiAliasLevel + " layer " + (i + 1) + "/" + photonFileHeader_.getNumberOfLayers()); 313 | 314 | PhotonFileLayer layer(0.05f * i, photonFileHeader_.getResolutionX(), photonFileHeader_.getResolutionY()); 315 | layer.imageData_ = dataLayer; 316 | layer.dataSize_ = dataLayer.length(); 317 | 318 | layerMap[i].addAntiAliasLayer(layer); 319 | } 320 | } 321 | } 322 | } 323 | 324 | photonLayer.unLink(); 325 | //System.gc(); 326 | 327 | return layers; 328 | } 329 | */ 330 | 331 | 332 | void addAntiAliasLayer(const PhotonFileLayer & layer) { 333 | antiAliasLayers_.push_back(layer); 334 | } 335 | 336 | static void calculateAALayers(const PhotonFileHeader & photonFileHeader, std::vector & layers, PhotonAaMatrix photonAaMatrix/*, IPhotonProgress & iPhotonProgress*/) { 337 | PhotonLayer photonLayer(photonFileHeader.getResolutionX(), photonFileHeader.getResolutionY()); 338 | photoncpp::MatrixInt source; 339 | source.resize(photonFileHeader.getResolutionY()); 340 | for (auto & line : source) 341 | line.resize(photonFileHeader.getResolutionX()); 342 | 343 | int i = 0; 344 | for (PhotonFileLayer & layer : layers) { 345 | std::vector unpackedImage = layer.unpackImage(photonFileHeader.getResolutionX()); 346 | 347 | //iPhotonProgress.showInfo("Calculating AA for photon file layer " + i + "/" + photonFileHeader.getNumberOfLayers()); 348 | 349 | 350 | for (uint32_t y = 0; y < photonFileHeader.getResolutionY(); y++) { 351 | for (uint32_t x = 0; x < photonFileHeader.getResolutionX(); x++) { 352 | source[y][x] = 0; 353 | } 354 | } 355 | 356 | for (size_t y = 0; y < unpackedImage.size(); y++) { 357 | photoncpp::BitSet currentRow = unpackedImage.at(y); 358 | if (!currentRow.empty()) { 359 | for (size_t x = 0; x < currentRow.size(); x++) { 360 | if (currentRow.at(x)) { 361 | source[y][x] = 255; 362 | } 363 | } 364 | } 365 | } 366 | 367 | // Calc 368 | photoncpp::MatrixInt target (photonAaMatrix.calc(source)); 369 | 370 | int aaTresholdDiff = 255 / photonFileHeader.getAntiAliasingLevel(); 371 | int aaTreshold = 0; 372 | for (PhotonFileLayer aaFileLayer : layer.antiAliasLayers_) { 373 | photonLayer.clear(); 374 | aaTreshold += aaTresholdDiff; 375 | 376 | for (uint32_t y = 0; y < photonFileHeader.getResolutionY(); y++) { 377 | for (uint32_t x = 0; x < photonFileHeader.getResolutionX(); x++) { 378 | if (target[y][x] >= aaTreshold) { 379 | photonLayer.supported(x, y); 380 | } 381 | } 382 | } 383 | 384 | aaFileLayer.saveLayer(photonLayer); 385 | } 386 | 387 | i++; 388 | } 389 | photonLayer.unLink(); 390 | //System.gc(); 391 | 392 | } 393 | 394 | static void calculateLayers(const PhotonFileHeader & photonFileHeader, std::vector & layers, int margin/*, IPhotonProgress iPhotonProgress*/) { 395 | PhotonLayer photonLayer(photonFileHeader.getResolutionX(), photonFileHeader.getResolutionY()); 396 | std::vector previousUnpackedImage; 397 | int i = 0; 398 | for (PhotonFileLayer layer : layers) { 399 | std::vector unpackedImage = layer.unpackImage(photonFileHeader.getResolutionX()); 400 | 401 | //iPhotonProgress.showInfo("Calculating photon file layer " + i + "/" + photonFileHeader.getNumberOfLayers()); 402 | 403 | if (margin > 0) { 404 | layer.extendsMargin_ = layer.checkMagin(unpackedImage, margin); 405 | } 406 | 407 | layer.unknownPixels(unpackedImage, photonLayer); 408 | 409 | layer.calculate(unpackedImage, previousUnpackedImage, photonLayer); 410 | 411 | previousUnpackedImage.clear(); 412 | 413 | previousUnpackedImage = unpackedImage; 414 | 415 | layer.packedLayerImage_ = photonLayer.packLayerImage(); 416 | layer.isCalculated_ = true; 417 | 418 | if (photonFileHeader.getVersion() > 1) { 419 | for (PhotonFileLayer aaFileLayer : layer.antiAliasLayers_) { 420 | std::vector aaUnpackedImage = aaFileLayer.unpackImage(photonFileHeader.getResolutionX()); 421 | PhotonLayer aaPhotonLayer(photonFileHeader.getResolutionX(), photonFileHeader.getResolutionY()); 422 | aaFileLayer.unknownPixels(aaUnpackedImage, aaPhotonLayer); 423 | aaFileLayer.packedLayerImage_ = aaPhotonLayer.packLayerImage(); 424 | aaFileLayer.isCalculated_ = false; 425 | } 426 | } 427 | 428 | i++; 429 | } 430 | photonLayer.unLink(); 431 | //System.gc(); 432 | } 433 | 434 | static void calculateLayers(const PhotonFileHeader & photonFileHeader, std::vector & layers, int margin, int layerNo) { 435 | PhotonLayer photonLayer(photonFileHeader.getResolutionX(), photonFileHeader.getResolutionY()); 436 | std::vector previousUnpackedImage; 437 | 438 | if (layerNo > 0) { 439 | previousUnpackedImage = layers.at(layerNo - 1).unpackImage(photonFileHeader.getResolutionX()); 440 | } 441 | 442 | for (int i = 0; i < 2; i++) { 443 | PhotonFileLayer layer = layers.at(layerNo + i); 444 | std::vector unpackedImage = layer.unpackImage(photonFileHeader.getResolutionX()); 445 | 446 | if (margin > 0) { 447 | layer.extendsMargin_ = layer.checkMagin(unpackedImage, margin); 448 | } 449 | 450 | layer.unknownPixels(unpackedImage, photonLayer); 451 | 452 | layer.calculate(unpackedImage, previousUnpackedImage, photonLayer); 453 | 454 | previousUnpackedImage.clear(); 455 | 456 | previousUnpackedImage = unpackedImage; 457 | 458 | layer.packedLayerImage_ = photonLayer.packLayerImage(); 459 | layer.isCalculated_ = true; 460 | 461 | i++; 462 | } 463 | photonLayer.unLink(); 464 | //System.gc(); 465 | } 466 | 467 | std::vector getRows() { 468 | return PhotonLayer::getRows(packedLayerImage_, width_, isCalculated_); 469 | } 470 | 471 | std::vector getIslandRows() { 472 | return islandRows_; 473 | } 474 | 475 | int getIsLandsCount() { 476 | return isLandsCount_; 477 | } 478 | 479 | uint64_t getPixels() { 480 | return pixels_; 481 | } 482 | 483 | float getLayerPositionZ() { 484 | return layerPositionZ_; 485 | } 486 | 487 | void setLayerPositionZ(float layerPositionZ_) { 488 | layerPositionZ_ = layerPositionZ_; 489 | } 490 | 491 | float getLayerExposure() { 492 | return layerExposure_; 493 | } 494 | 495 | float getLayerOffTime() { 496 | return layerOffTimeSeconds_; 497 | } 498 | 499 | void setLayerExposure(float layerExposure_) { 500 | layerExposure_ = layerExposure_; 501 | } 502 | 503 | void setLayerOffTimeSeconds(float layerOffTimeSeconds_) { 504 | layerOffTimeSeconds_ = layerOffTimeSeconds_; 505 | } 506 | 507 | void unLink() { 508 | imageData_.clear(); 509 | packedLayerImage_.clear(); 510 | islandRows_.clear(); 511 | } 512 | 513 | bool doExtendMargin() { 514 | return extendsMargin_; 515 | } 516 | 517 | private: 518 | bool checkMagin(std::vector & unpackedImage, uint32_t margin) { 519 | if (unpackedImage.size() > margin) { 520 | // check top margin rows 521 | for (uint32_t i = 0; i < margin; i++) { 522 | if (!unpackedImage.at(i).empty()) { 523 | return true; 524 | } 525 | } 526 | // check bottom margin rows 527 | for (size_t i = unpackedImage.size() - margin; i < unpackedImage.size(); i++) { 528 | if (!unpackedImage.at(i).empty()) { 529 | return true; 530 | } 531 | } 532 | 533 | for (size_t i = margin; i < unpackedImage.size() - margin; i++) { 534 | photoncpp::BitSet & row = unpackedImage.at(i); 535 | for (size_t j = 0; j < margin; j++) 536 | { 537 | if (row[j]) { 538 | return true; 539 | } 540 | } 541 | for (int32_t j = width_ - margin; j < width_; j++) 542 | { 543 | if (row[j]) { 544 | return true; 545 | } 546 | } 547 | } 548 | } 549 | return false; 550 | } 551 | 552 | public: 553 | PhotonLayer getLayer() { 554 | PhotonLayer photonLayer(width_, height_); 555 | photonLayer.unpackLayerImage(packedLayerImage_); 556 | return photonLayer; 557 | } 558 | 559 | void getUpdateLayer(PhotonLayer & photonLayer) { 560 | photonLayer.unpackLayerImage(packedLayerImage_); 561 | } 562 | 563 | void updateLayerIslands(PhotonLayer & photonLayer) { 564 | islandRows_.clear(); 565 | isLandsCount_ = photonLayer.setIslands(islandRows_); 566 | } 567 | 568 | void saveLayer(PhotonLayer & photonLayer) { 569 | packedLayerImage_ = photonLayer.packLayerImage(); 570 | imageData_ = photonLayer.packImageData(); 571 | dataSize_ = imageData_.size(); 572 | islandRows_.clear(); 573 | isLandsCount_ = photonLayer.setIslands(islandRows_); 574 | } 575 | 576 | std::vector getUnknownRows() { 577 | return unpackImage(width_); 578 | } 579 | 580 | PhotonFileLayer & getAntiAlias(uint32_t a) { 581 | return antiAliasLayers_.at(a); 582 | } 583 | 584 | std::vector & getAntiAlias() { 585 | return antiAliasLayers_; 586 | } 587 | }; 588 | -------------------------------------------------------------------------------- /PhotonFilePreview.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * by bn on 01/07/2018. 28 | */ 29 | class PhotonFilePreview { 30 | private: 31 | int32_t resolutionX_; 32 | int32_t resolutionY_; 33 | int32_t imageAddress_; 34 | int32_t dataSize_; 35 | 36 | std::vector rawImageData_; 37 | 38 | std::vector imageData_; 39 | 40 | int32_t p1_; 41 | int32_t p2_; 42 | int32_t p3_; 43 | int32_t p4_; 44 | 45 | public: 46 | PhotonFilePreview(int previewAddress, const std::string & fileContent) { 47 | std::string data(fileContent.begin() + previewAddress, fileContent.begin() + previewAddress + 32); 48 | std::stringstream ss(data); 49 | PhotonInputStream ds(ss); 50 | 51 | resolutionX_ = ds.readInt(); 52 | resolutionY_ = ds.readInt(); 53 | imageAddress_ = ds.readInt(); 54 | dataSize_ = ds.readInt(); 55 | p1_ = ds.readInt(); 56 | p2_ = ds.readInt(); 57 | p3_ = ds.readInt(); 58 | p4_ = ds.readInt(); 59 | 60 | rawImageData_.assign(fileContent.begin() + imageAddress_, fileContent.begin() + imageAddress_ + dataSize_); 61 | 62 | decodeImageData(); 63 | } 64 | 65 | void save(PhotonOutputStream os, int startAddress) { 66 | os.writeInt(resolutionX_); 67 | os.writeInt(resolutionY_); 68 | os.writeInt(startAddress + 4+4+4+4 + 4+4+4+4); 69 | os.writeInt(dataSize_); 70 | os.writeInt(p1_); 71 | os.writeInt(p2_); 72 | os.writeInt(p3_); 73 | os.writeInt(p4_); 74 | os.write(rawImageData_, 0, dataSize_); 75 | } 76 | 77 | int getByteSize() { 78 | return 4+4+4+4 + 4+4+4+4 + dataSize_; 79 | } 80 | 81 | private: 82 | void decodeImageData() { 83 | imageData_.resize(resolutionX_ * resolutionY_); 84 | int d = 0; 85 | for (int i = 0; i < dataSize_; i++) { 86 | int32_t dot = (rawImageData_[i] & 0xFF) | ((rawImageData_[i+1] & 0xFF) << 8); 87 | i++; 88 | 89 | int32_t color = ((dot & 0xF800) << 8) | ((dot & 0x07C0) << 5) | ((dot & 0x001F) << 3); 90 | 91 | // int red = ((dot >> 11) & 0x1F) << 3; 92 | // int green = ((dot >> 6) & 0x1F) << 3; 93 | // int blue = (dot & 0x1F) << 3; 94 | // color = red<<16 | green<<8 | blue; 95 | 96 | int repeat = 1; 97 | if ((dot & 0x0020) == 0x0020) { 98 | repeat += (rawImageData_[i+1] & 0xFF) | ((rawImageData_[i+2] & 0x0F) << 8); 99 | i += 2; 100 | } 101 | 102 | while (repeat > 0) { 103 | imageData_[d++] = color; 104 | repeat--; 105 | } 106 | } 107 | 108 | } 109 | 110 | public: 111 | int32_t getResolutionX() { 112 | return resolutionX_; 113 | } 114 | 115 | int32_t getResolutionY() { 116 | return resolutionY_; 117 | } 118 | 119 | std::vector getImageData() { 120 | return imageData_; 121 | } 122 | 123 | void unLink() { 124 | rawImageData_.clear(); 125 | imageData_.clear(); 126 | } 127 | 128 | }; 129 | -------------------------------------------------------------------------------- /PhotonFilePrintParameters.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | class PhotonFilePrintParameters { 27 | public: 28 | float bottomLiftDistance_ = 5.0f; 29 | float bottomLiftSpeed_ = 300.0f; 30 | 31 | float liftingDistance_ = 5.0f; 32 | float liftingSpeed_ = 300.0f; 33 | float retractSpeed_ = 300.0f; 34 | 35 | float volumeMl_ = 0; 36 | float weightG_ = 0; 37 | float costDollars_ = 0; 38 | 39 | float bottomLightOffDelay_ = 0.0f; 40 | float lightOffDelay_ = 0.0f; 41 | int32_t bottomLayerCount_; 42 | 43 | int32_t p1_; 44 | int32_t p2_; 45 | int32_t p3_; 46 | int32_t p4_; 47 | 48 | 49 | public: 50 | PhotonFilePrintParameters() = default; 51 | PhotonFilePrintParameters(int bottomLayerCount) { 52 | bottomLayerCount_ = bottomLayerCount; 53 | } 54 | 55 | PhotonFilePrintParameters(int parametersPos, const std::string & fileContent) { 56 | std::string data(fileContent.begin() + parametersPos, fileContent.begin() + parametersPos + getByteSize()); 57 | std::stringstream ss(data); 58 | PhotonInputStream ds(ss); 59 | 60 | bottomLiftDistance_ = ds.readFloat(); 61 | bottomLiftSpeed_ = ds.readFloat(); 62 | 63 | liftingDistance_ = ds.readFloat(); 64 | liftingSpeed_ = ds.readFloat(); 65 | retractSpeed_ = ds.readFloat(); 66 | 67 | volumeMl_ = ds.readFloat(); 68 | weightG_ = ds.readFloat(); 69 | costDollars_ = ds.readFloat(); 70 | 71 | bottomLightOffDelay_ = ds.readFloat(); 72 | lightOffDelay_ = ds.readFloat(); 73 | bottomLayerCount_ = ds.readInt(); 74 | 75 | p1_ = ds.readInt(); 76 | p2_ = ds.readInt(); 77 | p3_ = ds.readInt(); 78 | p4_ = ds.readInt(); 79 | } 80 | 81 | void save(PhotonOutputStream & os) { 82 | os.writeFloat(bottomLiftDistance_); 83 | os.writeFloat(bottomLiftSpeed_); 84 | 85 | os.writeFloat(liftingDistance_); 86 | os.writeFloat(liftingSpeed_); 87 | os.writeFloat(retractSpeed_); 88 | 89 | os.writeFloat(volumeMl_); 90 | os.writeFloat(weightG_); 91 | os.writeFloat(costDollars_); 92 | 93 | os.writeFloat(bottomLightOffDelay_); 94 | os.writeFloat(lightOffDelay_); 95 | os.writeInt(bottomLayerCount_); 96 | 97 | os.writeInt(p1_); 98 | os.writeInt(p2_); 99 | os.writeInt(p3_); 100 | os.writeInt(p4_); 101 | } 102 | 103 | int getByteSize() { 104 | return 4+4 +4+4+4 +4+4+4 +4+4+4 +4+4+4+4; 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /PhotonInputStream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * by bn on 01/07/2018. 28 | */ 29 | 30 | class PhotonInputStream { 31 | private: 32 | //DataInputStream dataInputStream; 33 | std::istream & inputStream_; 34 | // std::vector byteBuffer; 35 | 36 | public: 37 | PhotonInputStream(std::istream & inputStream) : inputStream_ (inputStream) { 38 | } 39 | 40 | int read() { // ?? 41 | assert(0); 42 | return (int)inputStream_.tellg(); 43 | } 44 | 45 | int read(std::vector bytes, int offset, int readLen) { 46 | assert(0); 47 | return 0;// inputStream_.read(bytes, offset, readLen); 48 | } 49 | 50 | void readFully(std::vector & bytes) { 51 | if(!bytes.empty()) 52 | inputStream_.read(&bytes[0], bytes.size()); 53 | } 54 | 55 | void readFully(std::vector bytes, int offset, int readLen) { 56 | assert(0); 57 | //dataInputStream.readFully(bytes, offset, readLen); 58 | } 59 | 60 | int skipBytes(int n) { 61 | assert(0); 62 | inputStream_.ignore(n); 63 | return n; 64 | } 65 | 66 | bool readBoolean() { 67 | char res; 68 | inputStream_ >> res; 69 | return !!res; 70 | } 71 | 72 | char readByte() { 73 | char res; 74 | inputStream_ >> res; 75 | return res; 76 | } 77 | 78 | int readUnsignedByte() { 79 | char res; 80 | inputStream_.read(&res, 1); 81 | return (uint8_t)res; 82 | } 83 | 84 | short readShort() { 85 | std::vector buf({0, 0}); 86 | readFully(buf); 87 | return (short)((buf[1] & 0xff) << 8 | (buf[0] & 0xff)); 88 | } 89 | 90 | int readUnsignedShort() { 91 | std::vector buf({ 0, 0 }); 92 | readFully(buf); 93 | return ((buf[1] & 0xff) << 8 | (buf[0] & 0xff)); 94 | } 95 | 96 | /* char readChar() { 97 | dataInputStream.readFully(byteBuffer, 0, 2); 98 | return (char)((byteBuffer[1] & 0xff) << 8 | (byteBuffer[0] & 0xff)); 99 | }*/ 100 | 101 | uint32_t readInt() { 102 | std::vector buf; 103 | buf.resize(4); 104 | readFully(buf); 105 | return (buf[3]) << 24 | (buf[2] & 0xff) << 16 | 106 | (buf[1] & 0xff) << 8 | (buf[0] & 0xff); 107 | } 108 | 109 | uint64_t readInt64() { 110 | std::vector buf; 111 | buf.resize(8); 112 | readFully(buf); 113 | return (uint64_t)(buf[7]) << 56 | (uint64_t)(buf[6]&0xff) << 48 | 114 | (uint64_t)(buf[5] & 0xff) << 40 | (uint64_t)(buf[4] & 0xff) << 32 | 115 | (uint64_t)(buf[3] & 0xff) << 24 | (uint64_t)(buf[2] & 0xff) << 16 | 116 | (uint64_t)(buf[1] & 0xff) << 8 | (uint64_t)(buf[0] & 0xff); 117 | } 118 | 119 | float readFloat() { 120 | float res; 121 | int32_t value = readInt(); 122 | res = *reinterpret_cast(&value); 123 | return res; 124 | } 125 | 126 | double readDouble() { 127 | double res; 128 | int64_t value = readInt64(); 129 | res = *reinterpret_cast(&value); 130 | return res; 131 | } 132 | 133 | /* @Deprecated 134 | @Override 135 | public final String readLine() throws IOException { 136 | return dataInputStream.readLine(); 137 | }*/ 138 | 139 | std::string readUTF() { 140 | std::string res; 141 | std::getline(inputStream_, res, '\0'); 142 | return res; 143 | } 144 | 145 | int available() { 146 | assert(0); 147 | return 1; 148 | // return inputStream_.available(); 149 | } 150 | 151 | void close() { 152 | // inputStream_.close(); 153 | } 154 | 155 | }; 156 | -------------------------------------------------------------------------------- /PhotonLayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * by bn on 02/07/2018. 28 | */ 29 | class PhotonLayer { 30 | public: 31 | 32 | 33 | private: 34 | int32_t width_; 35 | int32_t height_; 36 | int32_t islandCount_ = 0; 37 | 38 | std::vector> iArray; 39 | std::vector pixels; 40 | std::vector rowIslands; 41 | std::vector rowUnsupported; 42 | std::vector rowSupported; 43 | 44 | public: 45 | PhotonLayer(int width, int height) { 46 | width_ = width; 47 | height_ = height; 48 | 49 | for (int h = 0; h < height; h++) 50 | iArray.push_back({}); 51 | 52 | for (int h = 0; h < height; h++) 53 | iArray[h].resize(width); 54 | 55 | pixels.resize(height); 56 | rowIslands.resize(height); 57 | rowUnsupported.resize(height); 58 | rowSupported.resize(height); 59 | } 60 | 61 | void clear() { 62 | for (int y = 0; y < height_; y++) { 63 | for (int x = 0; x < width_; x++) { 64 | iArray[y][x] = PhotonDot::OFF; 65 | } 66 | } 67 | std::fill(pixels.begin(), pixels.end(), 0); 68 | std::fill(rowIslands.begin(), rowIslands.end(), 0); 69 | std::fill(rowUnsupported.begin(), rowUnsupported.end(), 0); 70 | std::fill(rowSupported.begin(), rowSupported.end(), 0); 71 | } 72 | 73 | void supported(int x, int y) { 74 | iArray[y][x] = PhotonDot::SUPPORTED; 75 | rowSupported[y]++; 76 | pixels[y]++; 77 | } 78 | 79 | void unSupported(int x, int y) { 80 | iArray[y][x] = PhotonDot::CONNECTED; 81 | rowUnsupported[y]++; 82 | pixels[y]++; 83 | } 84 | 85 | void island(int x, int y) { 86 | iArray[y][x] = PhotonDot::ISLAND; 87 | rowIslands[y]++; 88 | islandCount_++; 89 | pixels[y]++; 90 | } 91 | 92 | void remove(int x, int y, char type) { 93 | iArray[y][x] = PhotonDot::OFF; 94 | switch (type) { 95 | case PhotonDot::SUPPORTED: 96 | rowUnsupported[y]--; 97 | break; 98 | case PhotonDot::CONNECTED: 99 | rowUnsupported[y]--; 100 | break; 101 | case PhotonDot::ISLAND: 102 | rowIslands[y]--; 103 | islandCount_--; 104 | break; 105 | } 106 | pixels[y]--; 107 | } 108 | 109 | 110 | void reduce() { 111 | // Double reduce to handle single line connections. 112 | for (int i = 0; i < 2; i++) { 113 | if (islandCount_ > 0) { 114 | for (int y = 0; y < height_; y++) { 115 | if (rowIslands[y] > 0) { 116 | for (int x = 0; x < width_; x++) { 117 | if (iArray[y][x] == PhotonDot::ISLAND) { 118 | if (connected(x, y)) { 119 | makeConnected(x, y); 120 | checkUp(x, y); 121 | if (rowIslands[y] == 0) { 122 | break; 123 | } 124 | } 125 | } 126 | } 127 | } 128 | } 129 | } 130 | } 131 | } 132 | 133 | private: 134 | void checkUp(int x, int y) { 135 | if (y > 0 && rowIslands[y - 1] > 0 && iArray[y - 1][x] == PhotonDot::ISLAND) { 136 | makeConnected(x, y - 1); 137 | checkUp(x, y - 1); 138 | } 139 | if (x > 0 && rowIslands[y] > 0 && iArray[y][x - 1] == PhotonDot::ISLAND) { 140 | makeConnected(x - 1, y); 141 | checkBackUp(x - 1, y); 142 | } 143 | if (x < (width_-1) && rowIslands[y] > 0 && iArray[y][x + 1] == PhotonDot::ISLAND) { 144 | makeConnected(x + 1, y); 145 | checkFrontUp(x + 1, y); 146 | } 147 | } 148 | 149 | void checkBackUp(int x, int y) { 150 | if (y > 0 && rowIslands[y - 1] > 0 && iArray[y - 1][x] == PhotonDot::ISLAND) { 151 | makeConnected(x, y - 1); 152 | checkBackUp(x, y - 1); 153 | } 154 | if (x > 0 && rowIslands[y] > 0 && iArray[y][x - 1] == PhotonDot::ISLAND) { 155 | makeConnected(x - 1, y); 156 | checkBackUp(x - 1, y); 157 | } 158 | } 159 | 160 | void checkFrontUp(int x, int y) { 161 | if (y > 0 && rowIslands[y - 1] > 0 && iArray[y - 1][x] == PhotonDot::ISLAND) { 162 | makeConnected(x, y - 1); 163 | checkFrontUp(x, y - 1); 164 | } 165 | if (x < (width_-1) && rowIslands[y] > 0 && iArray[y][x + 1] == PhotonDot::ISLAND) { 166 | makeConnected(x + 1, y); 167 | checkFrontUp(x + 1, y); 168 | } 169 | } 170 | 171 | void makeConnected(int x, int y) { 172 | iArray[y][x] = PhotonDot::CONNECTED; 173 | rowSupported[y]++; 174 | rowIslands[y]--; 175 | islandCount_--; 176 | } 177 | 178 | bool connected(int x, int y) { 179 | return (x > 0 && (iArray[y][x - 1] & 0x01) == PhotonDot::SUPPORTED) 180 | || (x < (width_ - 1) && (iArray[y][x + 1] & 0x01) == PhotonDot::SUPPORTED) 181 | || (y > 0 && (iArray[y - 1][x] & 0x01) == PhotonDot::SUPPORTED) 182 | || (y < (height_ - 1) && (iArray[y + 1][x] & 0x01) == PhotonDot::SUPPORTED); 183 | } 184 | 185 | public: 186 | int setIslands(std::vector & islandRows) { 187 | int islands = 0; 188 | for (int y = 0; y < height_; y++) { 189 | photoncpp::BitSet bitSet; 190 | if (rowIslands[y] > 0) { 191 | for (int x = 0; x < width_; x++) { 192 | if (iArray[y][x] == PhotonDot::ISLAND) { 193 | bitSet[x] = true; 194 | } 195 | } 196 | } 197 | islandRows.push_back(bitSet); 198 | islands += rowIslands[y]; 199 | } 200 | return islands; 201 | } 202 | 203 | void unLink() { 204 | iArray.clear(); 205 | pixels.clear(); 206 | rowIslands.clear(); 207 | rowUnsupported.clear(); 208 | rowSupported.clear(); 209 | } 210 | 211 | std::string packLayerImage() { 212 | std::stringstream baos; 213 | 214 | { 215 | for (int y = 0; y < height_; y++) { 216 | if (pixels[y] == 0) { 217 | add(baos, PhotonDot::OFF, width_); 218 | } else { 219 | char current = PhotonDot::OFF; 220 | int length = 0; 221 | for (int x = 0; x < width_; x++) { 222 | char next = iArray[y][x]; 223 | if (next != current) { 224 | if (length > 0) { 225 | add(baos, current, length); 226 | } 227 | current = next; 228 | length = 1; 229 | } else { 230 | length++; 231 | } 232 | } 233 | if (length > 0) { 234 | add(baos, current, length); 235 | } 236 | } 237 | } 238 | 239 | return baos.str(); 240 | } 241 | } 242 | 243 | void unpackLayerImage(std::string packedLayerImage) { 244 | clear(); 245 | int x = 0; 246 | int y = 0; 247 | for (size_t i = 0; i < packedLayerImage.length(); i++) { 248 | char rle = packedLayerImage[i]; 249 | char colorCode = (char) ((rle & 0x60) >> 5); 250 | 251 | bool extended = (rle & 0x80) == 0x80; 252 | int length = rle & 0x1F; 253 | if (extended) { 254 | i++; 255 | length = (length << 8) | (packedLayerImage[i] & 0x00ff); 256 | } 257 | 258 | for(int xi = x; xi<(x+length); xi++) { 259 | switch (colorCode) { 260 | case PhotonDot::SUPPORTED: 261 | supported(xi, y); 262 | break; 263 | case PhotonDot::CONNECTED: 264 | unSupported(xi, y); 265 | break; 266 | case PhotonDot::ISLAND: 267 | island(xi, y); 268 | break; 269 | } 270 | } 271 | x += length; 272 | if (x >= width_) { 273 | y++; 274 | x = 0; 275 | } 276 | } 277 | 278 | } 279 | 280 | private: 281 | void add(std::ostream & baos, char current, int length) { 282 | if (length < 32) { 283 | std::vector data(1, 0); 284 | data[0] = (char) ((current << 5) | (length & 0x1f)); 285 | baos.write(data.data(), data.size()); 286 | } else { 287 | std::vector data(2, 0); 288 | data[0] = (char) (0x80 | (current << 5) | (length >> 8 & 0x00FF)); 289 | data[1] = (char) (length & 0x00FF); 290 | baos.write(data.data(), data.size()); 291 | } 292 | } 293 | 294 | /** 295 | * Get a layer image for drawing. 296 | *

297 | * This will decode the RLE packed layer information and return a list of rows, with color and length information 298 | * 299 | * @param packedLayerImage The packed layer image information 300 | * @param width The width of the current layer, used to change rows 301 | * @return A list with the 302 | */ 303 | public: 304 | static std::vector getRows(std::string packedLayerImage, int width, bool isCalculated) { 305 | std::map colors; 306 | colors[PhotonDot::OFF] = 0x000000; 307 | if (isCalculated) { 308 | colors[PhotonDot::SUPPORTED] = 0x008800; 309 | } else { 310 | colors[PhotonDot::SUPPORTED] = 0x000088; 311 | } 312 | colors[PhotonDot::CONNECTED] = 0xFFFF00; 313 | colors[PhotonDot::ISLAND] = 0xFF0000; 314 | std::vector rows; 315 | int resolutionX_ = width - 1; 316 | PhotonRow currentRow; 317 | rows.push_back(currentRow); 318 | int x = 0; 319 | if (!packedLayerImage.empty()) { // when user tries to show a layer before its calculated 320 | for (size_t i = 0; i < packedLayerImage.length(); i++) { 321 | char rle = packedLayerImage[i]; 322 | char colorCode = (char) ((rle & 0x60) >> 5); 323 | photoncpp::Color color = colors[colorCode]; 324 | bool extended = (rle & 0x80) == 0x80; 325 | int length = rle & 0x1F; 326 | if (extended) { 327 | i++; 328 | length = (length << 8) | (packedLayerImage[i] & 0x00ff); 329 | } 330 | currentRow.lines_.push_back(PhotonLine(color, length)); 331 | x += length; 332 | 333 | if (x >= resolutionX_) { 334 | currentRow.lines_.clear(); // GLS: what is "current"? 335 | rows.push_back(currentRow); 336 | x = 0; 337 | } 338 | } 339 | } 340 | return rows; 341 | } 342 | 343 | int fixlayer() { 344 | PhotonMatix photonMatix; 345 | std::vector dots; 346 | if (islandCount_ > 0) { 347 | for (int y = 0; y < height_; y++) { 348 | if (rowIslands[y] > 0) { 349 | for (int x = 0; x < width_; x++) { 350 | if (iArray[y][x] == PhotonDot::ISLAND) { 351 | photonMatix.clear(); 352 | int blanks = photonMatix.set(x, y, iArray, width_, height_); 353 | if (blanks>0) { // one or more neighbour pixels are OFF 354 | photonMatix.calc(); 355 | photonMatix.level(); 356 | photonMatix.calc(); 357 | 358 | for(int ry=0; ry<3; ry++) { 359 | for (int rx = 0; rx < 3; rx++) { 360 | int iy = y-1+ry; 361 | int ix = x-1+rx; 362 | if (iArray[iy][ix] == PhotonDot::OFF) { 363 | if (photonMatix.calcMatrix_[1+ry][1+rx]>3) { 364 | dots.push_back(PhotonDot(ix, iy)); 365 | } 366 | } 367 | } 368 | } 369 | } 370 | } 371 | } 372 | } 373 | } 374 | } 375 | for(PhotonDot dot : dots) { 376 | island(dot.x_, dot.y_); 377 | } 378 | return dots.size(); 379 | } 380 | 381 | std::string packImageData() { 382 | std::stringstream baos; 383 | 384 | { 385 | for (int y = 0; y < height_; y++) { 386 | if (pixels[y] == 0) { 387 | addPhotonRLE(baos, true, width_); 388 | } else { 389 | char current = PhotonDot::OFF; 390 | int length = 0; 391 | for (int x = 0; x < width_; x++) { 392 | char next = iArray[y][x]; 393 | if (next != current) { 394 | if (length > 0) { 395 | addPhotonRLE(baos, current == PhotonDot::OFF, length); 396 | } 397 | current = next; 398 | length = 1; 399 | } else { 400 | length++; 401 | } 402 | } 403 | if (length > 0) { 404 | addPhotonRLE(baos, current == PhotonDot::OFF, length); 405 | } 406 | } 407 | } 408 | 409 | return baos.str(); 410 | } 411 | } 412 | 413 | private: 414 | void addPhotonRLE(std::ostream & baos, bool off, int length) { 415 | std::vector data({ 0 }); 416 | while (length>0) { 417 | int lineLength = std::min(length, 125); // max storage length of 0x7D (125) ?? Why not 127? 418 | data[0] = (char) ((off ? 0x00: 0x80) | (lineLength & 0x7f)); 419 | baos.write(data.data(), data.size()); 420 | length -= lineLength; 421 | } 422 | } 423 | 424 | public: 425 | char get(int x, int y) { 426 | return iArray[y][x]; 427 | } 428 | 429 | }; 430 | -------------------------------------------------------------------------------- /PhotonLine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * by bn on 10/07/2018. 27 | */ 28 | class PhotonLine { 29 | public: 30 | photoncpp::Color color_; 31 | int length_; 32 | 33 | PhotonLine(photoncpp::Color color, int length) { 34 | color_ = color; 35 | length_ = length; 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /PhotonMatrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * by bn on 14/07/2018. 28 | */ 29 | class PhotonMatix { 30 | 31 | public: 32 | std::array, 5> calcMatrix_; 33 | 34 | void clear() { 35 | for (int y = 0; y < 5; y++) { 36 | for (int x = 0; x < 5; x++) { 37 | calcMatrix_[y][x] = 0; 38 | } 39 | } 40 | } 41 | 42 | 43 | int set(int x, int y, const std::vector> & iArray, int width, int height) { 44 | int blanks = 0; 45 | int x0 = x - 2; 46 | int y0 = y - 2; 47 | for (int yi = 0; yi < 5; yi++) { 48 | for (int xi = 0; xi < 5; xi++) { 49 | int y2 = y0 + yi; 50 | int x2 = x0 + xi; 51 | if (y2 >= 0 && y2 < height && x2 >= 0 && x2 < width) { 52 | switch (iArray[y2][x2]) { 53 | case PhotonDot::SUPPORTED: 54 | case PhotonDot::CONNECTED: 55 | calcMatrix_[yi][xi] = 16; 56 | break; 57 | 58 | case PhotonDot::ISLAND: 59 | calcMatrix_[yi][xi] = 4; 60 | break; 61 | 62 | case PhotonDot::OFF: 63 | if (yi > 0 && yi < 4 && xi > 0 && xi < 4) { 64 | blanks++; 65 | } 66 | break; 67 | } 68 | } 69 | } 70 | } 71 | return blanks; 72 | } 73 | 74 | 75 | void calc() { 76 | std::array, 3> temp; 77 | for (int yi = 0; yi < 3; yi++) { 78 | for (int xi = 0; xi < 3; xi++) { 79 | if (calcMatrix_[yi+1][xi+1]== PhotonDot::OFF) { 80 | temp[yi][xi] = calc(xi+1, yi+1); 81 | } 82 | } 83 | } 84 | for (int yi = 0; yi < 3; yi++) { 85 | for (int xi = 0; xi < 3; xi++) { 86 | if (calcMatrix_[yi+1][xi+1]== PhotonDot::OFF) { 87 | calcMatrix_[yi+1][xi+1] = temp[yi][xi]; 88 | } 89 | } 90 | } 91 | } 92 | 93 | private: 94 | int calc(int x, int y) { 95 | return (calcMatrix_[y-1][x] / 4) + (calcMatrix_[y][x-1] / 4) + (calcMatrix_[y][x+1] / 4) + (calcMatrix_[y+1][x] / 4); 96 | } 97 | 98 | public: 99 | void level() { 100 | for (int yi = 0; yi < 5; yi++) { 101 | for (int xi = 0; xi < 5; xi++) { 102 | if (calcMatrix_[yi][xi]<4) calcMatrix_[yi][xi] = 0; 103 | } 104 | } 105 | } 106 | 107 | }; 108 | -------------------------------------------------------------------------------- /PhotonOutputStream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * by bn on 06/07/2018. 28 | */ 29 | class PhotonOutputStream { 30 | private: 31 | std::ostream & outputStream_; 32 | 33 | 34 | public: 35 | PhotonOutputStream(std::ostream & outputStream) : outputStream_ (outputStream) { 36 | } 37 | 38 | void write(std::vector b, int off, int len) { 39 | if (!b.empty()) 40 | outputStream_.write(b.data(), len); 41 | } 42 | 43 | void write(std::string b, int off, int len) { 44 | if (!b.empty()) 45 | outputStream_.write(b.data(), len); 46 | } 47 | 48 | void writeBoolean(bool v) { 49 | outputStream_.put(v); 50 | } 51 | 52 | void writeByte(int v) { 53 | outputStream_.put(v); 54 | } 55 | 56 | /* @Deprecated 57 | @Override 58 | public void writeBytes(String s) throws IOException { 59 | dataOutputStream.writeBytes(s); 60 | }*/ 61 | 62 | void writeChar(int v) { 63 | writeShort(v); 64 | } 65 | 66 | void writeChars(std::string s) { 67 | assert(0); 68 | /* for (int i = 0; i < s.length(); i++) { 69 | writeChar(s.charAt(i)); 70 | }*/ 71 | } 72 | 73 | void writeDouble(double v) { 74 | int64_t value = *reinterpret_cast(&v); 75 | writeInt64(value); 76 | } 77 | 78 | void writeFloat(float v) { 79 | int32_t value = *reinterpret_cast(&v); 80 | writeInt(value); 81 | } 82 | 83 | void write(int b) { 84 | writeInt(b); 85 | } 86 | 87 | void writeInt(int v) { 88 | outputStream_.put(0xFF & v); 89 | outputStream_.put(0xFF & (v >> 8)); 90 | outputStream_.put(0xFF & (v >> 16)); 91 | outputStream_.put(0xFF & (v >> 24)); 92 | } 93 | 94 | void writeInt64(uint64_t v) { 95 | std::vector bytes; 96 | std::reverse(bytes.begin(), bytes.end()); 97 | outputStream_.write(bytes.data(), bytes.size()); 98 | } 99 | 100 | private: 101 | std::vector longToBytes(uint64_t l) { 102 | std::vector result(8, 0); 103 | for (int i = 7; i >= 0; i--) { 104 | result[i] = (char)(l & 0xFF); 105 | l >>= 8; 106 | } 107 | return result; 108 | } 109 | 110 | public: 111 | void writeShort(int v) { 112 | outputStream_.put(0xFF & v); 113 | outputStream_.put(0xFF & (v >> 8)); 114 | } 115 | 116 | void writeUTF(const std::string & str) { 117 | outputStream_.write(str.c_str(), str.length()); 118 | } 119 | 120 | void close() { 121 | //outputStream.close(); 122 | } 123 | 124 | 125 | }; 126 | -------------------------------------------------------------------------------- /PhotonProjectType.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * by bn on 30/06/2018. 27 | */ 28 | enum PhotonProjectType { 29 | cast = 0, 30 | lcdMirror = 1, 31 | }; 32 | 33 | /* ; 34 | 35 | int projectID; 36 | 37 | PhotonProjectType(int projectID) { 38 | projectID = projectID; 39 | } 40 | 41 | public static PhotonProjectType find(int typeID) { 42 | for(PhotonProjectType photonProjectType : values()) { 43 | if (photonProjectType.projectID == typeID) { 44 | return photonProjectType; 45 | } 46 | } 47 | return lcdMirror; 48 | } 49 | } 50 | */ -------------------------------------------------------------------------------- /PhotonRow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Bonosoft 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * by bn on 10/07/2018. 28 | */ 29 | class PhotonRow { 30 | public: 31 | std::vector lines_; 32 | }; 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # PngToPhoton 5 | 6 | Quick and dirty utility I've made to convert PNG files to Anycubic Photon 3d printer file format. It could be useful for PCB production. Source code was ported to C++ from [Photon File Validator](https://github.com/Photonsters/PhotonFileValidator) project. 7 | 8 | # Usage 9 | 10 | PngToPhoton.exe 11 | 12 | To read data from STDIN use '-' as filename. 13 | To write data from STDOUT use '-' as filename. 14 | 15 | White and transparent areas of the image are treated as voids. 16 | I insist on checking output with Photon File Validator after conversion. Use output at your own risk. 17 | 18 | # Building 19 | 20 | There is MSVC project for Windows and Makefile for Linux and MacOS X. 21 | -------------------------------------------------------------------------------- /_model.photon: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x3f00/PhotonCpp/9dc7d0a688ceb469d0af6b81396ff35aa12bb776/_model.photon -------------------------------------------------------------------------------- /model.scad: -------------------------------------------------------------------------------- 1 | rotate(a=[90,0,0]) 2 | linear_extrude(height = 0.1, center = true, convexity = 10, twist = 0) 3 | polygon(points=[[0,0],[0.15,0],[0,0.15]]); -------------------------------------------------------------------------------- /model.stl: -------------------------------------------------------------------------------- 1 | solid OpenSCAD_Model 2 | facet normal 0 1 0 3 | outer loop 4 | vertex 0 0.05 0 5 | vertex 0 0.05 0.149994 6 | vertex 0.149994 0.05 0 7 | endloop 8 | endfacet 9 | facet normal 0 -1 0 10 | outer loop 11 | vertex 0.149994 -0.05 0 12 | vertex 0 -0.05 0.149994 13 | vertex 0 -0.05 0 14 | endloop 15 | endfacet 16 | facet normal -1 0 0 17 | outer loop 18 | vertex 0 0.05 0 19 | vertex 0 -0.05 0.149994 20 | vertex 0 0.05 0.149994 21 | endloop 22 | endfacet 23 | facet normal -1 0 0 24 | outer loop 25 | vertex 0 0.05 0 26 | vertex 0 -0.05 0 27 | vertex 0 -0.05 0.149994 28 | endloop 29 | endfacet 30 | facet normal -0 0 -1 31 | outer loop 32 | vertex 0.149994 0.05 0 33 | vertex 0 -0.05 0 34 | vertex 0 0.05 0 35 | endloop 36 | endfacet 37 | facet normal 0 -0 -1 38 | outer loop 39 | vertex 0.149994 0.05 0 40 | vertex 0.149994 -0.05 0 41 | vertex 0 -0.05 0 42 | endloop 43 | endfacet 44 | facet normal 0.707107 0 0.707107 45 | outer loop 46 | vertex 0 0.05 0.149994 47 | vertex 0.149994 -0.05 0 48 | vertex 0.149994 0.05 0 49 | endloop 50 | endfacet 51 | facet normal 0.707107 0 0.707107 52 | outer loop 53 | vertex 0 0.05 0.149994 54 | vertex 0 -0.05 0.149994 55 | vertex 0.149994 -0.05 0 56 | endloop 57 | endfacet 58 | endsolid OpenSCAD_Model 59 | -------------------------------------------------------------------------------- /pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed 2 | 3 | #include "pch.h" 4 | 5 | // In general, ignore this file, but keep it around if you are using pre-compiled headers. 6 | -------------------------------------------------------------------------------- /pch.h: -------------------------------------------------------------------------------- 1 | // Tips for Getting Started: 2 | // 1. Use the Solution Explorer window to add/manage files 3 | // 2. Use the Team Explorer window to connect to source control 4 | // 3. Use the Output window to see build output and other messages 5 | // 4. Use the Error List window to view errors 6 | // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project 7 | // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file 8 | 9 | #ifndef PCH_H 10 | #define PCH_H 11 | 12 | #include 13 | 14 | #ifdef WIN32 15 | #include 16 | #include 17 | #endif // WIN32 18 | 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace photoncpp { 34 | using MatrixInt = std::vector>; 35 | using Color = uint32_t; 36 | using BitSet = std::vector; 37 | } 38 | 39 | #include "PhotonAaMatrix.h" 40 | #include "PhotonDot.h" 41 | #include "PhotonLine.h" 42 | #include "PhotonRow.h" 43 | #include "PhotonInputStream.h" 44 | #include "PhotonOutputStream.h" 45 | #include "PhotonProjectType.h" 46 | #include "PhotonMatrix.h" 47 | #include "PhotonLayer.h" 48 | #include "PhotonFileHeader.h" 49 | #include "PhotonFileLayer.h" 50 | #include "PhotonFilePreview.h" 51 | #include "PhotonFilePrintParameters.h" 52 | 53 | #endif //PCH_H 54 | --------------------------------------------------------------------------------