bool CJpegEncoder::Encode(const BYTE* dib) { m_bbuff = m_bwidth = 0; BITMAPINFO* bi = (BITMAPINFO*)dib; int bpp = bi->bmiHeader.biBitCount; if(bpp != 16 && bpp != 24 && bpp != 32) // 16 & 24 not tested!!! there may be some alignment problems when the row size is not 4*something in bytes return false; m_w = bi->bmiHeader.biWidth; m_h = abs(bi->bmiHeader.biHeight); m_p = new BYTE[m_w*m_h*4]; const BYTE* src = dib + sizeof(bi->bmiHeader); if(bi->bmiHeader.biBitCount <= 8) { if(bi->bmiHeader.biClrUsed) src += bi->bmiHeader.biClrUsed * sizeof(bi->bmiColors[0]); else src += (1 << bi->bmiHeader.biBitCount) * sizeof(bi->bmiColors[0]); } int srcpitch = m_w*(bpp>>3); int dstpitch = m_w*4; BitBltFromRGBToRGB( m_w, m_h, m_p, dstpitch, 32, (BYTE*)src + srcpitch*(m_h-1), -srcpitch, bpp); BYTE* p = m_p; for(BYTE* e = p + m_h*dstpitch; p < e; p += 4) { int r = p[2], g = p[1], b = p[0]; p[0] = (BYTE)min(max(0.2990*r+0.5870*g+0.1140*b, 0), 255) - 128; p[1] = (BYTE)min(max(-0.1687*r-0.3313*g+0.5000*b + 128, 0), 255) - 128; p[2] = (BYTE)min(max(0.5000*r-0.4187*g-0.0813*b + 128, 0), 255) - 128; } if(quanttbl[0][0] == 16) { for(int i = 0; i < countof(quanttbl); i++) for(int j = 0; j < countof(quanttbl[0]); j++) quanttbl[i][j] >>= 2; // the default quantization table contains a little too large values } WriteSOI(); WriteDQT(); WriteSOF0(); WriteDHT(); WriteSOS(); WriteEOI(); delete [] m_p; return true; }
///////////////////////////////////////////////////////////////////////////// // Convert YUV411 to JPEG photo file static int YUV2Jpg(PBYTE in_Y,PBYTE in_U,PBYTE in_V,int width,int height,int quality,int nStride,PBYTE pOut,DWORD *pnOutSize) { PBYTE pYBuf,pUBuf,pVBuf; int nYLen = nStride * height; int nUVLen = nStride * height / 4; int nDataLen; JPEGINFO JpgInfo; memset(&JpgInfo, 0, sizeof(JPEGINFO)); JpgInfo.bytenew = 0; JpgInfo.bytepos = 7; pYBuf = (PBYTE)malloc(nYLen); memcpy(pYBuf,in_Y,nYLen); pUBuf = (PBYTE)malloc(nYLen); pVBuf = (PBYTE)malloc(nYLen); ProcessUV(pUBuf,in_U,width,height,nStride); ProcessUV(pVBuf,in_V,width,height,nStride); // GetDataFromSource(pYBuf,pUBuf,pVBuf,in_Y,in_U,in_V,width); DivBuff(pYBuf,width,height,nStride,DCTSIZE,DCTSIZE); DivBuff(pUBuf,width,height,nStride,DCTSIZE,DCTSIZE); DivBuff(pVBuf,width,height,nStride,DCTSIZE,DCTSIZE); quality = QualityScaling(quality); SetQuantTable(std_Y_QT,JpgInfo.YQT, quality); // 设置Y量化表 SetQuantTable(std_UV_QT,JpgInfo.UVQT,quality); // 设置UV量化表 InitQTForAANDCT(&JpgInfo); // 初始化AA&N需要的量化表 JpgInfo.pVLITAB=JpgInfo.VLI_TAB + 2048; // 设置VLI_TAB的别名 BuildVLITable(&JpgInfo); // 计算VLI表 nDataLen = 0; // 写入各段 nDataLen = WriteSOI(pOut,nDataLen); nDataLen = WriteAPP0(pOut,nDataLen); nDataLen = WriteDQT(&JpgInfo,pOut,nDataLen); nDataLen = WriteSOF(pOut,nDataLen,width,height); nDataLen = WriteDHT(pOut,nDataLen); nDataLen = WriteSOS(pOut,nDataLen); // 计算Y/UV信号的交直分量的huffman表,这里使用标准的huffman表,并不是计算得出,缺点是文件略长,但是速度快 BuildSTDHuffTab(STD_DC_Y_NRCODES,STD_DC_Y_VALUES,JpgInfo.STD_DC_Y_HT); BuildSTDHuffTab(STD_AC_Y_NRCODES,STD_AC_Y_VALUES,JpgInfo.STD_AC_Y_HT); BuildSTDHuffTab(STD_DC_UV_NRCODES,STD_DC_UV_VALUES,JpgInfo.STD_DC_UV_HT); BuildSTDHuffTab(STD_AC_UV_NRCODES,STD_AC_UV_VALUES,JpgInfo.STD_AC_UV_HT); // 处理单元数据 nDataLen = ProcessData(&JpgInfo,pYBuf,pUBuf,pVBuf,width,height,pOut,nDataLen); nDataLen = WriteEOI(pOut,nDataLen); free(pYBuf); free(pUBuf); free(pVBuf); *pnOutSize = nDataLen; return 0; }