This tutorial demonstrates how to initialize a DW Image. A CUDA image is used as an example to show how it can be initialized using pixels obtained from a PNG file and how color pixels can be read from dw image and saved to PNG file. For interacting with PNG files, publicly available lodepng library is used.
- Note
- 1. Lodepng library mentioned in this tutorial is a 3rd party library for PNG image files. Any other library can also be used for PNG or other file formats to load image file with specific format.
-
2. Refer to public documentation for Lodepng online for more details, error checking etc.
-
3. This tutorial uses cuda images. NvMedia or CPU images can also be used similarly by using respective APIs to copy pixels.
-
4. Error checking macros are for illustration purpose and may not actually be part of DW SDK
Steps for initializing DW image from an image file
Step 1: Loading a PNG image file
As described below, decode the PNG file to get image attributes and pixel data. These pixels will be used to initialize the DW image and the size(wxh) will be used to allocate DW image in next step.
uint8_t* pBytes = nullptr;
uint32_t width = 0;
uint32_t height = 0;
uint32_t bitDepth = 8;
uint32_t decodeRes = lodepng_decode_file(&pBytes, &width, &height, inFilePath.c_str(), LCT_RGBA, bitDepth);
if (decodeRes != 0)
{
std::cerr <<": loading png file failed. Error= "<< lodepng_error_text(decodeRes) << "(" << decodeRes << ") \n";
}
Step 2: Create a DW image file
Create an image as described here in "Basic Creation". This will allocate memory for the underlying image allocation.
Step 3: Get cuda pointer for image memory
Get the underlying memory using dwImage_getCUDA API to get the cuda pointer for the underlying image
Step 4: Initialize DW image using pixel data
Using the pixel data obtained above as source, copy it to the cuda pointer using cudaMemcpy2D API as shown below.
size_t elemSize = 0;
size_t planeCount = 0;
size_t srcPitch = planeChannels[0] * elemSize * imageCUDA->
prop.
width;
CHECK_FOR_CUDA_SUCCESS(cudaMemcpy2D(imageCUDA->
dptr[0],
pBytes,
srcPitch,
srcPitch,
cudaMemcpyHostToDevice),
"ImageCreateFromPNG: updateImage: Error: failed to copy to device buffer");
With above steps, a DW image can be initialized with pixel data obtained from png file.
- Note
- cudaMemcpy2D should be used as source and destination pitch may differ
-
Appropriate synchronization can be added when using cuda APIs as required
Saving image contents to file
Step 1: Get image pixels
The DW image pixel data is accessible using cuda pointer and can be copied using cudaMemcpy2D with cuda pointer as source and an array as destination. The destination shoulkd be large enough to hold pixel data.
size_t elemSize = 0;
size_t planeCount = 0;
size_t dstWidth = planeChannels[0] * elemSize * imageCUDA->
prop.
width;
std::unique_ptr<uint8_t[]> bytes(new uint8_t[size]);
CHECK_FOR_CUDA_SUCCESS(cudaMemcpy2D(bytes.get(),
dstWidth,
dstWidth,
cudaMemcpyDeviceToHost),
"cudaMemcpy2DA failed");
- Note
- Before reading image using cudaMemcpy2D, application has to ensure that previous writes has finished.
Step 2: Wait for cuda copy to finish
After cudaMemcpy2D, and before using the destination, application should ensure that copy has finished before using the destination.
Step 3: Save the pixel bytes to PNG file
The pixel data buffer obtained from DW image can now be processed by application as desired or can be saved to an image file. An example to store it as PNG file is shown below.
uint32_t res = lodepng_encode_file(destPath.c_str(), bytes.get(), props.
width, props.
height, LCT_RGBA, elemSize * 8);
if (res != 0)
{
std::cerr << " saveImage: lodepng_encode_file returned error= "
<< lodepng_error_text(res) << "(" << res << ")\n";
}