使用libjpeg實現windows截圖保存成jpeg文件【看這一篇就好啦】

工程中有個需求是要求在windows平臺下截圖某一個窗口,並實現保存成jpeg,實現功能大概是:
1.查找窗口
2.截圖得到bitmap數據
3.把bitmap數據保存成jpeg文件
其中bitmap數據保存成jpeg文件這裏使用libjpeg來實現,這裏記錄下編譯和使用時遇到的一些坑,首先要下載源碼進行編譯

1、下載源代碼下載地址:http://www.ijg.org/files/,

選擇最新版本的windows版本壓縮包,進行下載。

2、然後開始編譯,這裏環境是用vs2019,windows 10 64位編譯:

  • 2.1.修改文件名jconfig.vc爲jconfig.h
  • 2.2.在開始菜單中打到x64 Native Tools Command Prompt For VS 2019並打開,然後進入目錄輸入命令:
    nmake -f makefile.vc libjpeg.lib
    有可能編譯會失敗,提示找不到Win32.mak,這是編譯環境裏找不到這個文件,這個文件一般是在安裝的vs的c++編譯環境中自帶的,如果沒有可以下載一個,這裏已經文件下載到本地了

3、使用

libjpeg.lib是用c語言開發的,
如果在C++程序裏使用,需要用extern “C” { }包含一下。
相關頭文件:
extern “C”
{
#include “jpeglib.h”
}
cpp文件中引用編譯好的文件:
#pragma comment(lib, "libjpeg/jpeg.lib")

貼出實現bitmap像素保存jpeg函數源碼:

//===================================================================================
//function:       jpeg壓縮
//input:          1:生成的文件名,2:bmp的指針,3:位圖寬度,4:位圖高度,5:顏色深度
//return:         int
//description:    bmp的像素格式爲(RGB)
//===================================================================================
int savejpeg(const char* filename, unsigned char* bits, int width, int height, int depth)
{
	//RGB順序調整,這裏很重要,因爲傳進來的像素數組是使用CreateDIBSettion分配的,它的順序是BGR,不是RGB,而jpeg文件是RGB,所以需要進行順序調整,否則會出現紅色變成藍色,這個網上很多文章都沒說到,不瞭解的小白肯定會遇到這個問題!
	/*順便普及知識
	2.DIB注意點:
        <1>DIB位圖每行數據必須是32bit(4個字節)的整數倍,如果圖像數據爲Byte型(0~255),即每個像素爲一個字節(8bit),這樣圖      像每行的寬必須是4的整數倍,不足4的整數倍的部分,以0補充。
    
        <2>DIB數據存儲順序是:自左到右,自下到上,逆序存儲。即:圖像的第一行數據,存在DIB數據部分最後一行,最後一行存在第一行    ,因爲顯示的時候,DIB位圖是,自下而上顯示的,即讀取的第一行數據,會顯示在界面的最後一行,然後,第二行顯示在界面倒數第    二行。
		<3>調色板順序爲BGR而不是RGB。
	*/
	unsigned char buf = 0;
	unsigned char* tmp = bits;//image_buffer = tmp = (unsigned char*)map + m_buf.offsets[frame];
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++)
		{
			buf = *tmp;
			*tmp = *(tmp + 2);
			*(tmp + 2) = buf;
			tmp += 3;
		}
	}
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	FILE* outfile;                 //target file 
	JSAMPROW row_pointer[1];        //pointer to JSAMPLE row[s] 
	int     row_stride;             //physical row width in image buffer 
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);

	if (0 != fopen_s(&outfile, filename, "wb"))
	{
		fprintf(stderr, "can't open %s/n", filename);
		return -1;
	}
	jpeg_stdio_dest(&cinfo, outfile);
	cinfo.image_width = width;      //image width and height, in pixels 
	cinfo.image_height = height;
	cinfo.input_components = 3;         //# of color components per pixel 
	cinfo.in_color_space = JCS_RGB;         //colorspace of input image 
	  //// 指定亮度及色度質量
	cinfo.q_scale_factor[0] = jpeg_quality_scaling(100);
	cinfo.q_scale_factor[1] = jpeg_quality_scaling(100);

	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE);//limit to baseline-JPEG values 
	jpeg_start_compress(&cinfo, TRUE);

	row_stride = width * depth; // JSAMPLEs per row in image_buffer 
	while (cinfo.next_scanline < cinfo.image_height)
	{
		//由於jpg文件的圖像是倒的,改一下讀的順序,這個參考網上的一段源碼
		//這是原代碼:
		//row_pointer[0] = & bits[cinfo.next_scanline * row_stride];
		row_pointer[0] = &bits[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride];
		(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	jpeg_finish_compress(&cinfo);
	fclose(outfile);
	jpeg_destroy_compress(&cinfo);
	return 0;
}

順便貼一下截圖代碼:

int captureRenderProgressWindow(HWND hwnd, LPCSTR filePath)
{
	HDC     hDC;
	HDC     MemDC;
	BYTE* Data;
	HBITMAP   hBmp;
	BITMAPINFO   bi;

	RECT rtClientWnd;
	::GetClientRect(hwnd, &rtClientWnd);
	int width = rtClientWnd.right - rtClientWnd.left;
	int height = rtClientWnd.bottom - rtClientWnd.top;

	memset(&bi, 0, sizeof(bi));
	bi.bmiHeader.biSize = sizeof(BITMAPINFO);
	bi.bmiHeader.biWidth = width;
	bi.bmiHeader.biHeight = height;
	bi.bmiHeader.biPlanes = 1;
	bi.bmiHeader.biBitCount = 24;

	hDC = GetWindowDC(hwnd);
	MemDC = CreateCompatibleDC(hDC);
	//創建位圖
	hBmp = CreateDIBSection(MemDC, &bi, DIB_RGB_COLORS, (void**)& Data, NULL, 0);
	SelectObject(MemDC, hBmp);
	BitBlt(MemDC, 0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, hDC, 0, 0, SRCCOPY);
	//int result = SaveBitmapToFile(hBmp, filePath);
	// 保存
	int result = savejpeg(filePath, Data, width, height, 3);
	//int result = colorBitmap(hBmp);
	ReleaseDC(NULL, hDC);
	DeleteDC(MemDC);
	DeleteObject(hBmp);
	return result;
}

libjpeg源碼已經配好win32.mak編譯有問題的可以看下一下這個庫,libjpeg已經把win32.mak文件加上,且已經編譯好一個libjpeg.lib的64位版本

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章