/* * Copyright 2018-2019 NVIDIA Corporation. All rights reserved. * * NOTICE TO LICENSEE: * * This source code and/or documentation ("Licensed Deliverables") are * subject to NVIDIA intellectual property rights under U.S. and * international Copyright laws. * * These Licensed Deliverables contained herein is PROPRIETARY and * CONFIDENTIAL to NVIDIA and is being provided under the terms and * conditions of a form of NVIDIA software license agreement by and * between NVIDIA and Licensee ("License Agreement") or electronically * accepted by Licensee. Notwithstanding any terms or conditions to * the contrary in the License Agreement, reproduction or disclosure * of the Licensed Deliverables to any third party without the express * written consent of NVIDIA is prohibited. * * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE * LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE * SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE. IT IS * PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. * NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED * DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, * NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE * LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY * SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THESE LICENSED DELIVERABLES. * * U.S. Government End Users. These Licensed Deliverables are a * "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT * 1995), consisting of "commercial computer software" and "commercial * computer software documentation" as such terms are used in 48 * C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government * only as a commercial end item. Consistent with 48 C.F.R.12.212 and * 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all * U.S. Government End Users acquire the Licensed Deliverables with * only those rights set forth herein. * * Any use of the Licensed Deliverables in individual and commercial * software must include, in the user documentation and internal * comments to the code, the above Disclaimer and U.S. Government End * Users Notice. */ // This sample needs at least CUDA 10.1. // It demonstrates usages of the nvJPEG library #ifndef NV_JPEG_EXAMPLE #define NV_JPEG_EXAMPLE #ifdef _WIN64 #include #endif #include "cuda_runtime.h" #include "nvjpeg.h" #include "helper_cuda.h" #include "helper_timer.h" #include "helper_string.h" #include #include #include #include #include #include #include // strcmpi #ifndef _WIN64 #include // timings #include // linux dir traverse #include #endif #include #include // write bmp, input - RGB, device int writeBMP(const char *filename, const unsigned char *d_chanR, int pitchR, const unsigned char *d_chanG, int pitchG, const unsigned char *d_chanB, int pitchB, int width, int height) { unsigned int headers[13]; FILE *outfile; int extrabytes; int paddedsize; int x; int y; int n; int red, green, blue; std::vector vchanR(height * width); std::vector vchanG(height * width); std::vector vchanB(height * width); unsigned char *chanR = vchanR.data(); unsigned char *chanG = vchanG.data(); unsigned char *chanB = vchanB.data(); checkCudaErrors(cudaMemcpy2D(chanR, (size_t)width, d_chanR, (size_t)pitchR, width, height, cudaMemcpyDeviceToHost)); checkCudaErrors(cudaMemcpy2D(chanG, (size_t)width, d_chanG, (size_t)pitchR, width, height, cudaMemcpyDeviceToHost)); checkCudaErrors(cudaMemcpy2D(chanB, (size_t)width, d_chanB, (size_t)pitchR, width, height, cudaMemcpyDeviceToHost)); extrabytes = 4 - ((width * 3) % 4); // How many bytes of padding to add to each // horizontal line - the size of which must // be a multiple of 4 bytes. if (extrabytes == 4) extrabytes = 0; paddedsize = ((width * 3) + extrabytes) * height; // Headers... // Note that the "BM" identifier in bytes 0 and 1 is NOT included in these // "headers". headers[0] = paddedsize + 54; // bfSize (whole file size) headers[1] = 0; // bfReserved (both) headers[2] = 54; // bfOffbits headers[3] = 40; // biSize headers[4] = width; // biWidth headers[5] = height; // biHeight // Would have biPlanes and biBitCount in position 6, but they're shorts. // It's easier to write them out separately (see below) than pretend // they're a single int, especially with endian issues... headers[7] = 0; // biCompression headers[8] = paddedsize; // biSizeImage headers[9] = 0; // biXPelsPerMeter headers[10] = 0; // biYPelsPerMeter headers[11] = 0; // biClrUsed headers[12] = 0; // biClrImportant if (!(FOPEN(outfile, filename, "wb"))) { std::cerr << "Cannot open file: " << filename << std::endl; return 1; } // // Headers begin... // When printing ints and shorts, we write out 1 character at a time to avoid // endian issues. // fprintf(outfile, "BM"); for (n = 0; n <= 5; n++) { fprintf(outfile, "%c", headers[n] & 0x000000FF); fprintf(outfile, "%c", (headers[n] & 0x0000FF00) >> 8); fprintf(outfile, "%c", (headers[n] & 0x00FF0000) >> 16); fprintf(outfile, "%c", (headers[n] & (unsigned int)0xFF000000) >> 24); } // These next 4 characters are for the biPlanes and biBitCount fields. fprintf(outfile, "%c", 1); fprintf(outfile, "%c", 0); fprintf(outfile, "%c", 24); fprintf(outfile, "%c", 0); for (n = 7; n <= 12; n++) { fprintf(outfile, "%c", headers[n] & 0x000000FF); fprintf(outfile, "%c", (headers[n] & 0x0000FF00) >> 8); fprintf(outfile, "%c", (headers[n] & 0x00FF0000) >> 16); fprintf(outfile, "%c", (headers[n] & (unsigned int)0xFF000000) >> 24); } // // Headers done, now write the data... // for (y = height - 1; y >= 0; y--) // BMP image format is written from bottom to top... { for (x = 0; x <= width - 1; x++) { red = chanR[y * width + x]; green = chanG[y * width + x]; blue = chanB[y * width + x]; if (red > 255) red = 255; if (red < 0) red = 0; if (green > 255) green = 255; if (green < 0) green = 0; if (blue > 255) blue = 255; if (blue < 0) blue = 0; // Also, it's written in (b,g,r) format... fprintf(outfile, "%c", blue); fprintf(outfile, "%c", green); fprintf(outfile, "%c", red); } if (extrabytes) // See above - BMP lines must be of lengths divisible by 4. { for (n = 1; n <= extrabytes; n++) { fprintf(outfile, "%c", 0); } } } fclose(outfile); return 0; } // write bmp, input - RGB, device int writeBMPi(const char *filename, const unsigned char *d_RGB, int pitch, int width, int height) { unsigned int headers[13]; FILE *outfile; int extrabytes; int paddedsize; int x; int y; int n; int red, green, blue; std::vector vchanRGB(height * width * 3); unsigned char *chanRGB = vchanRGB.data(); checkCudaErrors(cudaMemcpy2D(chanRGB, (size_t)width * 3, d_RGB, (size_t)pitch, width * 3, height, cudaMemcpyDeviceToHost)); extrabytes = 4 - ((width * 3) % 4); // How many bytes of padding to add to each // horizontal line - the size of which must // be a multiple of 4 bytes. if (extrabytes == 4) extrabytes = 0; paddedsize = ((width * 3) + extrabytes) * height; // Headers... // Note that the "BM" identifier in bytes 0 and 1 is NOT included in these // "headers". headers[0] = paddedsize + 54; // bfSize (whole file size) headers[1] = 0; // bfReserved (both) headers[2] = 54; // bfOffbits headers[3] = 40; // biSize headers[4] = width; // biWidth headers[5] = height; // biHeight // Would have biPlanes and biBitCount in position 6, but they're shorts. // It's easier to write them out separately (see below) than pretend // they're a single int, especially with endian issues... headers[7] = 0; // biCompression headers[8] = paddedsize; // biSizeImage headers[9] = 0; // biXPelsPerMeter headers[10] = 0; // biYPelsPerMeter headers[11] = 0; // biClrUsed headers[12] = 0; // biClrImportant if (!(FOPEN(outfile, filename, "wb"))) { std::cerr << "Cannot open file: " << filename << std::endl; return 1; } // // Headers begin... // When printing ints and shorts, we write out 1 character at a time to avoid // endian issues. // fprintf(outfile, "BM"); for (n = 0; n <= 5; n++) { fprintf(outfile, "%c", headers[n] & 0x000000FF); fprintf(outfile, "%c", (headers[n] & 0x0000FF00) >> 8); fprintf(outfile, "%c", (headers[n] & 0x00FF0000) >> 16); fprintf(outfile, "%c", (headers[n] & (unsigned int)0xFF000000) >> 24); } // These next 4 characters are for the biPlanes and biBitCount fields. fprintf(outfile, "%c", 1); fprintf(outfile, "%c", 0); fprintf(outfile, "%c", 24); fprintf(outfile, "%c", 0); for (n = 7; n <= 12; n++) { fprintf(outfile, "%c", headers[n] & 0x000000FF); fprintf(outfile, "%c", (headers[n] & 0x0000FF00) >> 8); fprintf(outfile, "%c", (headers[n] & 0x00FF0000) >> 16); fprintf(outfile, "%c", (headers[n] & (unsigned int)0xFF000000) >> 24); } // // Headers done, now write the data... // for (y = height - 1; y >= 0; y--) // BMP image format is written from bottom to top... { for (x = 0; x <= width - 1; x++) { red = chanRGB[(y * width + x) * 3]; green = chanRGB[(y * width + x) * 3 + 1]; blue = chanRGB[(y * width + x) * 3 + 2]; if (red > 255) red = 255; if (red < 0) red = 0; if (green > 255) green = 255; if (green < 0) green = 0; if (blue > 255) blue = 255; if (blue < 0) blue = 0; // Also, it's written in (b,g,r) format... fprintf(outfile, "%c", blue); fprintf(outfile, "%c", green); fprintf(outfile, "%c", red); } if (extrabytes) // See above - BMP lines must be of lengths divisible by 4. { for (n = 1; n <= extrabytes; n++) { fprintf(outfile, "%c", 0); } } } fclose(outfile); return 0; } int inputDirExists(const char *pathname) { struct stat info; if (stat(pathname, &info) != 0) { return 0; // Directory does not exists } else if (info.st_mode & S_IFDIR) { // is a directory return 1; } else { // is not a directory return 0; } } int readInput(const std::string &sInputPath, std::vector &filelist) { int error_code = 1; #ifndef _WIN64 struct stat s; if (stat(sInputPath.c_str(), &s) == 0) { if (s.st_mode & S_IFREG) { filelist.push_back(sInputPath); } else if (s.st_mode & S_IFDIR) { // processing each file in directory DIR *dir_handle; struct dirent *dir; dir_handle = opendir(sInputPath.c_str()); std::vector filenames; if (dir_handle) { error_code = 0; while ((dir = readdir(dir_handle)) != NULL) { std::string sFileName = sInputPath + dir->d_name; if (inputDirExists(sFileName.c_str())) { std::string sname = dir->d_name; if (sname != "." && sname != "..") { readInput(sInputPath + sname + "/", filelist); } } else { filelist.push_back(sFileName); } } closedir(dir_handle); } else { std::cout << "Cannot open input directory: " << sInputPath << std::endl; return error_code; } } else { std::cout << "Cannot open input: " << sInputPath << std::endl; return error_code; } } else { std::cout << "Cannot find input path " << sInputPath << std::endl; return error_code; } #else std::string search_path = sInputPath + "/*.*"; WIN32_FIND_DATA fd; HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd); if (hFind != INVALID_HANDLE_VALUE) { do { // read all (real) files in current folder // , delete '!' read other 2 default folder . and .. if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { std::string temp(sInputPath + "\\" + fd.cFileName); filelist.push_back(temp); } } while (::FindNextFile(hFind, &fd)); ::FindClose(hFind); } else { std::cout << "Cannot open input directory: " << sInputPath << std::endl; return error_code; } #endif return 0; } int getInputDir(std::string &input_dir, const char *executable_path) { int found = 0; if (executable_path != 0) { std::string executable_name = std::string(executable_path); #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) // Windows path delimiter size_t delimiter_pos = executable_name.find_last_of('\\'); executable_name.erase(0, delimiter_pos + 1); if (executable_name.rfind(".exe") != std::string::npos) { // we strip .exe, only if the .exe is found executable_name.resize(executable_name.size() - 4); } #else // Linux & OSX path delimiter size_t delimiter_pos = executable_name.find_last_of('/'); executable_name.erase(0, delimiter_pos + 1); #endif // Search in default paths for input images. std::string pathname = ""; const char *searchPath[] = { "./images", "../../../7_CUDALibraries//images", "../../../../7_CUDALibraries//images", "./7_CUDALibraries//images", "../7_CUDALibraries//images"}; for (unsigned int i = 0; i < sizeof(searchPath) / sizeof(char *); ++i) { std::string pathname(searchPath[i]); size_t executable_name_pos = pathname.find(""); // If there is executable_name variable in the searchPath // replace it with the value if (executable_name_pos != std::string::npos) { pathname.replace(executable_name_pos, strlen(""), executable_name); } if (inputDirExists(pathname.c_str())) { input_dir = pathname + "/"; found = 1; break; } } } return found; } #endif