| 260 | } |
| 261 | |
| 262 | static void GetImageByteVectorFromTensorPlanar(const TensorData &tensorData, int sample, |
| 263 | std::vector<nvcv::Byte> &outData) |
| 264 | { |
| 265 | Optional<TensorDataAccessStridedImagePlanar> tDataAc = nvcv::TensorDataAccessStridedImagePlanar::Create(tensorData); |
| 266 | |
| 267 | if (!tDataAc) |
| 268 | throw std::runtime_error("Tensor Data not compatible with planar access."); |
| 269 | |
| 270 | if (tDataAc->numSamples() <= sample || sample < 0) |
| 271 | throw std::runtime_error("Number of samples smaller than requested sample."); |
| 272 | |
| 273 | // in a planar tensor the dtype represents each plane so the total bytes per pixel must be calculated |
| 274 | int bytesPerC = tDataAc->dtype().bitsPerPixel() / 8; |
| 275 | int outputSizeBytes = tDataAc->numRows() * tDataAc->numCols() * bytesPerC * tDataAc->numChannels(); |
| 276 | |
| 277 | // Make sure we have the right size. |
| 278 | outData.resize(outputSizeBytes); |
| 279 | Byte *basePtr = tDataAc->sampleData(sample); |
| 280 | size_t dstWidth = tDataAc->numCols() * bytesPerC; |
| 281 | for (int i = 0; i < tDataAc->numChannels(); ++i) |
| 282 | { |
| 283 | if (cudaSuccess |
| 284 | != cudaMemcpy2D(outData.data() + (i * (tDataAc->numCols() * tDataAc->numRows()) * bytesPerC), dstWidth, |
| 285 | basePtr, tDataAc->rowStride(), dstWidth, tDataAc->numRows(), cudaMemcpyDeviceToHost)) |
| 286 | { |
| 287 | throw std::runtime_error("CudaMemcpy failed on copy of channel plane from device to host."); |
| 288 | } |
| 289 | basePtr += tDataAc->planeStride(); |
| 290 | } |
| 291 | return; |
| 292 | } |
| 293 | |
| 294 | void GetImageByteVectorFromTensor(const TensorData &tensorData, int sample, std::vector<nvcv::Byte> &outData) |
| 295 | { |
no test coverage detected