| 364 | } |
| 365 | |
| 366 | void SetImageTensorFromByteVector(const TensorData &tensorData, std::vector<nvcv::Byte> &data, int sample) |
| 367 | { |
| 368 | Optional<TensorDataAccessStridedImage> tDataAc = nvcv::TensorDataAccessStridedImage::Create(tensorData); |
| 369 | |
| 370 | if (!tDataAc) |
| 371 | throw std::runtime_error("Tensor Data not compatible with pitch access."); |
| 372 | |
| 373 | if (tDataAc->infoLayout().isChannelFirst()) // planar case |
| 374 | return SetImageTensorFromByteVectorPlanar(tensorData, data, sample); |
| 375 | |
| 376 | if (tDataAc->numSamples() <= sample) |
| 377 | throw std::runtime_error("Number of samples smaller than requested sample."); |
| 378 | |
| 379 | if ((int64_t)data.size() |
| 380 | != tDataAc->numCols() * tDataAc->numRows() * (tDataAc->dtype().bitsPerPixel() / 8) * tDataAc->numChannels()) |
| 381 | throw std::runtime_error("Data vector is incorrect size, size must be N*W*sizeof(pixel)."); |
| 382 | |
| 383 | int bytesPerC = (tDataAc->dtype().bitsPerPixel() / 8); |
| 384 | |
| 385 | auto copyToGpu = [&](int i) |
| 386 | { |
| 387 | Byte *basePtr = tDataAc->sampleData(i); |
| 388 | Byte *srcPtr = data.data(); |
| 389 | size_t srcPitch = tDataAc->numCols() * bytesPerC * tDataAc->numChannels(); |
| 390 | size_t srcWidthBytes = tDataAc->numCols() * bytesPerC * tDataAc->numChannels(); |
| 391 | |
| 392 | if (cudaSuccess |
| 393 | != cudaMemcpy2D(basePtr, tDataAc->rowStride(), srcPtr, srcPitch, srcWidthBytes, tDataAc->numRows(), |
| 394 | cudaMemcpyHostToDevice)) |
| 395 | { |
| 396 | throw std::runtime_error("CudaMemcpy failed on copy of image from host to device."); |
| 397 | } |
| 398 | }; |
| 399 | |
| 400 | if (sample < 0) |
| 401 | for (auto i = 0; i < tDataAc->numSamples(); ++i) |
| 402 | { |
| 403 | copyToGpu(i); |
| 404 | } |
| 405 | else |
| 406 | copyToGpu(sample); |
| 407 | } |
| 408 | |
| 409 | } // namespace nvcv::util |