/* * Copyright 1993-2015 NVIDIA Corporation. All rights reserved. * * NOTICE TO USER: * * This source code is subject to NVIDIA ownership rights under U.S. and * international Copyright laws. * * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. * 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 THIS SOURCE CODE. * * U.S. Government End Users. This source code is 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 * source code with only those rights set forth herein. */ // This sample needs at least CUDA 5.5 and a GPU that has at least Compute Capability 2.0 // This sample demonstrates a simple image processing pipeline. // First, a JPEG file is huffman decoded and inverse DCT transformed and dequantized. // Then the different planes are resized. Finally, the resized image is quantized, forward // DCT transformed and huffman encoded. #include #include #include "EnCode/Exceptions.h" #include "EnCode/Endianess.h" #include #include #include #include #include #include using namespace std; struct FrameHeader //帧图像 { unsigned char nSamplePrecision; //精度:表示每个数据样本的位数 unsigned short nHeight; //图像的高 像素为单位 unsigned short nWidth; //图像的宽 像素为单位 unsigned char nComponents; //颜色分量个数 unsigned char aComponentIdentifier[3]; //颜色分量ID unsigned char aSamplingFactors[3]; //水平/垂直采样因子,高4位代表水平采样因子,低4位代表垂直采样因子 unsigned char aQuantizationTableSelector[3]; //当前分量使用的量化表ID }; struct ScanHeader { unsigned char nComponents; unsigned char aComponentSelector[3]; unsigned char aHuffmanTablesSelector[3]; unsigned char nSs; unsigned char nSe; unsigned char nA; }; struct QuantizationTable { unsigned char nPrecisionAndIdentifier; unsigned char aTable[64]; }; struct HuffmanTable { unsigned char nClassAndIdentifier; unsigned char aCodes[16]; unsigned char aTable[256]; }; int DivUp(int x, int d) { return (x + d - 1) / d; } template T readAndAdvance(const unsigned char *&pData) { T nElement = readBigEndian(pData); pData += sizeof(T); return nElement; } template void writeAndAdvance(unsigned char *&pData, T nElement) { writeBigEndian(pData, nElement); pData += sizeof(T); } int nextMarker(const unsigned char *pData, int &nPos, int nLength) { unsigned char c = pData[nPos++]; do { while (c != 0xffu && nPos < nLength) { c = pData[nPos++]; } if (nPos >= nLength) return -1; c = pData[nPos++]; } while (c == 0 || c == 0x0ffu); return c; } void writeMarker(unsigned char nMarker, unsigned char *&pData) { *pData++ = 0x0ff; *pData++ = nMarker; } void writeJFIFTag(unsigned char *&pData) { const char JFIF_TAG[] = { 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00 }; writeMarker(0x0e0, pData); writeAndAdvance(pData, sizeof(JFIF_TAG) + sizeof(unsigned short)); memcpy(pData, JFIF_TAG, sizeof(JFIF_TAG)); pData += sizeof(JFIF_TAG); } void loadJpeg(const char *input_file, unsigned char *&pJpegData, int &nInputLength) { // Load file into CPU memory ifstream stream(input_file, ifstream::binary); if (!stream.good()) { return; } stream.seekg(0, ios::end); nInputLength = (int)stream.tellg(); stream.seekg(0, ios::beg); pJpegData = new unsigned char[nInputLength] {}; stream.read(reinterpret_cast(pJpegData), nInputLength); } void readFrameHeader(const unsigned char *pData, FrameHeader &header) { readAndAdvance(pData); header.nSamplePrecision = readAndAdvance(pData); header.nHeight = readAndAdvance(pData); header.nWidth = readAndAdvance(pData); header.nComponents = readAndAdvance(pData); for (int c = 0; c(pData); header.aSamplingFactors[c] = readAndAdvance(pData); header.aQuantizationTableSelector[c] = readAndAdvance(pData); } } void writeFrameHeader(const FrameHeader &header, unsigned char *&pData) { unsigned char aTemp[128]; unsigned char *pTemp = aTemp; writeAndAdvance(pTemp, header.nSamplePrecision); writeAndAdvance(pTemp, header.nHeight); writeAndAdvance(pTemp, header.nWidth); writeAndAdvance(pTemp, header.nComponents); for (int c = 0; c(pTemp, header.aComponentIdentifier[c]); writeAndAdvance(pTemp, header.aSamplingFactors[c]); writeAndAdvance(pTemp, header.aQuantizationTableSelector[c]); } unsigned short nLength = (unsigned short)(pTemp - aTemp); writeMarker(0x0C0, pData); writeAndAdvance(pData, nLength + 2); memcpy(pData, aTemp, nLength); pData += nLength; } void readScanHeader(const unsigned char *pData, ScanHeader &header) { readAndAdvance(pData); header.nComponents = readAndAdvance(pData); for (int c = 0; c(pData); header.aHuffmanTablesSelector[c] = readAndAdvance(pData); } header.nSs = readAndAdvance(pData); header.nSe = readAndAdvance(pData); header.nA = readAndAdvance(pData); } void writeScanHeader(const ScanHeader &header, unsigned char *&pData) { unsigned char aTemp[128]; unsigned char *pTemp = aTemp; writeAndAdvance(pTemp, header.nComponents); for (int c = 0; c(pTemp, header.aComponentSelector[c]); writeAndAdvance(pTemp, header.aHuffmanTablesSelector[c]); } writeAndAdvance(pTemp, header.nSs); writeAndAdvance(pTemp, header.nSe); writeAndAdvance(pTemp, header.nA); unsigned short nLength = (unsigned short)(pTemp - aTemp); writeMarker(0x0DA, pData); writeAndAdvance(pData, nLength + 2); memcpy(pData, aTemp, nLength); pData += nLength; } void readQuantizationTables(const unsigned char *pData, QuantizationTable *pTables) { unsigned short nLength = readAndAdvance(pData) -2; while (nLength > 0) { unsigned char nPrecisionAndIdentifier = readAndAdvance(pData); int nIdentifier = nPrecisionAndIdentifier & 0x0f; pTables[nIdentifier].nPrecisionAndIdentifier = nPrecisionAndIdentifier; memcpy(pTables[nIdentifier].aTable, pData, 64); pData += 64; nLength -= 65; } } void writeQuantizationTable(const QuantizationTable &table, unsigned char *&pData) { writeMarker(0x0DB, pData); writeAndAdvance(pData, sizeof(QuantizationTable) + 2); memcpy(pData, &table, sizeof(QuantizationTable)); pData += sizeof(QuantizationTable); } void readHuffmanTables(const unsigned char *pData, HuffmanTable *pTables) { unsigned short nLength = readAndAdvance(pData) -2; while (nLength > 0) { unsigned char nClassAndIdentifier = readAndAdvance(pData); int nClass = nClassAndIdentifier >> 4; // AC or DC int nIdentifier = nClassAndIdentifier & 0x0f; int nIdx = nClass * 2 + nIdentifier; pTables[nIdx].nClassAndIdentifier = nClassAndIdentifier; // Number of Codes for Bit Lengths [1..16] int nCodeCount = 0; for (int i = 0; i < 16; ++i) { pTables[nIdx].aCodes[i] = readAndAdvance(pData); nCodeCount += pTables[nIdx].aCodes[i]; } memcpy(pTables[nIdx].aTable, pData, nCodeCount); pData += nCodeCount; nLength -= 17 + nCodeCount; } } void writeHuffmanTable(const HuffmanTable &table, unsigned char *&pData) { writeMarker(0x0C4, pData); // Number of Codes for Bit Lengths [1..16] int nCodeCount = 0; for (int i = 0; i < 16; ++i) { nCodeCount += table.aCodes[i]; } writeAndAdvance(pData, 17 + nCodeCount + 2); memcpy(pData, &table, 17 + nCodeCount); pData += 17 + nCodeCount; } void readRestartInterval(const unsigned char *pData, int &nRestartInterval) { readAndAdvance(pData); nRestartInterval = readAndAdvance(pData); } void printHelp() { cout << "jpegNPP usage" << endl; cout << " -input=srcfile.jpg (input file JPEG image)" << endl; cout << " -output=destfile.jpg (output file JPEG image)" << endl; cout << " -scale=1.0 (scale multiplier for width and height)" << endl << endl; } bool printfNPPinfo(int argc, char *argv[], int cudaVerMajor, int cudaVerMinor) { const NppLibraryVersion *libVer = nppGetLibVersion(); printf("NPP Library Version %d.%d.%d\n", libVer->major, libVer->minor, libVer->build); int driverVersion, runtimeVersion; cudaDriverGetVersion(&driverVersion); cudaRuntimeGetVersion(&runtimeVersion); printf(" CUDA Driver Version: %d.%d\n", driverVersion / 1000, (driverVersion % 100) / 10); printf(" CUDA Runtime Version: %d.%d\n", runtimeVersion / 1000, (runtimeVersion % 100) / 10); bool bVal = checkCudaCapabilities(cudaVerMajor, cudaVerMinor); return bVal; } const char *szInputFile; const char *szOutputFile; NppiSize aSrcSize[3]; Npp16s *aphDCT[3] = { 0, 0, 0 }; Npp16s *apdDCT[3] = { 0, 0, 0 }; Npp16s *apdDCT_My[3] = { 0, 0, 0 }; Npp32s aDCTStep[3]; Npp8u *apSrcImage[3] = { 0, 0, 0 }; Npp32s aSrcImageStep[3]; Npp8u *apDstImage[3] = { 0, 0, 0 }; Npp32s aDstImageStep[3]; NppiSize aDstSize[3]; HuffmanTable aHuffmanTables[4]; HuffmanTable *pHuffmanDCTables = aHuffmanTables; HuffmanTable *pHuffmanACTables = &aHuffmanTables[2]; ScanHeader oScanHeader; FrameHeader oFrameHeader; QuantizationTable aQuantizationTables[4]; Npp8u *pdQuantizationTables; NppiDCTState *pDCTState; int nMCUBlocksH = 0; int nMCUBlocksV = 0; unsigned char *pJpegData = 0; int nInputLength = 0; int DecodeJPEG() { //float nScaleFactor; szInputFile = "G:\\TestData\\人车物\\18.jpg"; cout << "Source File: " << szInputFile << endl; szOutputFile = "scaled.jpg"; cout << "Output File: " << szOutputFile << endl; /*if (checkCmdLineFlag(argc, (const char **)argv, "scale")) { nScaleFactor = max(0.0f, min(getCmdLineArgumentFloat(argc, (const char **)argv, "scale"), 1.0f)); } else { nScaleFactor = 1.0f; } cout << "Scale Factor: " << nScaleFactor << endl;*/ NPP_CHECK_NPP(nppiDCTInitAlloc(&pDCTState)); // Load Jpeg loadJpeg(szInputFile, pJpegData, nInputLength); if (pJpegData == 0) { cerr << "1. Input File Error: " << szInputFile << endl; return EXIT_FAILURE; } /*************************** * * Input * ***************************/ // Check if this is a valid JPEG file int nPos = 0; int nMarker = nextMarker(pJpegData, nPos, nInputLength); if (nMarker != 0x0D8) { cerr << "Invalid Jpeg Image" << endl; return EXIT_FAILURE; } nMarker = nextMarker(pJpegData, nPos, nInputLength); // Parsing and Huffman Decoding (on host) cudaMalloc(&pdQuantizationTables, 64 * 4); memset(&oFrameHeader, 0, sizeof(FrameHeader)); memset(aQuantizationTables, 0, 4 * sizeof(QuantizationTable)); memset(aHuffmanTables, 0, 4 * sizeof(HuffmanTable)); int nRestartInterval = -1; while (nMarker != -1) { if (nMarker == 0x0D8) { // Embedded Thumbnail, skip it int nNextMarker = nextMarker(pJpegData, nPos, nInputLength); while (nNextMarker != -1 && nNextMarker != 0x0D9) { nNextMarker = nextMarker(pJpegData, nPos, nInputLength); } } if (nMarker == 0x0DD) { readRestartInterval(pJpegData + nPos, nRestartInterval); } if ((nMarker == 0x0C0) | (nMarker == 0x0C2)) { //Assert Baseline for this Sample //Note: NPP does support progressive jpegs for both encode and decode if (nMarker != 0x0C0) { cerr << "The sample does only support baseline JPEG images" << endl; return EXIT_SUCCESS; } // Baseline or Progressive Frame Header //读取JPEG文件头 readFrameHeader(pJpegData + nPos, oFrameHeader); cout << "Image Size: " << oFrameHeader.nWidth << "x" << oFrameHeader.nHeight << "x" << static_cast(oFrameHeader.nComponents) << endl; //Assert 3-Channel Image for this Sample if (oFrameHeader.nComponents != 3) { cerr << "The sample does only support color JPEG images" << endl; return EXIT_SUCCESS; } // Compute channel sizes as stored in the JPEG (8x8 blocks & MCU block layout) for (int i = 0; i < oFrameHeader.nComponents; ++i) { nMCUBlocksV = max(nMCUBlocksV, oFrameHeader.aSamplingFactors[i] & 0x0f); //2 1 1 nMCUBlocksH = max(nMCUBlocksH, oFrameHeader.aSamplingFactors[i] >> 4); //2 1 1 } for (int i = 0; i < oFrameHeader.nComponents; ++i) { NppiSize oBlocks; NppiSize oBlocksPerMCU = { oFrameHeader.aSamplingFactors[i] >> 4, oFrameHeader.aSamplingFactors[i] & 0x0f }; //水平采样因子 和 垂直采样因子 cout << "oBlocksPerMCU Size: " << oBlocksPerMCU.width << " " << oBlocksPerMCU.height << endl; oBlocks.width = (int)ceil((oFrameHeader.nWidth + 7) / 8 * static_cast(oBlocksPerMCU.width) / nMCUBlocksH); oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width; //相除 并且 上取整 确保够所有的MCU Block的大小 oBlocks.height = (int)ceil((oFrameHeader.nHeight + 7) / 8 * static_cast(oBlocksPerMCU.height) / nMCUBlocksV); oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height; aSrcSize[i].width = oBlocks.width * 8; aSrcSize[i].height = oBlocks.height * 8; cout << "oBlock Size: " << oBlocks.width << " " << oBlocks.height << endl; // Allocate Memory size_t nPitch; //返回分配的一行的内存大小 NPP_CHECK_CUDA(cudaMallocPitch(&apdDCT[i], &nPitch, oBlocks.width * 64 * sizeof(Npp16s), oBlocks.height)); NPP_CHECK_CUDA(cudaMallocPitch(&apdDCT_My[i], &nPitch, oBlocks.width * 64 * sizeof(Npp16s), oBlocks.height)); aDCTStep[i] = static_cast(nPitch); NPP_CHECK_CUDA(cudaMallocPitch(&apSrcImage[i], &nPitch, aSrcSize[i].width, aSrcSize[i].height)); aSrcImageStep[i] = static_cast(nPitch); NPP_CHECK_CUDA(cudaHostAlloc(&aphDCT[i], aDCTStep[i] * oBlocks.height, cudaHostAllocDefault)); } } //从压缩数据中读取量化表 if (nMarker == 0x0DB) { // Quantization Tables readQuantizationTables(pJpegData + nPos, aQuantizationTables); } //从压缩数据中读取码表 熵编码表 if (nMarker == 0x0C4) { // Huffman Tables readHuffmanTables(pJpegData + nPos, aHuffmanTables); } if (nMarker == 0x0DA) { // Scan readScanHeader(pJpegData + nPos, oScanHeader); nPos += 6 + oScanHeader.nComponents * 2; int nAfterNextMarkerPos = nPos; int nAfterScanMarker = nextMarker(pJpegData, nAfterNextMarkerPos, nInputLength); if (nRestartInterval > 0) { while (nAfterScanMarker >= 0x0D0 && nAfterScanMarker <= 0x0D7) { // This is a restart marker, go on nAfterScanMarker = nextMarker(pJpegData, nAfterNextMarkerPos, nInputLength); } } NppiDecodeHuffmanSpec *apHuffmanDCTable[3]; NppiDecodeHuffmanSpec *apHuffmanACTable[3]; for (int i = 0; i < 3; ++i) { nppiDecodeHuffmanSpecInitAllocHost_JPEG(pHuffmanDCTables[(oScanHeader.aHuffmanTablesSelector[i] >> 4)].aCodes, nppiDCTable, &apHuffmanDCTable[i]); nppiDecodeHuffmanSpecInitAllocHost_JPEG(pHuffmanACTables[(oScanHeader.aHuffmanTablesSelector[i] & 0x0f)].aCodes, nppiACTable, &apHuffmanACTable[i]); } //恢复图像数据 NPP_CHECK_NPP(nppiDecodeHuffmanScanHost_JPEG_8u16s_P3R(pJpegData + nPos, nAfterNextMarkerPos - nPos - 2, nRestartInterval, oScanHeader.nSs, oScanHeader.nSe, oScanHeader.nA >> 4, oScanHeader.nA & 0x0f, aphDCT, aDCTStep, apHuffmanDCTable, apHuffmanACTable, aSrcSize)); for (int i = 0; i < 3; ++i) { nppiDecodeHuffmanSpecFreeHost_JPEG(apHuffmanDCTable[i]); nppiDecodeHuffmanSpecFreeHost_JPEG(apHuffmanACTable[i]); } } nMarker = nextMarker(pJpegData, nPos, nInputLength); } // Copy DCT coefficients and Quantization Tables from host to device for (int i = 0; i < 4; ++i) { NPP_CHECK_CUDA(cudaMemcpyAsync(pdQuantizationTables + i * 64, aQuantizationTables[i].aTable, 64, cudaMemcpyHostToDevice)); } for (int i = 0; i < 3; ++i) { cout << aDCTStep[i] << " " << aSrcSize[i].height << " " << aDCTStep[i] * aSrcSize[i].height / 8 << endl; NPP_CHECK_CUDA(cudaMemcpyAsync(apdDCT[i], aphDCT[i], aDCTStep[i] * aSrcSize[i].height / 8, cudaMemcpyHostToDevice)); } /* Inverse DCT 该函数实现了将jpeg图像 解码成 YUV数据*/ for (int i = 0; i < 3; ++i) { NPP_CHECK_NPP(nppiDCTQuantInv8x8LS_JPEG_16s8u_C1R_NEW(apdDCT[i], aDCTStep[i], apSrcImage[i], aSrcImageStep[i], pdQuantizationTables + oFrameHeader.aQuantizationTableSelector[i] * 64, aSrcSize[i], pDCTState)); } //Npp16s } int EncodeJPEG(char* SaveFileName) { /*Npp8u *apSrcImageTest[3]; for (int i = 0; i < 3; i++) { size_t nPitch; NPP_CHECK_CUDA(cudaMalloc(&apSrcImageTest[i], 1920 * 1080 * sizeof(Npp8u))); NPP_CHECK_CUDA(cudaMemcpy(apSrcImageTest[i], imgData[i], 1920 * 1080 * sizeof(Npp8u), cudaMemcpyDeviceToDevice)); } */ for (int i = 0; i < 3; i++) { NPP_CHECK_NPP(nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[i], aSrcImageStep[i], apdDCT_My[i], aDCTStep[i], pdQuantizationTables + oFrameHeader.aQuantizationTableSelector[i] * 64, aSrcSize[i], pDCTState )); } //后面的代码是关于图像编码的 /*************************** * * Processing * ***************************/ // Compute channel sizes as stored in the output JPEG (8x8 blocks & MCU block layout) /*************** 1. 求输出图像的大小********************/ NppiSize oDstImageSize; float frameWidth = floor((float)oFrameHeader.nWidth); //原图像大小 * 防缩比例 float frameHeight = floor((float)oFrameHeader.nHeight); oDstImageSize.width = (int)max(1.0f, frameWidth); oDstImageSize.height = (int)max(1.0f, frameHeight); //cout << "Output Size: " << oDstImageSize.width << "x" << oDstImageSize.height << "x" << static_cast(oFrameHeader.nComponents) << endl; /*************** 2. 求aDstSize的大小********************/ for (int i = 0; i < oFrameHeader.nComponents; ++i) //3次 { NppiSize oBlocks; NppiSize oBlocksPerMCU = { oFrameHeader.aSamplingFactors[i] & 0x0f, oFrameHeader.aSamplingFactors[i] >> 4 }; oBlocks.width = (int)ceil((oDstImageSize.width + 7) / 8 * static_cast(oBlocksPerMCU.width) / nMCUBlocksH); oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width; oBlocks.height = (int)ceil((oDstImageSize.height + 7) / 8 * static_cast(oBlocksPerMCU.height) / nMCUBlocksV); oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height; aDstSize[i].width = oBlocks.width * 8; aDstSize[i].height = oBlocks.height * 8; //cout << "***********" << aDstSize[i].width << " " << aDstSize[i].height << "***********" << endl; ////不影响保存 但是不确定能不能删除 //Allocate Memory size_t nPitch; NPP_CHECK_CUDA(cudaMallocPitch(&apDstImage[i], &nPitch, aDstSize[i].width, aDstSize[i].height)); aDstImageStep[i] = static_cast(nPitch); } /*************** 3. Huffman Encoding********************/ // Huffman Encoding Npp8u *pdScan; Npp32s nScanLength; NPP_CHECK_CUDA(cudaMalloc(&pdScan, 4 << 20)); Npp8u *pJpegEncoderTemp; Npp32s nTempSize; NPP_CHECK_NPP(nppiEncodeHuffmanGetSize(aSrcSize[0], 3, &nTempSize)); NPP_CHECK_CUDA(cudaMalloc(&pJpegEncoderTemp, nTempSize)); NppiEncodeHuffmanSpec *apHuffmanDCTable[3]; NppiEncodeHuffmanSpec *apHuffmanACTable[3]; for (int i = 0; i < 3; ++i) { nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[(oScanHeader.aHuffmanTablesSelector[i] >> 4)].aCodes, nppiDCTable, &apHuffmanDCTable[i]); nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[(oScanHeader.aHuffmanTablesSelector[i] & 0x0f)].aCodes, nppiACTable, &apHuffmanACTable[i]); } //Npp16s *apdDCT1[3] = { 0, 0, 0 }; //Huffman Encode //apdDCT = (Npp16s*)(img); NPP_CHECK_NPP(nppiEncodeHuffmanScan_JPEG_8u16s_P3R(apdDCT_My, aDCTStep, 0, oScanHeader.nSs, oScanHeader.nSe, oScanHeader.nA >> 4, oScanHeader.nA & 0x0f, pdScan, &nScanLength, apHuffmanDCTable, //在这之前申请 在这之后释放 apHuffmanACTable, //在这之前申请 在这之后释放 aDstSize, pJpegEncoderTemp)); for (int i = 0; i < 3; ++i) { nppiEncodeHuffmanSpecFree_JPEG(apHuffmanDCTable[i]); nppiEncodeHuffmanSpecFree_JPEG(apHuffmanACTable[i]); } //Write JPEG unsigned char *pDstJpeg = new unsigned char[4 << 20]{}; unsigned char *pDstOutput = pDstJpeg; oFrameHeader.nWidth = oDstImageSize.width; oFrameHeader.nHeight = oDstImageSize.height; writeMarker(0x0D8, pDstOutput); writeJFIFTag(pDstOutput); writeQuantizationTable(aQuantizationTables[0], pDstOutput); writeQuantizationTable(aQuantizationTables[1], pDstOutput); writeFrameHeader(oFrameHeader, pDstOutput); writeHuffmanTable(pHuffmanDCTables[0], pDstOutput); writeHuffmanTable(pHuffmanACTables[0], pDstOutput); writeHuffmanTable(pHuffmanDCTables[1], pDstOutput); writeHuffmanTable(pHuffmanACTables[1], pDstOutput); writeScanHeader(oScanHeader, pDstOutput); NPP_CHECK_CUDA(cudaMemcpy(pDstOutput, pdScan, nScanLength, cudaMemcpyDeviceToHost)); pDstOutput += nScanLength; writeMarker(0x0D9, pDstOutput); { // Write result to file. std::ofstream outputFile(SaveFileName, ios::out | ios::binary); outputFile.write(reinterpret_cast(pDstJpeg), static_cast(pDstOutput - pDstJpeg)); } // Cleanup cudaFree(pJpegEncoderTemp); cudaFree(pdScan); //delete[] pJpegData; delete[] pDstJpeg; /* cudaFree(pdQuantizationTables); nppiDCTFree(pDCTState); */ for (int i = 0; i < 3; ++i) { /* cudaFree(apdDCT[i]); cudaFree(apdDCT_My[i]); cudaFreeHost(aphDCT[i]); cudaFree(apSrcImage[i]);*/ cudaFree(apDstImage[i]); } return EXIT_SUCCESS; } // //int main(int argc, char **argv) //{ // // Min spec is SM 2.0 devices // if (printfNPPinfo(argc, argv, 2, 0) == false) // { // cerr << "jpegNPP requires a GPU with Compute Capability 2.0 or higher" << endl; // return EXIT_SUCCESS; // } // // const char *szInputFile; // const char *szOutputFile; // //float nScaleFactor; // // if ((argc == 1) || checkCmdLineFlag(argc, (const char **)argv, "help")) // { // printHelp(); // } // // if (checkCmdLineFlag(argc, (const char **)argv, "input")) // { // getCmdLineArgumentString(argc, (const char **)argv, "input", (char **)&szInputFile); // } // else // { // szInputFile = sdkFindFilePath("18.jpg", argv[0]); // } // // cout << "Source File: " << szInputFile << endl; // // if (checkCmdLineFlag(argc, (const char **)argv, "output")) // { // getCmdLineArgumentString(argc, (const char **)argv, "output", (char **)&szOutputFile); // } // else // { // szOutputFile = "scaled.jpg"; // } // // cout << "Output File mm: " << szOutputFile << endl; // // /*if (checkCmdLineFlag(argc, (const char **)argv, "scale")) // { // nScaleFactor = max(0.0f, min(getCmdLineArgumentFloat(argc, (const char **)argv, "scale"), 1.0f)); // } // else // { // nScaleFactor = 1.0f; // } // // cout << "Scale Factor: " << nScaleFactor << endl;*/ // // NppiDCTState *pDCTState; // NPP_CHECK_NPP(nppiDCTInitAlloc(&pDCTState)); // // unsigned char *pJpegData = 0; // int nInputLength = 0; // // // Load Jpeg // loadJpeg(szInputFile, pJpegData, nInputLength); // // if (pJpegData == 0) // { // cerr << "Input File Error: " << szInputFile << endl; // return EXIT_FAILURE; // } // // /*************************** // * // * Input // * // ***************************/ // // // // Check if this is a valid JPEG file // int nPos = 0; // int nMarker = nextMarker(pJpegData, nPos, nInputLength); // // if (nMarker != 0x0D8) // { // cerr << "Invalid Jpeg Image" << endl; // return EXIT_FAILURE; // } // // nMarker = nextMarker(pJpegData, nPos, nInputLength); // // // Parsing and Huffman Decoding (on host) // FrameHeader oFrameHeader; // QuantizationTable aQuantizationTables[4]; // Npp8u *pdQuantizationTables; // cudaMalloc(&pdQuantizationTables, 64 * 4); // // HuffmanTable aHuffmanTables[4]; // HuffmanTable *pHuffmanDCTables = aHuffmanTables; // HuffmanTable *pHuffmanACTables = &aHuffmanTables[2]; // ScanHeader oScanHeader; // memset(&oFrameHeader, 0, sizeof(FrameHeader)); // memset(aQuantizationTables, 0, 4 * sizeof(QuantizationTable)); // memset(aHuffmanTables, 0, 4 * sizeof(HuffmanTable)); // int nMCUBlocksH = 0; // int nMCUBlocksV = 0; // // int nRestartInterval = -1; // // NppiSize aSrcSize[3]; // Npp16s *aphDCT[3] = { 0, 0, 0 }; // Npp16s *apdDCT[3] = { 0, 0, 0 }; // Npp32s aDCTStep[3]; // // Npp8u *apSrcImage[3] = { 0, 0, 0 }; // Npp32s aSrcImageStep[3]; // // Npp8u *apDstImage[3] = { 0, 0, 0 }; // Npp32s aDstImageStep[3]; // NppiSize aDstSize[3]; // // while (nMarker != -1) // { // if (nMarker == 0x0D8) // { // // Embedded Thumbnail, skip it // int nNextMarker = nextMarker(pJpegData, nPos, nInputLength); // // while (nNextMarker != -1 && nNextMarker != 0x0D9) // { // nNextMarker = nextMarker(pJpegData, nPos, nInputLength); // } // } // // if (nMarker == 0x0DD) // { // readRestartInterval(pJpegData + nPos, nRestartInterval); // } // // if ((nMarker == 0x0C0) | (nMarker == 0x0C2)) // { // //Assert Baseline for this Sample // //Note: NPP does support progressive jpegs for both encode and decode // if (nMarker != 0x0C0) // { // cerr << "The sample does only support baseline JPEG images" << endl; // return EXIT_SUCCESS; // } // // // Baseline or Progressive Frame Header // readFrameHeader(pJpegData + nPos, oFrameHeader); // cout << "Image Size: " << oFrameHeader.nWidth << "x" << oFrameHeader.nHeight << "x" << static_cast(oFrameHeader.nComponents) << endl; // // //Assert 3-Channel Image for this Sample // if (oFrameHeader.nComponents != 3) // { // cerr << "The sample does only support color JPEG images" << endl; // return EXIT_SUCCESS; // } // // // Compute channel sizes as stored in the JPEG (8x8 blocks & MCU block layout) // for (int i = 0; i < oFrameHeader.nComponents; ++i) // { // nMCUBlocksV = max(nMCUBlocksV, oFrameHeader.aSamplingFactors[i] & 0x0f); // nMCUBlocksH = max(nMCUBlocksH, oFrameHeader.aSamplingFactors[i] >> 4); // } // // for (int i = 0; i < oFrameHeader.nComponents; ++i) // { // NppiSize oBlocks; // NppiSize oBlocksPerMCU = { oFrameHeader.aSamplingFactors[i] >> 4, oFrameHeader.aSamplingFactors[i] & 0x0f }; // // oBlocks.width = (int)ceil((oFrameHeader.nWidth + 7) / 8 * // static_cast(oBlocksPerMCU.width) / nMCUBlocksH); // oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width; // // oBlocks.height = (int)ceil((oFrameHeader.nHeight + 7) / 8 * // static_cast(oBlocksPerMCU.height) / nMCUBlocksV); // oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height; // // aSrcSize[i].width = oBlocks.width * 8; // aSrcSize[i].height = oBlocks.height * 8; // // // Allocate Memory // size_t nPitch; // NPP_CHECK_CUDA(cudaMallocPitch(&apdDCT[i], &nPitch, oBlocks.width * 64 * sizeof(Npp16s), oBlocks.height)); // aDCTStep[i] = static_cast(nPitch); // // NPP_CHECK_CUDA(cudaMallocPitch(&apSrcImage[i], &nPitch, aSrcSize[i].width, aSrcSize[i].height)); // aSrcImageStep[i] = static_cast(nPitch); // // NPP_CHECK_CUDA(cudaHostAlloc(&aphDCT[i], aDCTStep[i] * oBlocks.height, cudaHostAllocDefault)); // } // } // // if (nMarker == 0x0DB) // { // // Quantization Tables // readQuantizationTables(pJpegData + nPos, aQuantizationTables); // } // // if (nMarker == 0x0C4) // { // // Huffman Tables // readHuffmanTables(pJpegData + nPos, aHuffmanTables); // } // // if (nMarker == 0x0DA) // { // // Scan // readScanHeader(pJpegData + nPos, oScanHeader); // nPos += 6 + oScanHeader.nComponents * 2; // // int nAfterNextMarkerPos = nPos; // int nAfterScanMarker = nextMarker(pJpegData, nAfterNextMarkerPos, nInputLength); // // if (nRestartInterval > 0) // { // while (nAfterScanMarker >= 0x0D0 && nAfterScanMarker <= 0x0D7) // { // // This is a restart marker, go on // nAfterScanMarker = nextMarker(pJpegData, nAfterNextMarkerPos, nInputLength); // } // } // // NppiDecodeHuffmanSpec *apHuffmanDCTable[3]; // NppiDecodeHuffmanSpec *apHuffmanACTable[3]; // // for (int i = 0; i < 3; ++i) // { // nppiDecodeHuffmanSpecInitAllocHost_JPEG(pHuffmanDCTables[(oScanHeader.aHuffmanTablesSelector[i] >> 4)].aCodes, nppiDCTable, &apHuffmanDCTable[i]); // nppiDecodeHuffmanSpecInitAllocHost_JPEG(pHuffmanACTables[(oScanHeader.aHuffmanTablesSelector[i] & 0x0f)].aCodes, nppiACTable, &apHuffmanACTable[i]); // } // // NPP_CHECK_NPP(nppiDecodeHuffmanScanHost_JPEG_8u16s_P3R(pJpegData + nPos, nAfterNextMarkerPos - nPos - 2, // nRestartInterval, oScanHeader.nSs, oScanHeader.nSe, oScanHeader.nA >> 4, oScanHeader.nA & 0x0f, // aphDCT, aDCTStep, // apHuffmanDCTable, // apHuffmanACTable, // aSrcSize)); // // for (int i = 0; i < 3; ++i) // { // nppiDecodeHuffmanSpecFreeHost_JPEG(apHuffmanDCTable[i]); // nppiDecodeHuffmanSpecFreeHost_JPEG(apHuffmanACTable[i]); // } // } // // nMarker = nextMarker(pJpegData, nPos, nInputLength); // } // // // Copy DCT coefficients and Quantization Tables from host to device // for (int i = 0; i < 4; ++i) // { // NPP_CHECK_CUDA(cudaMemcpyAsync(pdQuantizationTables + i * 64, aQuantizationTables[i].aTable, 64, cudaMemcpyHostToDevice)); // } // // for (int i = 0; i < 3; ++i) // { // NPP_CHECK_CUDA(cudaMemcpyAsync(apdDCT[i], aphDCT[i], aDCTStep[i] * aSrcSize[i].height / 8, cudaMemcpyHostToDevice)); // } // // // Inverse DCT // //该函数实现了将jpeg图像 解码成 YUV数据 // //for (int i = 0; i < 3; ++i) // //{ // // NPP_CHECK_NPP(nppiDCTQuantInv8x8LS_JPEG_16s8u_C1R_NEW(apdDCT[i], aDCTStep[i], // // apSrcImage[i], aSrcImageStep[i], // // pdQuantizationTables + oFrameHeader.aQuantizationTableSelector[i] * 64, // // aSrcSize[i], // // pDCTState)); // //} // // //后面的代码是关于图像编码的 // /*************************** // * // * Processing // * // ***************************/ // // // Compute channel sizes as stored in the output JPEG (8x8 blocks & MCU block layout) // /*************** 1. 求输出图像的大小********************/ // NppiSize oDstImageSize; // float frameWidth = floor((float)oFrameHeader.nWidth); //原图像大小 * 防缩比例 // float frameHeight = floor((float)oFrameHeader.nHeight); // // oDstImageSize.width = (int)max(1.0f, frameWidth); // oDstImageSize.height = (int)max(1.0f, frameHeight); // // cout << "Output Size: " << oDstImageSize.width << "x" << oDstImageSize.height << "x" << static_cast(oFrameHeader.nComponents) << endl; // // // /*************** 2. 求aDstSize的大小********************/ // for (int i = 0; i < oFrameHeader.nComponents; ++i) //3次 // { // NppiSize oBlocks; // NppiSize oBlocksPerMCU = { oFrameHeader.aSamplingFactors[i] & 0x0f, oFrameHeader.aSamplingFactors[i] >> 4 }; // // oBlocks.width = (int)ceil((oDstImageSize.width + 7) / 8 * // static_cast(oBlocksPerMCU.width) / nMCUBlocksH); // oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width; // // oBlocks.height = (int)ceil((oDstImageSize.height + 7) / 8 * // static_cast(oBlocksPerMCU.height) / nMCUBlocksV); // oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height; // // aDstSize[i].width = oBlocks.width * 8; // aDstSize[i].height = oBlocks.height * 8; // // cout << "***********" << aDstSize[i].width << " " << aDstSize[i].height << "***********" << endl; // ////不影响保存 但是不确定能不能删除 // //Allocate Memory // /*size_t nPitch; // NPP_CHECK_CUDA(cudaMallocPitch(&apDstImage[i], &nPitch, aDstSize[i].width, aDstSize[i].height)); // aDstImageStep[i] = static_cast(nPitch);*/ // } // // /*************** 3. Huffman Encoding********************/ // // Huffman Encoding // Npp8u *pdScan; // Npp32s nScanLength; // NPP_CHECK_CUDA(cudaMalloc(&pdScan, 4 << 20)); // // Npp8u *pJpegEncoderTemp; // Npp32s nTempSize; // NPP_CHECK_NPP(nppiEncodeHuffmanGetSize(aSrcSize[0], 3, &nTempSize)); // NPP_CHECK_CUDA(cudaMalloc(&pJpegEncoderTemp, nTempSize)); // // NppiEncodeHuffmanSpec *apHuffmanDCTable[3]; // NppiEncodeHuffmanSpec *apHuffmanACTable[3]; // // for (int i = 0; i < 3; ++i) // { // nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[(oScanHeader.aHuffmanTablesSelector[i] >> 4)].aCodes, nppiDCTable, &apHuffmanDCTable[i]); // nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[(oScanHeader.aHuffmanTablesSelector[i] & 0x0f)].aCodes, nppiACTable, &apHuffmanACTable[i]); // } // // //Npp16s *apdDCT1[3] = { 0, 0, 0 }; // //Huffman Encode // NPP_CHECK_NPP(nppiEncodeHuffmanScan_JPEG_8u16s_P3R(apdDCT, aDCTStep, // 0, oScanHeader.nSs, oScanHeader.nSe, oScanHeader.nA >> 4, oScanHeader.nA & 0x0f, // pdScan, &nScanLength, // apHuffmanDCTable, //在这之前申请 在这之后释放 // apHuffmanACTable, //在这之前申请 在这之后释放 // aDstSize, // pJpegEncoderTemp)); // // for (int i = 0; i < 3; ++i) // { // nppiEncodeHuffmanSpecFree_JPEG(apHuffmanDCTable[i]); // nppiEncodeHuffmanSpecFree_JPEG(apHuffmanACTable[i]); // } // // //Write JPEG // unsigned char *pDstJpeg = new unsigned char[4 << 20]; // unsigned char *pDstOutput = pDstJpeg; // // oFrameHeader.nWidth = oDstImageSize.width; // oFrameHeader.nHeight = oDstImageSize.height; // // writeMarker(0x0D8, pDstOutput); // writeJFIFTag(pDstOutput); // writeQuantizationTable(aQuantizationTables[0], pDstOutput); // writeQuantizationTable(aQuantizationTables[1], pDstOutput); // writeFrameHeader(oFrameHeader, pDstOutput); // writeHuffmanTable(pHuffmanDCTables[0], pDstOutput); // writeHuffmanTable(pHuffmanACTables[0], pDstOutput); // writeHuffmanTable(pHuffmanDCTables[1], pDstOutput); // writeHuffmanTable(pHuffmanACTables[1], pDstOutput); // writeScanHeader(oScanHeader, pDstOutput); // NPP_CHECK_CUDA(cudaMemcpy(pDstOutput, pdScan, nScanLength, cudaMemcpyDeviceToHost)); // pDstOutput += nScanLength; // writeMarker(0x0D9, pDstOutput); // // { // // Write result to file. // std::ofstream outputFile(szOutputFile, ios::out | ios::binary); // outputFile.write(reinterpret_cast(pDstJpeg), static_cast(pDstOutput - pDstJpeg)); // } // // // Cleanup // delete[] pJpegData; // delete[] pDstJpeg; // // cudaFree(pJpegEncoderTemp); // cudaFree(pdQuantizationTables); // cudaFree(pdScan); // // nppiDCTFree(pDCTState); // // for (int i = 0; i < 3; ++i) // { // cudaFree(apdDCT[i]); // cudaFreeHost(aphDCT[i]); // cudaFree(apSrcImage[i]); // cudaFree(apDstImage[i]); // } // // return EXIT_SUCCESS; //}