Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.04.2015, 01:22   #1
Malriser
xor esp, esp
Форумчанин
 
Регистрация: 11.02.2014
Сообщений: 135
По умолчанию Проблема с JPG скрином C++ используя gdi+

Всем привет. Не пойму где ошибка, не сохраняет файл и все. Уже и в дебаггере студии посмотрел, и в OllyDbg ( все функции возвращают ERROR_SUCCESS ).

Код:
#include <windows.h>
#include <gdiplus.h>

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:main")
#pragma comment(lib, "gdiplus.lib")

using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
	UINT  num = 0;          
	UINT  size = 0;  

	ImageCodecInfo* pImageCodecInfo = NULL;

	
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	GetImageEncodersSize(&num, &size);
	if (size == 0)
	{
		GdiplusShutdown(gdiplusToken);
		return -1;
	}
	pImageCodecInfo = (ImageCodecInfo*)(VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
	if (pImageCodecInfo == NULL)
	{
		GdiplusShutdown(gdiplusToken);
		return -1;
	}
	GetImageEncoders(num, size, pImageCodecInfo);

	for (UINT j = 0; j < num; ++j)
	{
		if (lstrcmpW(pImageCodecInfo[j].MimeType, format) == 0)
		{
			*pClsid = pImageCodecInfo[j].Clsid;
			VirtualFree(pImageCodecInfo, 0, MEM_RELEASE);
			GdiplusShutdown(gdiplusToken);
			return j;  
		}
	}

	VirtualFree(pImageCodecInfo, 0, MEM_RELEASE);
	GdiplusShutdown(gdiplusToken);
	return -1;  
}

int SaveJpeg(HBITMAP hBmp, LPCWSTR lpszFilename, ULONG uQuality)
{
	ULONG *pBitmap = NULL;
	CLSID imageCLSID;
	EncoderParameters encoderParams;
	int iRes = 0;
	
	HMODULE hModuleThread = LoadLibraryA("gdiplus.dll");
	if (hModuleThread == 0)
		return 0;

	typedef Status(WINAPI *pGdipCreateBitmapFromHBITMAP)(HBITMAP, HPALETTE, ULONG**);
	pGdipCreateBitmapFromHBITMAP lGdipCreateBitmapFromHBITMAP;

	typedef Status(WINAPI *pGdipSaveImageToFile)(ULONG *, const WCHAR*, const CLSID*, const EncoderParameters*);
	pGdipSaveImageToFile lGdipSaveImageToFile;

	lGdipCreateBitmapFromHBITMAP = (pGdipCreateBitmapFromHBITMAP)GetProcAddress(hModuleThread, "GdipCreateBitmapFromHBITMAP");
	if (lGdipCreateBitmapFromHBITMAP == NULL)
		return 0;

	lGdipSaveImageToFile = (pGdipSaveImageToFile)GetProcAddress(hModuleThread, "GdipSaveImageToFile");
	if (lGdipSaveImageToFile == NULL)
		return 0;

	lGdipCreateBitmapFromHBITMAP(hBmp, NULL, &pBitmap);

	iRes = GetEncoderClsid(L"image/jpeg", &imageCLSID);
	if (iRes == -1)
		return 0;
	encoderParams.Count = 1;
	encoderParams.Parameter[0].NumberOfValues = 1;
	encoderParams.Parameter[0].Guid = EncoderQuality;
	encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
	encoderParams.Parameter[0].Value = &uQuality;

	lGdipSaveImageToFile(pBitmap, lpszFilename, &imageCLSID, &encoderParams);

	return 1;
}

void Screen()
{

	HDC hScreenDC = CreateDC("DISPLAY", 0, 0, 0);
	
	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);

	int x = GetDeviceCaps(hScreenDC, HORZRES);
	int y = GetDeviceCaps(hScreenDC, VERTRES);


	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);

	HBITMAP hOldBitmap = reinterpret_cast<HBITMAP>(SelectObject(hMemoryDC, hBitmap));

	BitBlt(hMemoryDC, 0, 0, x, y, hScreenDC, 0, 0, SRCCOPY);
	hBitmap = reinterpret_cast<HBITMAP>(SelectObject(hMemoryDC, hOldBitmap));

	DeleteDC(hMemoryDC);
	DeleteDC(hScreenDC);

	SaveJpeg(hBitmap, L"C:\\test\\test.jpeg", 640);

}

