|
27 | 27 | #include "ReformatBitmap.h" |
28 | 28 | #include "IccRecognizer.h" |
29 | 29 | #include "thread" |
30 | | -#include "VulkanRunner.h" |
31 | 30 | #include <android/asset_manager_jni.h> |
32 | 31 | #include "imagebits/RGBAlpha.h" |
33 | 32 | #include "imagebits/RgbaU16toHF.h" |
| 33 | +#include "Eigen/Eigen" |
34 | 34 |
|
35 | 35 | using namespace std; |
36 | 36 |
|
@@ -174,162 +174,92 @@ jobject decodeImplementationNative(JNIEnv *env, jobject thiz, |
174 | 174 | convertUseICC(dstARGB, stride, imageWidth, imageHeight, profile.data(), |
175 | 175 | profile.size(), |
176 | 176 | useBitmapHalf16Floats, &stride); |
177 | | - } else if ((colorProfile == "BT2020_PQ" || colorProfile == "DISPLAY_P3_PQ" || |
178 | | - colorProfile == "BT2020_HLG" || colorProfile == "DISPLAY_P3_HLG" || |
179 | | - colorProfile.find("SMPTE_428") != std::string::npos) && hasNCLX && (nclx)) { |
180 | | - bool isVulkanLoaded = loadVulkanRunner(); |
181 | | - bool vulkanWorkerDone = false; |
182 | | - if (assetManager != nullptr && isVulkanLoaded) { |
183 | | - std::string kernel = "SMPTE2084.comp.spv"; |
184 | | - |
185 | | - if (colorProfile.find("HLG") != std::string::npos) { |
186 | | - kernel = "HLG.comp.spv"; |
187 | | - } else if (colorProfile.find("SMPTE_428") != std::string::npos) { |
188 | | - kernel = "SMPTE428.comp.spv"; |
189 | | - } |
190 | | - |
191 | | - float primaries[3][2] = {{static_cast<float>(nclx->color_primary_red_x), |
192 | | - static_cast<float>(nclx->color_primary_red_y)}, |
193 | | - {static_cast<float>(nclx->color_primary_green_x), |
194 | | - static_cast<float>(nclx->color_primary_green_y)}, |
195 | | - {static_cast<float>(nclx->color_primary_blue_x), |
196 | | - static_cast<float>(nclx->color_primary_blue_y)}}; |
197 | | - float whitePoint[2] = {static_cast<float>(nclx->color_primary_white_x), |
198 | | - static_cast<float>(nclx->color_primary_white_y)}; |
199 | | - |
200 | | - float lumaPrimaries[3]; |
201 | | - |
202 | | - if (colorProfile.find("BT2020") != std::string::npos) { |
203 | | - memcpy(lumaPrimaries, Rec2020LumaPrimaries, sizeof(float) * 3); |
204 | | - } else { |
205 | | - memcpy(lumaPrimaries, DisplayP3LumaPrimaries, sizeof(float) * 3); |
206 | | - } |
207 | | - |
208 | | - ColorSpaceProfile srcProfile(primaries, whitePoint, Rec2020LumaPrimaries, |
209 | | - Rec2020WhitePointNits); |
210 | | - CmsMatrix dstMatrix = CmsMatrix(rec709Profile->primaries, rec709Profile->illuminant); |
211 | | - CmsMatrix srcMatrix = CmsMatrix(srcProfile.primaries, srcProfile.illuminant); |
212 | | - CmsMatrix trns = dstMatrix.inverted() * srcMatrix; |
213 | | - |
214 | | - ShaderEotfData shaderData = { |
215 | | - .toneMapper = toneMapper, |
216 | | - .oetfCurve = 1, |
217 | | - }; |
218 | | - |
219 | | - memcpy(shaderData.lumaPrimaries, lumaPrimaries, sizeof(float) * 3); |
220 | | - |
221 | | - if (colorProfile == "DISPLAY_P3_PQ" || colorProfile == "DISPLAY_P3_HLG" || |
222 | | - colorProfile.find("BT2020") != std::string::npos) { |
223 | | - shaderData.oetfCurve = 2; |
224 | | - } |
225 | | - |
226 | | - for (int i = 0; i < 3; ++i) { |
227 | | - for (int j = 0; j < 3; ++j) { |
228 | | - shaderData.colorMatrix[i][j] = trns.getMatrix()[i * 3 + j]; |
229 | | - } |
230 | | - } |
231 | | - |
232 | | - vulkanWorkerDone = VulkanRunnerWithData(kernel, assetManager, |
233 | | - reinterpret_cast<uint8_t *>(dstARGB.data()), |
234 | | - imageWidth, |
235 | | - imageHeight, stride, |
236 | | - useBitmapHalf16Floats ? RgbaF16 : RgbaU8, |
237 | | - reinterpret_cast<void *>(&shaderData), |
238 | | - sizeof(ShaderEotfData)); |
239 | | - } |
240 | | - if (!vulkanWorkerDone) { |
241 | | - ColorSpaceProfile srcProfile(Rec2020Primaries, IlluminantD65, |
242 | | - Rec2020LumaPrimaries, |
243 | | - Rec2020WhitePointNits); |
244 | | - GammaCurve gammaCurve = Rec2020; |
245 | | - HDRTransferFunction function = PQ; |
246 | | - if (colorProfile == "DISPLAY_P3_PQ" || colorProfile == "DISPLAY_P3_HLG") { |
247 | | - gammaCurve = DCIP3; |
248 | | - } |
249 | | - |
250 | | - if (colorProfile.find("HLG") != std::string::npos) { |
251 | | - function = HLG; |
252 | | - } else if (colorProfile.find("SMPTE_428") != std::string::npos) { |
253 | | - function = SMPTE428; |
254 | | - gammaCurve = DCIP3; |
255 | | - } |
256 | | - HDRTransferAdapter hdrTransferAdapter( |
257 | | - reinterpret_cast<uint8_t *>(dstARGB.data()), |
258 | | - stride, imageWidth, imageHeight, useBitmapHalf16Floats, |
259 | | - useBitmapHalf16Floats ? 16 : 8, gammaCurve, function, toneMapper, &srcProfile, |
260 | | - rec709Profile, 2.2f); |
261 | | - hdrTransferAdapter.transfer(); |
262 | | - } |
263 | | - } else if (colorProfile == "BT2020" || colorProfile == "BT709" || |
264 | | - colorProfile == "DISPLAY_P3") { |
265 | | - bool isVulkanLoaded = loadVulkanRunner(); |
266 | | - bool vulkanWorkerDone = false; |
267 | | - |
268 | | - ColorSpaceProfile *srcProfile = rec2020Profile; |
269 | | - if (colorProfile == "BT709") { |
270 | | - srcProfile = rec709Profile; |
| 177 | + } else if (hasNCLX && nclx && |
| 178 | + nclx->transfer_characteristics != heif_transfer_characteristic_unspecified && |
| 179 | + nclx->color_primaries != heif_color_primaries_unspecified) { |
| 180 | + Eigen::Matrix<float, 3, 2> primaries; |
| 181 | + if (nclx->color_primaries != heif_color_primaries_unspecified) { |
| 182 | + primaries << static_cast<float>(nclx->color_primary_red_x), |
| 183 | + static_cast<float>(nclx->color_primary_red_y), |
| 184 | + static_cast<float>(nclx->color_primary_green_x), |
| 185 | + static_cast<float>(nclx->color_primary_green_y), |
| 186 | + static_cast<float>(nclx->color_primary_blue_x), |
| 187 | + static_cast<float>(nclx->color_primary_blue_y); |
| 188 | + } else { |
| 189 | + primaries = getSRGBPrimaries(); |
271 | 190 | } |
272 | | - CmsMatrix dstMatrix = CmsMatrix(rec709Profile->primaries, rec709Profile->illuminant); |
273 | | - CmsMatrix srcMatrix = CmsMatrix(srcProfile->primaries, srcProfile->illuminant); |
274 | | - CmsMatrix trns = dstMatrix.inverted() * srcMatrix; |
275 | | - |
276 | | - float lumaPrimaries[3]; |
277 | | - |
278 | | - if (colorProfile.find("BT2020") != std::string::npos) { |
279 | | - memcpy(lumaPrimaries, Rec2020LumaPrimaries, sizeof(float) * 3); |
280 | | - } else if (colorProfile.find("BT709") != std::string::npos) { |
281 | | - memcpy(lumaPrimaries, Rec709LumaPrimaries, sizeof(float) * 3); |
| 191 | + Eigen::Vector2f whitePoint; |
| 192 | + if (nclx->color_primaries != heif_color_primaries_unspecified) { |
| 193 | + whitePoint << static_cast<float>(nclx->color_primary_white_x), |
| 194 | + static_cast<float>(nclx->color_primary_white_y); |
282 | 195 | } else { |
283 | | - memcpy(lumaPrimaries, DisplayP3LumaPrimaries, sizeof(float) * 3); |
| 196 | + whitePoint = getIlluminantD65(); |
284 | 197 | } |
285 | 198 |
|
286 | | - if (isVulkanLoaded) { |
287 | | - ShaderGammaData shaderData = { |
288 | | - .oetfCurve = 3, |
289 | | - .gamma = 2.4, |
290 | | - }; |
291 | | - |
292 | | - if (colorProfile.find("P3") != std::string::npos) { |
293 | | - shaderData.gamma = 2.6f; |
294 | | - } else if (colorProfile.find("709") != std::string::npos) { |
295 | | - shaderData.gamma = 2.0f; |
296 | | - } |
297 | | - |
298 | | - memcpy(shaderData.lumaPrimaries, lumaPrimaries, sizeof(float) * 3); |
299 | | - |
300 | | - for (int i = 0; i < 3; ++i) { |
301 | | - for (int j = 0; j < 3; ++j) { |
302 | | - shaderData.colorMatrix[i][j] = trns.getMatrix()[i * 3 + j]; |
303 | | - } |
304 | | - } |
305 | | - string kernel = "GammaOetf.comp.spv"; |
306 | | - vulkanWorkerDone = VulkanRunnerWithData(kernel, assetManager, |
307 | | - reinterpret_cast<uint8_t *>(dstARGB.data()), |
308 | | - imageWidth, |
309 | | - imageHeight, stride, |
310 | | - useBitmapHalf16Floats ? RgbaF16 : RgbaU8, |
311 | | - reinterpret_cast<void *>(&shaderData), |
312 | | - sizeof(ShaderGammaData)); |
313 | | - } |
314 | | - if (!vulkanWorkerDone) { |
315 | | - HDRTransferFunction function = GAMMA_TRANSFER; |
316 | | - float gamma = 2.4f; |
317 | | - if (colorProfile.find("P3") != std::string::npos) { |
318 | | - gamma = 2.6f; |
319 | | - } else if (colorProfile.find("709") != std::string::npos) { |
320 | | - gamma = 2.0f; |
321 | | - } |
322 | | - |
323 | | - HDRTransferAdapter hdrTransferAdapter( |
324 | | - reinterpret_cast<uint8_t *>(dstARGB.data()), |
325 | | - stride, imageWidth, imageHeight, useBitmapHalf16Floats, |
326 | | - useBitmapHalf16Floats ? 16 : 8, sRGB, function, toneMapper, srcProfile, |
327 | | - rec709Profile, gamma); |
328 | | - hdrTransferAdapter.transfer(); |
| 199 | + Eigen::Matrix3f srgbXyz = GamutRgbToXYZ(getSRGBPrimaries(), getIlluminantD65()); |
| 200 | + Eigen::Matrix3f srcXyz = GamutRgbToXYZ(primaries, whitePoint); |
| 201 | + |
| 202 | + Eigen::Matrix3f conversion = srgbXyz.inverse() * srgbXyz; |
| 203 | + |
| 204 | + GammaCurve gammaCurve = sRGB; |
| 205 | + GamutTransferFunction function = SKIP; |
| 206 | + |
| 207 | + const float gamma = 1.0f; |
| 208 | + |
| 209 | + if (nclx->transfer_characteristics == |
| 210 | + heif_transfer_characteristic_ITU_R_BT_2100_0_HLG) { |
| 211 | + function = HLG; |
| 212 | + } else if (nclx->transfer_characteristics == |
| 213 | + heif_transfer_characteristic_SMPTE_ST_428_1) { |
| 214 | + function = SMPTE428; |
| 215 | + } else if (nclx->transfer_characteristics == |
| 216 | + heif_transfer_characteristic_ITU_R_BT_2100_0_PQ) { |
| 217 | + function = PQ; |
| 218 | + } else if (nclx->transfer_characteristics == heif_transfer_characteristic_linear) { |
| 219 | + function = SKIP; |
| 220 | + } else if (nclx->transfer_characteristics == |
| 221 | + heif_transfer_characteristic_ITU_R_BT_470_6_System_M) { |
| 222 | + function = Gamma2p2; |
| 223 | + } else if (nclx->transfer_characteristics == |
| 224 | + heif_transfer_characteristic_ITU_R_BT_470_6_System_B_G) { |
| 225 | + function = Gamma2p8; |
| 226 | + } else if (nclx->transfer_characteristics == |
| 227 | + heif_transfer_characteristic_ITU_R_BT_601_6) { |
| 228 | + function = EOTF_BT601; |
| 229 | + } else if ( |
| 230 | + nclx->transfer_characteristics == heif_transfer_characteristic_ITU_R_BT_709_5 || |
| 231 | + nclx->transfer_characteristics == |
| 232 | + heif_transfer_characteristic_ITU_R_BT_2020_2_10bit || |
| 233 | + nclx->transfer_characteristics == |
| 234 | + heif_transfer_characteristic_ITU_R_BT_2020_2_12bit) { |
| 235 | + function = EOTF_BT709; |
| 236 | + } else if (nclx->transfer_characteristics == heif_transfer_characteristic_SMPTE_240M) { |
| 237 | + function = EOTF_SMPTE240; |
| 238 | + } else if (nclx->transfer_characteristics == |
| 239 | + heif_transfer_characteristic_logarithmic_100) { |
| 240 | + function = EOTF_LOG100; |
| 241 | + } else if (nclx->transfer_characteristics == |
| 242 | + heif_transfer_characteristic_logarithmic_100_sqrt10) { |
| 243 | + function = EOTF_LOG100SRT10; |
| 244 | + } else if ( |
| 245 | + nclx->transfer_characteristics == heif_transfer_characteristic_IEC_61966_2_1 || |
| 246 | + nclx->transfer_characteristics == heif_transfer_characteristic_IEC_61966_2_4) { |
| 247 | + function = EOTF_IEC_61966; |
| 248 | + } else if (nclx->transfer_characteristics == |
| 249 | + heif_transfer_characteristic_ITU_R_BT_1361) { |
| 250 | + function = EOTF_BT1361; |
| 251 | + } else if (nclx->transfer_characteristics == heif_transfer_characteristic_unspecified) { |
| 252 | + function = EOTF_BT709; |
329 | 253 | } |
330 | | - } else if (colorProfile == "LINEAR_SRGB") { |
331 | | - convertUseICC(dstARGB, stride, imageWidth, imageHeight, &linearSRGB[0], |
332 | | - sizeof(linearSRGB), useBitmapHalf16Floats, &stride); |
| 254 | + HDRTransferAdapter hdrTransferAdapter( |
| 255 | + reinterpret_cast<uint8_t *>(dstARGB.data()), |
| 256 | + stride, imageWidth, imageHeight, useBitmapHalf16Floats, |
| 257 | + useBitmapHalf16Floats ? 16 : 8, gammaCurve, function, |
| 258 | + toneMapper, |
| 259 | + &conversion, |
| 260 | + gamma, |
| 261 | + getIlluminantD65() != whitePoint); |
| 262 | + hdrTransferAdapter.transfer(); |
333 | 263 | } |
334 | 264 |
|
335 | 265 | string imageConfig = useBitmapHalf16Floats ? "RGBA_F16" : "ARGB_8888"; |
|
0 commit comments