初心者ですがよろしくお願いします。表題のとおりのプログラムを作成したいのですが、うまくいきません。bmpファイルの保存はできるのですが、jpgファイルに変換できず、終了コード1(0x1)が吐き出されます。以下にソースコードを示すので、アドバイス等ありましたらよろしくお願いします。
// fukumura41.cpp : コンソール アプリケーション用のエントリ ポイントの定義
//
#include "stdafx.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef __cplusplus
#define TRUE 1
#define FALSE 0
extern "C"
{
#endif
#define XMD_H
#include "jpeglib.h"
#include "jerror.h"
#ifdef __cplusplus
}
#endif
#pragma comment(lib, "libjpeg.lib")
BOOL SaveBitmapAsJpeg(LPCSTR pszFileName, HBITMAP hbm, INT quality, BOOL progression)
{
FILE *fp;
BITMAP bm;
struct jpeg_compress_struct comp;
struct jpeg_error_mgr jerr;
JSAMPLE * image_buffer;
BITMAPINFO bi;
HDC hDC, hMemDC;
LPBYTE pbBits;
INT nWidthBytes;
DWORD cbBits;
BOOL f;
if (GetObject(hbm, sizeof(BITMAP), &bm) != sizeof(BITMAP))
return FALSE;
fp = fopen(pszFileName, "wb");
if (fp == NULL)
return FALSE;
comp.err = jpeg_std_error(&jerr);
jpeg_create_compress(&comp);
jpeg_stdio_dest(&comp, fp);
comp.image_width = bm.bmWidth;
comp.image_height = bm.bmHeight;
comp.input_components = 3;
comp.in_color_space = JCS_RGB;
jpeg_set_defaults(&comp);
jpeg_set_quality(&comp, quality, TRUE);
if (progression)
jpeg_simple_progression(&comp);
jpeg_start_compress(&comp, TRUE);
ZeroMemory(&bi, sizeof(BITMAPINFOHEADER));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = bm.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
f = FALSE;
#define WIDTHBYTES(i) (((i) + 31) / 32 * 4)
nWidthBytes = WIDTHBYTES(bm.bmWidth * 24);
cbBits = nWidthBytes * bm.bmHeight;
pbBits = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, cbBits);
if (pbBits != NULL)
{
image_buffer = (JSAMPLE *)HeapAlloc(GetProcessHeap(), 0, nWidthBytes);
if (image_buffer != NULL)
{
hDC = GetDC(NULL);
if (hDC != NULL)
{
hMemDC = CreateCompatibleDC(hDC);
if (hMemDC != NULL)
{
f = GetDIBits(hMemDC, hbm, 0, bm.bmHeight, pbBits,
(BITMAPINFO*)&bi, DIB_RGB_COLORS);
DeleteDC(hMemDC);
}
ReleaseDC(NULL, hDC);
}
if (f)
{
INT x, y;
LPBYTE src, dest;
for(y = 0; y < bm.bmHeight; y++)
{
dest = image_buffer;
src = &pbBits[(bm.bmHeight - y - 1) * nWidthBytes];
for(x = 0; x < bm.bmWidth; x++)
{
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
}
jpeg_write_scanlines(&comp, &image_buffer, 1);
}
}
HeapFree(GetProcessHeap(), 0, image_buffer);
}
HeapFree(GetProcessHeap(), 0, pbBits);
}
jpeg_finish_compress(&comp);
jpeg_destroy_compress(&comp);
fclose(fp);
if (!f)
{
DeleteFile(pszFileName);
return FALSE;
}
return TRUE;
}
//#ifdef UNITTEST
HBITMAP CreateWindowBitmap(HWND hWnd)
{
HBITMAP hbmNew;
HDC hDC, hMemDC;
HGDIOBJ hbmOld;
RECT rc;
SIZE siz;
DWORD dwError;
BITMAPINFO bi;
VOID *pvBits;
GetWindowRect(hWnd, &rc);
siz.cx = rc.right - rc.left;
siz.cy = rc.bottom - rc.top;
hbmNew = NULL;
hDC = GetWindowDC(hWnd);
if (hDC != NULL)
{
hMemDC = CreateCompatibleDC(hDC);
if (hMemDC != NULL)
{
ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = siz.cx;
bi.bmiHeader.biHeight = siz.cy;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
hbmNew = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits,
NULL, 0);
if (hbmNew != NULL)
{
hbmOld = SelectObject(hMemDC, hbmNew);
BitBlt(hMemDC, 0, 0, siz.cx, siz.cy,
hDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hbmOld);
}
else
dwError = GetLastError();
DeleteDC(hMemDC);
}
else
dwError = GetLastError();
ReleaseDC(hWnd, hDC);
SetLastError(dwError);
}
return hbmNew;
}
typedef struct tagBITMAPINFOEX
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} BITMAPINFOEX, FAR * LPBITMAPINFOEX;
BOOL SaveBitmapToFile(LPCTSTR pszFileName, HBITMAP hbm)
{
BOOL f;
DWORD dwError;
BITMAPFILEHEADER bf;
BITMAPINFOEX bi;
BITMAPINFOHEADER *pbmih;
DWORD cb;
DWORD cColors, cbColors;
HDC hDC;
HANDLE hFile;
LPVOID pBits;
BITMAP bm;
if (!GetObject(hbm, sizeof(BITMAP), &bm))
return FALSE;
pbmih = &bi.bmiHeader;
ZeroMemory(pbmih, sizeof(BITMAPINFOHEADER));
pbmih->biSize = sizeof(BITMAPINFOHEADER);
pbmih->biWidth = bm.bmWidth;
pbmih->biHeight = bm.bmHeight;
pbmih->biPlanes = 1;
pbmih->biBitCount = bm.bmBitsPixel;
pbmih->biCompression = BI_RGB;
pbmih->biSizeImage = bm.bmWidthBytes * bm.bmHeight;
if (bm.bmBitsPixel < 16)
cColors = 1 << bm.bmBitsPixel;
else
cColors = 0;
cbColors = cColors * sizeof(RGBQUAD);
bf.bfType = 0x4d42;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
cb = sizeof(BITMAPFILEHEADER) + pbmih->biSize + cbColors;
bf.bfOffBits = cb;
bf.bfSize = cb + pbmih->biSizeImage;
pBits = HeapAlloc(GetProcessHeap(), 0, pbmih->biSizeImage);
if (pBits == NULL)
return FALSE;
f = FALSE;
hDC = GetDC(NULL);
if (hDC != NULL)
{
if (GetDIBits(hDC, hbm, 0, bm.bmHeight, pBits, (BITMAPINFO*)&bi,
DIB_RGB_COLORS))
{
hFile = CreateFile(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_WRITE_THROUGH, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
f = WriteFile(hFile, &bf, sizeof(BITMAPFILEHEADER), &cb, NULL) &&
WriteFile(hFile, &bi, sizeof(BITMAPINFOHEADER), &cb, NULL) &&
WriteFile(hFile, bi.bmiColors, cbColors, &cb, NULL) &&
WriteFile(hFile, pBits, pbmih->biSizeImage, &cb, NULL);
if (!f)
dwError = GetLastError();
CloseHandle(hFile);
if (!f)
DeleteFile(pszFileName);
}
else
dwError = GetLastError();
}
else
dwError = GetLastError();
ReleaseDC(NULL, hDC);
}
else
dwError = GetLastError();
HeapFree(GetProcessHeap(), 0, pBits);
SetLastError(dwError);
return f;
}
int main(int argc, char* argv[])
{
HBITMAP hbm = CreateWindowBitmap(GetDesktopWindow());
SaveBitmapToFile("Desktop.bmp", hbm);
if(hbm != NULL){
printf("succes!\n");
}
SaveBitmapAsJpeg("100%.jpg", hbm, 100, FALSE);
DeleteObject(hbm);
return 0;
}
libjpeg内のどれかの関数でexit(1)が実行されて終了しているのでしょう。
まずは、ステップ実行するなりして、どの関数で死んでいるのか調査が必要かと思われます。
ステップ実行をしたところ
HBITMAP CreateWindowBitmap(HWND hWnd)
{
HBITMAP hbmNew;
HDC hDC, hMemDC;
HGDIOBJ hbmOld;
RECT rc;
SIZE siz;
DWORD dwError;
BITMAPINFO bi;
VOID *pvBits;
GetWindowRect(hWnd, &rc);
siz.cx = rc.right - rc.left;
siz.cy = rc.bottom - rc.top;
hbmNew = NULL;
hDC = GetWindowDC(hWnd);
if (hDC != NULL)
{
hMemDC = CreateCompatibleDC(hDC);
if (hMemDC != NULL)
{
ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = siz.cx;
bi.bmiHeader.biHeight = siz.cy;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
hbmNew = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits,
NULL, 0);
if (hbmNew != NULL)
{
hbmOld = SelectObject(hMemDC, hbmNew);
BitBlt(hMemDC, 0, 0, siz.cx, siz.cy,
hDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hbmOld);
}
else
dwError = GetLastError();
DeleteDC(hMemDC);
}
else
dwError = GetLastError();
ReleaseDC(hWnd, hDC);
SetLastError(dwError);
}
return hbmNew;
}
のZeroMemoryのところでソースファイルの検索のダイアログが出ました。
これはZeroMemoryの定義がおかしいのが原因なのでしょうか?
> のZeroMemoryのところでソースファイルの検索のダイアログが出ました。
ステップイン(関数内部をステップ実行)しようとしたため、デバッガさん
が、関数内部を表示しようとして「ソースファイルのありかを教えてくれ」
といってダイアログが出ています。
ZeroMemoryは自分で作成した関数ではないでしょ。この関数にステップイン
する必要はありません。
/* エラーの原因を調べるため、自分で作成した以外の関数の内部を調べる
ことが無いわけではないですけどね。 */
ステップ実行には、
ステップイン(実行する行に関数があればその内部へ入る)
ステップオーバー(その行を実行する)
ステップアウト(現在の関数を最後まで実行して呼び出し元に戻る)
があるので、使い分ける必要があります。
デバッグについて詳しく教えていただきありがとうございました。
デバッグをした際に変数の値の変化を逐次確認したのですが、エラー等が発生していないのに上記のソースからjpgファイルができません。
どこが問題でこのようなことになっているかいまいち分かりません。
ご迷惑をおかけしますが、何かお気づきの点はないでしょうか?
連続投稿失礼します。
実行するとプロンプトに以下のような文章が出ます。
JPEG parameter struct mismatch: library thinks size is 360, caller expects 376
Press any key to continue
この文章の前半の訳は分かるのですが、どこを直せば良いか分かりません。
これについてもアドバイス等ありましたらよろしくお願いします。
> JPEG parameter struct mismatch: library thinks size is 360, caller expects 376
構造体のサイズが(libjpegが知っている情報と)違うぞ、と文句言われてる。
多分、この構造体ってのはアプリと libjpeg.lib 間でデータをやり取りするための構造体の事だと思われる。
で、libjpeg.lib側はこの構造体のサイズは 360 と認識しているが、アプリ側は 376 と言っている。
この違いはかなりヤバいぞ、って事かと。
> どこを直せば良いか分かりません。
libjpeg.lib と jpeglib.h のバージョン合ってる?
> #pragma comment(lib, "libjpeg.lib")
> #include "jpeglib.h"
libjpeg.lib は versin7 なのに、version8 の jpeglib.h を参照してるとか無い?
或いは、#ifdef 等で切り替えられるオプション関係の設定が libjpeg.lib を作成した時と
現時点とで異なってるなんて事も有り得るのかもしれないが
返答が遅くなってしまいました。申し訳ありません。
gakさんのお返事のとおりにやってみました。
IJGから再度jpeg-8bをダウンロードしてlibjpeg.lib等を作成し、上書きしてから実行したところまた同じ表示が出ました。
JPEG parameter struct mismatch: library thinks size is 416, caller expects 432
表示されている数字が変わっただけで解決には至りませんでした。
たびたびすいません。
Visual Stadio C++のIncludeフォルダとLibフォルダに作成したヘッダファイルとライブラリファイルを保存したらうまくいきました。
ご迷惑をおかけしました。
また何かあったらよろしくお願いします。