int main()
{
	Screen();
	
	ExitProcess(0);
}
P.S. Если у вас есть более простой и работающий пример - не откажусь. Главное - это WinApi.

Последний раз редактировалось Malriser; 17.04.2015 в 01:24.
Malriser вне форума Ответить с цитированием
Старый 17.04.2015, 07:11   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
все функции возвращают ERROR_SUCCESS
Прям так все? Ай-яй-яй. Лукавишь ведь.
А где проверка работы lGdipCreateBitmapFromHBITMAP и lGdipSaveImageToFile?
Давай топай сюда: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
Потом ставь if()-ы на эти функции и получай код ошибки.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 17.04.2015, 13:12   #3
Malriser
xor esp, esp
Форумчанин
 
Регистрация: 11.02.2014
Сообщений: 135
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Прям так все? Ай-яй-яй. Лукавишь ведь.
А где проверка работы lGdipCreateBitmapFromHBITMAP и lGdipSaveImageToFile?
Давай топай сюда: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
Потом ставь if()-ы на эти функции и получай код ошибки.
Я что, врать буду? Мне же надо. Я смотрел в OllyDbg (https://ru.wikipedia.org/wiki/OllyDbg) всю работу. Возвращают, действительно, все, что меня и удивило.

За наставления спасибо, попробую.

Попробовал метод Save. Честно, не люблю ООП, не переношу.

Посмотрите, забавно, во что компилируется это:

Все также, возвращает ERROR_SUCCESS, файл не сохраняет. Может собака в чем-то другом зарыта?

P.S. Графика и ООП - это мое самое слабое место...

P.P.S. image->Save(L"C:\\test\\Mosaic2.jpg", &imageCLSID, &encoderParams); - так тоже не работает

P.P.P.S. Сразу поясню, зачем я VirtualAlloc припихнул. При обычном объявлении ( Image image); эта хрень требует, что было как в примере майкрософтовском: Image image(L"myImage.jpg");

А у меня вообще никакого исходного файла нет, получаю скрин в bitmap так, вот и думаю, может собака зарыта в функции Screen?

Код:

void Screen()
{

	HDC hScreenDC = CreateDC("DISPLAY", 0, 0, 0);
	
	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);

	int x = GetDeviceCaps(hScreenDC, HORZRES);
	int y = GetDeviceCaps(hScreenDC, VERTRES);


	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);

	HBITMAP hOldBitmap = reinterpret_cast<HBITMAP>(SelectObject(hMemoryDC, hBitmap));

	BitBlt(hMemoryDC, 0, 0, x, y, hScreenDC, 0, 0, SRCCOPY);
	hBitmap = reinterpret_cast<HBITMAP>(SelectObject(hMemoryDC, hOldBitmap));

	DeleteDC(hMemoryDC);
	DeleteDC(hScreenDC);

	SaveJpeg(hBitmap, L"C:\\test\\test.jpeg", 640);

}

Последний раз редактировалось Malriser; 17.04.2015 в 13:39.
Malriser вне форума Ответить с цитированием
Старый 17.04.2015, 13:33   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

И тем не менее не хватает, как видишь, двух обработчиков ошибок )
Врал - не врал, тут уже по барабану.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 17.04.2015, 13:41   #5
Malriser
xor esp, esp
Форумчанин
 
Регистрация: 11.02.2014
Сообщений: 135
По умолчанию

Ура! Разобрался, вот готовое решение:

Код:
#include <windows.h>
#include <gdiplus.h>

#pragma comment(lib, "gdiplus.lib")

using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
	UINT  num = 0;          
	UINT  size = 0;  

	ImageCodecInfo* pImageCodecInfo = NULL;

	GetImageEncodersSize(&num, &size);
	if (size == 0)
	{
		return -1;
	}
	pImageCodecInfo = (ImageCodecInfo*)(VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
	if (pImageCodecInfo == NULL)
	{
		return -1;
	}
	GetImageEncoders(num, size, pImageCodecInfo);

	for (UINT j = 0; j < num; ++j)
	{
		if (lstrcmpW(pImageCodecInfo[j].MimeType, format) == 0)
		{
			*pClsid = pImageCodecInfo[j].Clsid;
			VirtualFree(pImageCodecInfo, 0, MEM_RELEASE);
			return j;  
		}
	}

	VirtualFree(pImageCodecInfo, 0, MEM_RELEASE);
	return -1;  
}

