//----------------------------------------------------------------------------- // BugDlg_CompressScreenshot // // Compress .BMP to .JPG, Delete .BMP //----------------------------------------------------------------------------- bool BugDlg_CompressScreenshot() { if ( !g_bug_szScreenshot[0] ) { return false; } bool bSuccess = false; HBITMAP hBitmap = NULL; HDC hDC = NULL; char *pBMPBits = NULL; CUtlBuffer buf( 0, 0 ); hBitmap = (HBITMAP)LoadImage( NULL, g_bug_szScreenshot, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE ); if ( !hBitmap ) goto cleanUp; hDC = CreateCompatibleDC( NULL ); if ( !hDC ) goto cleanUp; BITMAPINFO bitmapInfo; ZeroMemory( &bitmapInfo, sizeof( BITMAPINFO ) ); bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); // populate the bmp info if ( !GetDIBits( hDC, hBitmap, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS ) ) goto cleanUp; pBMPBits = (char *)Sys_Alloc( bitmapInfo.bmiHeader.biSizeImage ); if ( !pBMPBits ) goto cleanUp; // could be bottom-up or top-down int nHeight = abs( bitmapInfo.bmiHeader.biHeight ); if ( bitmapInfo.bmiHeader.biBitCount != 32 ) { // unexpected format goto cleanUp; } if ( bitmapInfo.bmiHeader.biCompression != BI_RGB && bitmapInfo.bmiHeader.biCompression != BI_BITFIELDS ) { // unexpected format goto cleanUp; } // don't want color masks bitmapInfo.bmiHeader.biCompression = BI_RGB; // get the raw bits if ( !GetDIBits( hDC, hBitmap, 0, nHeight, pBMPBits, &bitmapInfo, DIB_RGB_COLORS ) ) goto cleanUp; JSAMPROW row_pointer[1]; // compression data structure struct jpeg_compress_struct cinfo; ZeroMemory( &cinfo, sizeof( jpeg_compress_struct ) ); // point at stderr struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error( &jerr ); // create compressor jpeg_create_compress( &cinfo ); // Hook CUtlBuffer to compression jpeg_UtlBuffer_dest( &cinfo, &buf ); // image width and height, in pixels cinfo.image_width = bitmapInfo.bmiHeader.biWidth; cinfo.image_height = nHeight; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; // Apply settings jpeg_set_defaults( &cinfo ); jpeg_set_quality( &cinfo, 50, TRUE ); // Start compressor jpeg_start_compress( &cinfo, TRUE); char *pRowBuffer = (char*)_alloca( bitmapInfo.bmiHeader.biWidth * 3 ); row_pointer[0] = (JSAMPROW)pRowBuffer; // Write scanlines while ( cinfo.next_scanline < cinfo.image_height ) { char *pSrc; if ( bitmapInfo.bmiHeader.biHeight < 0 ) { // top down pSrc = &pBMPBits[cinfo.next_scanline * bitmapInfo.bmiHeader.biWidth * 4]; } else { // bottom up pSrc = &pBMPBits[(nHeight-1 - cinfo.next_scanline) * bitmapInfo.bmiHeader.biWidth * 4]; } // convert to BGR to RGB char *pDst = pRowBuffer; for ( int i=0; i<bitmapInfo.bmiHeader.biWidth; i++ ) { pDst[0] = pSrc[2]; pDst[1] = pSrc[1]; pDst[2] = pSrc[0]; pSrc += 4; pDst += 3; } jpeg_write_scanlines( &cinfo, row_pointer, 1 ); } // Finalize image jpeg_finish_compress( &cinfo ); char jpgFilename[MAX_PATH]; Sys_StripExtension( g_bug_szScreenshot, jpgFilename, sizeof( jpgFilename ) ); Sys_AddExtension( ".jpg", jpgFilename, sizeof( jpgFilename ) ); if ( !Sys_SaveFile( jpgFilename, buf.Base(), buf.TellMaxPut() ) ) goto cleanUp; // remove the uncompressed version unlink( g_bug_szScreenshot ); strcpy( g_bug_szScreenshot, jpgFilename ); bSuccess = true; cleanUp: if ( hBitmap ) DeleteObject( hBitmap ); if ( hDC ) DeleteDC( hDC ); if ( pBMPBits ) Sys_Free( pBMPBits ); return bSuccess; }
void VTFHandler_ConvertImageToJPG( CUtlBuffer &buf, unsigned char *imageData, uint32 width, uint32 height ) { int quality = 100; JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] int row_stride; // physical row width in image buffer // stderr handler struct jpeg_error_mgr jerr; // compression data structure struct jpeg_compress_struct cinfo; row_stride = width * 3; // JSAMPLEs per row in image_buffer // point at stderr cinfo.err = jpeg_std_error(&jerr); // create compressor jpeg_create_compress(&cinfo); // Hook CUtlBuffer to compression jpeg_UtlBuffer_dest(&cinfo, &buf); // image width and height, in pixels cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; // Apply settings jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); // Start compressor jpeg_start_compress(&cinfo, TRUE); // Write scanlines while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = &imageData[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } // Finalize image jpeg_finish_compress(&cinfo); // Cleanup jpeg_destroy_compress(&cinfo); }