| 320 | } |
| 321 | |
| 322 | void CommandExtract::executeExtract() { |
| 323 | InputStream inputStream(options.inputFilepath, *this); |
| 324 | validateToolInput(inputStream, fmtInFile(options.inputFilepath), *this); |
| 325 | |
| 326 | KTXTexture2 texture{nullptr}; |
| 327 | StreambufStream<std::streambuf*> ktx2Stream{inputStream->rdbuf(), std::ios::in | std::ios::binary}; |
| 328 | auto ret = ktxTexture2_CreateFromStream(ktx2Stream.stream(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, texture.pHandle()); |
| 329 | if (ret != KTX_SUCCESS) |
| 330 | fatal(rc::INVALID_FILE, "Failed to create KTX2 texture: {}", ktxErrorString(ret)); |
| 331 | |
| 332 | // CLI request validation |
| 333 | if (!options.fragmentURI.mip.validate(texture->numLevels)) |
| 334 | fatal(rc::INVALID_FILE, "Requested level index {} is missing. The input file only has {} level(s).", |
| 335 | options.fragmentURI.mip, texture->numLevels); |
| 336 | |
| 337 | if (((options.uriFlagUsed && !options.fragmentURI.stratal.is_undefined()) || options.layerFlagUsed) && !texture->isArray) { |
| 338 | if (options.fragmentURI.stratal == all) |
| 339 | fatal(rc::INVALID_FILE, "Requested all layers from a non-array texture."); |
| 340 | else |
| 341 | fatal(rc::INVALID_FILE, "Requested layer index {} from a non-array texture.", options.fragmentURI.stratal); |
| 342 | } |
| 343 | |
| 344 | if (!options.fragmentURI.stratal.validate(texture->numLayers)) |
| 345 | fatal(rc::INVALID_FILE, "Requested layer index {} is missing. The input file only has {} layer(s).", |
| 346 | options.fragmentURI.stratal, texture->numLayers); |
| 347 | |
| 348 | if (((options.uriFlagUsed && !options.fragmentURI.facial.is_undefined()) || options.faceFlagUsed) && !texture->isCubemap) { |
| 349 | if (options.fragmentURI.facial == all) |
| 350 | fatal(rc::INVALID_FILE, "Requested all faces from a non-cubemap texture."); |
| 351 | else |
| 352 | fatal(rc::INVALID_FILE, "Requested face index {} from a non-cubemap texture.", options.fragmentURI.facial); |
| 353 | } |
| 354 | |
| 355 | if (!options.fragmentURI.facial.validate(texture->numFaces)) |
| 356 | fatal(rc::INVALID_FILE, "Requested face index {} is missing. The input file only has {} face(s).", |
| 357 | options.fragmentURI.facial, texture->numFaces); |
| 358 | |
| 359 | if (!options.globalAll && options.depthFlagUsed && texture->numDimensions != 3) { |
| 360 | if (options.depth == all) |
| 361 | fatal(rc::INVALID_FILE, "Requested all depth slices from a non-3D texture."); |
| 362 | else |
| 363 | fatal(rc::INVALID_FILE, "Requested depth slice index {} from a non-3D texture.", options.depth); |
| 364 | } |
| 365 | |
| 366 | // Transcoding |
| 367 | if (ktxTexture2_NeedsTranscoding(texture)) { |
| 368 | texture = transcode(std::move(texture), options, *this); |
| 369 | |
| 370 | } else if (options.transcodeTarget) { |
| 371 | fatal(rc::INVALID_FILE, "Requested transcode \"{}\" but the KTX file is not transcodable.", |
| 372 | options.transcodeTargetName); |
| 373 | } |
| 374 | |
| 375 | const auto format = createFormatDescriptor(texture->pDfd); |
| 376 | const auto blockSizeZ = format.basic.texelBlockDimension2 + 1u; |
| 377 | |
| 378 | const auto lastExportedLevel = options.fragmentURI.mip == all ? texture->numLevels - 1 : options.fragmentURI.mip.last(); |
| 379 | const auto lastExportedLevelDepthCount = std::max(1u, ceil_div(texture->baseDepth, blockSizeZ) >> lastExportedLevel); |
nothing calls this directly
no test coverage detected