int SaveJpeg(HBITMAP hBmp, LPCWSTR lpszFilename, ULONG uQuality)
{
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
	
	ULONG *pBitmap = NULL;
	CLSID imageCLSID;
	EncoderParameters encoderParams;
	int iRes = 0;
	
	HMODULE hModuleThread = LoadLibraryA("gdiplus.dll");
	if (hModuleThread == 0)
		return 0;

	typedef Status(WINAPI *pGdipCreateBitmapFromHBITMAP)(HBITMAP, HPALETTE, ULONG**);
	pGdipCreateBitmapFromHBITMAP lGdipCreateBitmapFromHBITMAP;

	typedef Status(WINAPI *pGdipSaveImageToFile)(ULONG *, const WCHAR*, const CLSID*, const EncoderParameters*);
	pGdipSaveImageToFile lGdipSaveImageToFile;

	lGdipCreateBitmapFromHBITMAP = (pGdipCreateBitmapFromHBITMAP)GetProcAddress(hModuleThread, "GdipCreateBitmapFromHBITMAP");
	if (lGdipCreateBitmapFromHBITMAP == NULL)
		return 0;

	lGdipSaveImageToFile = (pGdipSaveImageToFile)GetProcAddress(hModuleThread, "GdipSaveImageToFile");
	if (lGdipSaveImageToFile == NULL)
		return 0;

	lGdipCreateBitmapFromHBITMAP(hBmp, NULL, &pBitmap);

	iRes = GetEncoderClsid(L"image/jpeg", &imageCLSID);
	int good;
	if (iRes != -1)
	{
		good = 1;
		encoderParams.Count = 1;
		encoderParams.Parameter[0].NumberOfValues = 1;
		encoderParams.Parameter[0].Guid = EncoderQuality;
		encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
		encoderParams.Parameter[0].Value = &uQuality;


		lGdipSaveImageToFile(pBitmap, lpszFilename, &imageCLSID, &encoderParams);
	}
	else  good = 0;
	GdiplusShutdown(gdiplusToken);

	return good;
}

int Screen(LPWSTR PATH)
{

	HDC hScreenDC = CreateDC("DISPLAY", 0, 0, 0);
	
	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);

	int x = GetDeviceCaps(hScreenDC, HORZRES);
	int y = GetDeviceCaps(hScreenDC, VERTRES);


	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);

	HBITMAP hOldBitmap = reinterpret_cast<HBITMAP>(SelectObject(hMemoryDC, hBitmap));

	BitBlt(hMemoryDC, 0, 0, x, y, hScreenDC, 0, 0, SRCCOPY);
	hBitmap = reinterpret_cast<HBITMAP>(SelectObject(hMemoryDC, hOldBitmap));

	DeleteDC(hMemoryDC);
	DeleteDC(hScreenDC);

	return SaveJpeg(hBitmap, PATH, 640);

}
Вызывать так:

Код:
Screen(L"C:\\test\\file.jpeg");
Если скрин сохранился, то вернет 1, иначе 0.

P.S. Строка в кодировке UNICODE.

P.P.S. Пол кода с msdn, но переписал так, чтобы не юзал msvcrt

Последний раз редактировалось Malriser; 17.04.2015 в 13:45.
Malriser вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
GDI\GDI+\Photoshop - как добиться прозрачности пикселей определенного цвета? STRELOK-2007 Мультимедиа в Delphi 12 11.01.2014 13:37
Перемещая папки с экзел файлом и jpg картинками, ссылки на jpg не работают?? Igorilla Microsoft Office Excel 0 16.03.2013 21:36
Mini Foto Redactor (Dev C++ WinAPI GDI+ Convert JPG to BMP and back) kachkarvv Софт 12 09.08.2012 10:26
Проблема с GDI... VintProg Общие вопросы Delphi 1 07.09.2011 17:17
JPG в базе Access, используя Delphi??? $T@LKER БД в Delphi 3 30.08.2010 08:37