Wiki »
Nv12转jpg¶
- 示例(前后分辨率一样)
查看...查看...
#include <iostream> #include <jpeglib.h> #include <fstream> #include <cstring> bool ReadYuvFromFile(const std::string& filename, uint8_t* buffer, int size) { std::ifstream file(filename, std::ios::binary); if (!file) { return false; } file.read(reinterpret_cast<char*>(buffer), size); return file.gcount() == size; } int Nv12ToJpgFile(const char *pFileName, uint8_t* pYUVBuffer, const int nWidth, const int nHeight) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; FILE * pJpegFile = NULL; unsigned char *yuvbuf = NULL; unsigned char *ybase = NULL, *ubase = NULL; int i=0, j=0; int idx=0; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); if ((pJpegFile = fopen(pFileName, "wb")) == NULL) { return -1; } jpeg_stdio_dest(&cinfo, pJpegFile); // image width and height, in pixels cinfo.image_width = nWidth; cinfo.image_height = nHeight; cinfo.input_components = 3; // # of color components per pixel cinfo.in_color_space = JCS_YCbCr; //colorspace of input image jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 75, TRUE); cinfo.jpeg_color_space = JCS_YCbCr; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; jpeg_start_compress(&cinfo, TRUE); if(NULL == (yuvbuf=(unsigned char *)malloc(nWidth*3))) { return -1; } memset(yuvbuf, 0, nWidth*3); ybase=pYUVBuffer; ubase=pYUVBuffer+nWidth*nHeight; while (cinfo.next_scanline < cinfo.image_height) { idx=0; for(i=0;i<nWidth;i++) { yuvbuf[idx++]=ybase[i + j * nWidth]; yuvbuf[idx++]=ubase[j/2 * nWidth+(i/2)*2]; yuvbuf[idx++]=ubase[j/2 * nWidth+(i/2)*2+1]; } row_pointer[0] = yuvbuf; jpeg_write_scanlines(&cinfo, row_pointer, 1); j++; } jpeg_finish_compress( &cinfo); jpeg_destroy_compress(&cinfo); fclose(pJpegFile); return 0; } bool Nv12ToJpg(const uint8_t* pYUVBuffer, const int nWidth, const int nHeight, std::string& sJpeg) { if (!pYUVBuffer) { return false; } struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); size_t outSize = 0; uint8_t *buffer = NULL; jpeg_mem_dest(&cinfo, &buffer, &outSize); cinfo.image_width = nWidth; cinfo.image_height = nHeight; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 75, TRUE); cinfo.jpeg_color_space = JCS_YCbCr; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; jpeg_start_compress(&cinfo, TRUE); int rowStride = nWidth * 3; JSAMPROW rowPointer = new uint8_t[rowStride](); if(NULL == rowPointer) { return false; } int j = 0; int idx = 0; const uint8_t *ybase = pYUVBuffer; const uint8_t *ubase = pYUVBuffer + nWidth * nHeight; while (cinfo.next_scanline < cinfo.image_height) { idx=0; for(int i=0;i<nWidth;i++) { rowPointer[idx++] = ybase[i + j * nWidth]; rowPointer[idx++] = ubase[j/2 * nWidth+(i/2)*2]; rowPointer[idx++] = ubase[j/2 * nWidth+(i/2)*2+1]; } jpeg_write_scanlines(&cinfo, &rowPointer, 1); ++j; } jpeg_finish_compress(&cinfo); std::string output(reinterpret_cast<char*>(buffer), outSize); jpeg_destroy_compress(&cinfo); if(buffer != NULL) { delete[] buffer; } if(rowPointer != NULL) { delete[] rowPointer; } sJpeg.swap(output); return true; } int main() { const int width = 1280; const int height = 720; uint8_t* yuvImage = new uint8_t[width * height * 3 / 2]; std::string jpegOutput; int size = width * height * 3 / 2; if (!ReadYuvFromFile("in.yuv", yuvImage, width * height * 3 / 2)) { std::cout << "Failed to read YUV file." << std::endl; delete[] yuvImage; // 释放内存 return -1; } // Nv12ToJpgFile("out1.jpg", yuvImage, width, height); if (Nv12ToJpg(yuvImage, width, height, jpegOutput)) { std::ofstream outFile("out.jpg", std::ios::binary); outFile.write(jpegOutput.data(), jpegOutput.size()); std::cout << "JPEG length: " << jpegOutput.size() << " bytes" << std::endl; } else { std::cout << "JPEG failed." << std::endl; } delete[] yuvImage; // 释放内存 return 0; }
- 示例(前后分辨率不一样)
查看...查看...
bool CHttpClient::Nv12ToJpg(const uint8_t* pYUVBuffer, int nWidth, int nHeight, int nDstWidth, int nDstHeight, std::string& sJpeg) { if (!pYUVBuffer) { return false; } struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); size_t outSize = 0; uint8_t *buffer = NULL; jpeg_mem_dest(&cinfo, &buffer, &outSize); cinfo.image_width = nDstWidth; cinfo.image_height = nDstHeight; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 75, TRUE); cinfo.jpeg_color_space = JCS_YCbCr; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; jpeg_start_compress(&cinfo, TRUE); int rowStride = nWidth * 3; JSAMPROW rowPointer = new uint8_t[rowStride](); if(NULL == rowPointer) { return false; } int j = 0; int idx = 0; const uint8_t *ybase = pYUVBuffer; const uint8_t *ubase = pYUVBuffer + nWidth * nHeight; while (cinfo.next_scanline < cinfo.image_height) { idx=0; for(int i=0;i<nWidth;i++) { rowPointer[idx++] = ybase[i + j * nWidth]; rowPointer[idx++] = ubase[j/2 * nWidth+(i/2)*2]; rowPointer[idx++] = ubase[j/2 * nWidth+(i/2)*2+1]; } jpeg_write_scanlines(&cinfo, &rowPointer, 1); ++j; } jpeg_finish_compress(&cinfo); std::string output(reinterpret_cast<char*>(buffer), outSize); jpeg_destroy_compress(&cinfo); if(buffer != NULL) { delete[] buffer; } if(rowPointer != NULL) { delete[] rowPointer; } sJpeg.swap(output); return true; }
- 编译命令
g++ test.cpp -o test -ljpeg g++ test.cpp -o test -lturbojpeg(turbojpeg更快)