| 150 | } |
| 151 | |
| 152 | std::shared_ptr<ImageBuffer> loadImagePHM(const DeviceRef& device, |
| 153 | const std::string& filename, |
| 154 | DataType dataType, |
| 155 | Storage storage) |
| 156 | { |
| 157 | // Open the file |
| 158 | std::ifstream file(filename, std::ios::binary); |
| 159 | if (file.fail()) |
| 160 | throw std::runtime_error("cannot open image file: '" + filename + "'"); |
| 161 | |
| 162 | // Read the header |
| 163 | std::string id; |
| 164 | file >> id; |
| 165 | int C; |
| 166 | if (id == "PH") |
| 167 | C = 3; |
| 168 | else if (id == "Ph") |
| 169 | C = 1; |
| 170 | else if (id == "P:") |
| 171 | C = 2; // non-standard 2-channel format |
| 172 | else |
| 173 | throw std::runtime_error("invalid PHM image"); |
| 174 | |
| 175 | if (dataType == DataType::Undefined) |
| 176 | dataType = DataType::Float16; |
| 177 | |
| 178 | int H, W; |
| 179 | file >> W >> H; |
| 180 | |
| 181 | float scale; |
| 182 | file >> scale; |
| 183 | |
| 184 | file.get(); // skip newline |
| 185 | |
| 186 | if (file.fail()) |
| 187 | throw std::runtime_error("invalid PHM image"); |
| 188 | |
| 189 | if (scale >= 0.f) |
| 190 | throw std::runtime_error("big-endian PHM images are not supported"); |
| 191 | scale = fabs(scale); |
| 192 | |
| 193 | // Read the pixels |
| 194 | auto image = std::make_shared<ImageBuffer>(device, W, H, C, dataType, storage); |
| 195 | |
| 196 | for (int h = 0; h < H; ++h) |
| 197 | { |
| 198 | for (int w = 0; w < W; ++w) |
| 199 | { |
| 200 | for (int c = 0; c < C; ++c) |
| 201 | { |
| 202 | half x; |
| 203 | file.read((char*)&x, sizeof(x)); |
| 204 | if (scale == 1.f) |
| 205 | { |
| 206 | image->set((size_t(H-1-h)*W + w) * C + c, x); |
| 207 | } |
| 208 | else |
| 209 | { |