jpegcodedlg.cpp

来自「《Visual C++视频技术方案宝典》配套光盘」· C++ 代码 · 共 1,095 行 · 第 1/2 页

CPP
1,095
字号

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CJpegCodeDlg dialog

CJpegCodeDlg::CJpegCodeDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CJpegCodeDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CJpegCodeDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
	m_hBmp = NULL;
	m_Name = "";
}

void CJpegCodeDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CJpegCodeDlg)
	DDX_Control(pDX, IDC_BKDEMO, m_Demo);
	DDX_Control(pDX, IDC_FILENAME, m_FileName);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CJpegCodeDlg, CDialog)
	//{{AFX_MSG_MAP(CJpegCodeDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BROWN, OnBrown)
	ON_BN_CLICKED(IDC_JPEGSAVE, OnJpegSave)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CJpegCodeDlg message handlers

BOOL CJpegCodeDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CJpegCodeDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CJpegCodeDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
	if (m_hBmp != NULL)
	{
		CDC* pDC = m_Demo.GetDC();
		CBitmap bmp;
		bmp.Attach(m_hBmp);
		CDC memDC;
		memDC.CreateCompatibleDC(pDC);
		memDC.SelectObject(&bmp);

		CRect rc;
		m_Demo.GetClientRect(rc);

		BITMAP bInfo;
		bmp.GetBitmap(&bInfo);
		int x = bInfo.bmWidth;
		int y = bInfo.bmHeight;

		pDC->StretchBlt(0,0,rc.Width(),rc.Height(),&memDC,0,0,x,y,SRCCOPY);
		pDC->DeleteDC();
		bmp.DeleteObject();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CJpegCodeDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CJpegCodeDlg::OnOK() 
{
	CString fName;
	m_FileName.GetWindowText(fName);
	if (! fName.IsEmpty())
	{
		m_Name = fName;
		m_hBmp = (HBITMAP)::LoadImage(NULL,fName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE);
	}
	else
	{
		m_Name = "";
		m_hBmp = NULL;
	}
	OnPaint();
}

void CJpegCodeDlg::OnBrown() 
{
	CFileDialog fDlg(TRUE,"","",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"位图文件(bmp)|*.bmp");
	if (fDlg.DoModal()==IDOK)
	{
		m_FileName.SetWindowText(fDlg.GetPathName());	
	}
}

void CJpegCodeDlg::OnJpegSave() 
{
	CFileDialog fDlg(false,"jpeg","mrkj",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"JPEG文件|(*.jpeg;*.jpg)");
	if (fDlg.DoModal()==IDOK)
	{
		CString strFileName = fDlg.GetPathName();
		SaveJpeg(NULL,strFileName,24,80);
	}
}

#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4) 

void CJpegCodeDlg::SaveJpeg(unsigned char *pBitdata, LPCSTR lpstrFileName, BOOL bColor, int Quality)
{
	CFile file;
	file.Open(m_Name,CFile::modeReadWrite);
	
	DWORD len = file.GetLength();
	BITMAPFILEHEADER bmpFileheader;
	file.Read(&bmpFileheader,sizeof(BITMAPFILEHEADER));
	
	unsigned char* pBuffer = new unsigned char[len];
	memset(pBuffer,0,len);
	
	file.ReadHuge(pBuffer,len);
	file.Close();
	
	BITMAPINFOHEADER bmpHeader;
	memcpy(&bmpHeader,pBuffer,sizeof(BITMAPINFOHEADER));
	
	//获取图像的高度和宽度
	int bmpHeight = bmpHeader.biHeight;
	int bmpWidth  = bmpHeader.biWidth;
	
	int cnt = bmpHeader.biBitCount;
	unsigned char* newBuffer = NULL;
	//如果不是24色的位图,需要进行转换
	if (cnt != 24)
		newBuffer = ConvertBmpFormat(pBuffer,24,bmpHeader.biSizeImage,bmpWidth,bmpHeight);

	BYTE* pTemp ;
	if (newBuffer != NULL)
		pTemp = newBuffer;
	else
		pTemp = pBuffer;
	pTemp+= 40;

	BYTE* tmp = CancelAlign((BYTE*)pTemp,
									bmpWidth,
									WIDTHBYTES(bmpWidth * 24),
									bmpHeight);

	FlipBuf(tmp, bmpWidth*3, bmpHeight);
	ConvertRGB(tmp, bmpWidth, bmpHeight);

	BOOL bSuccess = WriteJPEGFile(lpstrFileName,
							tmp,
							bmpWidth, 
							bmpHeight,
							bColor,
							Quality);
	delete pBuffer;
}




//转换为24色位图
unsigned char*  CJpegCodeDlg::ConvertBmpFormat(unsigned char *pDib, int Colors, DWORD dwImageSize,int Width,int Height)
{
	LPBITMAPINFO lpbmi = NULL; 
    LPBYTE       lpSourceBits, lpTargetBits, lpResult; 
    HDC			 hDC = NULL, hSourceDC, hTargetDC; 
    HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
    DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; 
	HANDLE		 hNewDIB;
	DWORD		 dwSize;

    if (Colors<= 8) 
		dwColorNum = 1 << Colors;
	else
		dwColorNum = 0;

    dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); 

	LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)pDib;

    lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 

    lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
    lpbmi->bmiHeader.biWidth = Width; 
    lpbmi->bmiHeader.biHeight = Height; 
    lpbmi->bmiHeader.biPlanes = 1; 
    lpbmi->bmiHeader.biBitCount = Colors; 
    lpbmi->bmiHeader.biCompression = BI_RGB; 
    lpbmi->bmiHeader.biSizeImage = 0; 
    lpbmi->bmiHeader.biXPelsPerMeter = 0; 
    lpbmi->bmiHeader.biYPelsPerMeter = 0; 
    lpbmi->bmiHeader.biClrUsed = 0; 
    lpbmi->bmiHeader.biClrImportant = 0; 

	 HPALETTE hPalSrc;

    if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, NULL) ) 
    { 
        free( lpbmi ); 
        return NULL; 
    } 
 
	hDC = ::GetDC(NULL ); 

    hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
    hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
    hSourceDC = CreateCompatibleDC( hDC ); 
    hTargetDC = CreateCompatibleDC( hDC ); 
 

    dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); 
    dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); 

    memcpy( lpSourceBits, FindDIBBits((char*)pDib), dwSourceBitsSize ); 
    lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
 


    hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
    hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
 

    if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) 
        SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); 
    if( lpbmi->bmiHeader.biBitCount <= 8 ) 
        SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
 
 
    BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
 

    SelectObject( hSourceDC, hOldSourceBitmap ); 
    SelectObject( hTargetDC, hOldTargetBitmap ); 
    DeleteDC( hSourceDC ); 
    DeleteDC( hTargetDC ); 
    ::ReleaseDC( NULL,hDC ); 
 
    GdiFlush(); 
 
	dwSize = dwTargetHeaderSize + dwTargetBitsSize;
	hNewDIB = GlobalAlloc(GHND, dwSize);
    lpResult = (LPBYTE)GlobalLock(hNewDIB);
    memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
    memcpy( FindDIBBits( (char*)lpResult ), lpTargetBits, dwTargetBitsSize ); 
 

    DeleteObject( hTargetBitmap ); 
    DeleteObject( hSourceBitmap ); 
    free( lpbmi ); 

 
    return lpResult;
}


unsigned char* CJpegCodeDlg::CancelAlign(unsigned char * pBuf, UINT wPix, UINT wBytes, UINT Height)
{
	unsigned char *tmp;
	tmp=new unsigned char [Height * wPix * 3];
	if (tmp==NULL)
		return NULL;
	for (int i=0 ; i <Height; i++) 
	{
		memcpy((tmp+i * wPix * 3), 
				(pBuf + i * wBytes), 
				wPix * 3);
	}
	return tmp;
}

BOOL CJpegCodeDlg::FlipBuf(unsigned char *pInbuf, UINT WidthBytes, UINT Height)
{
	unsigned char *pChar1;
	unsigned char *pChar2;

	if (pInbuf==NULL)
		return FALSE;

	UINT size = WidthBytes;
	pChar1 = new unsigned char [size];

	if (pChar1==NULL) 
	{
		return FALSE;
	}
	pChar2 = new unsigned char [size];

	if (pChar2==NULL) 
	{
		return FALSE;
	}
	ULONG off1=0;
	ULONG off2=0;

	for (int  row=0;row <(Height+1)/2; row++) 
	{
		off1=row*size;
		off2=((Height-1)-row)*size;   
		
		memcpy(pChar1,pInbuf+off1,size);
		memcpy(pChar2,pInbuf+off2,size);	
		
		memcpy(pInbuf+off1,pChar2,size);
		memcpy(pInbuf+off2,pChar1,size);
	}	

	delete [] pChar1;
	delete [] pChar2;
	return TRUE;
}

void CJpegCodeDlg::ConvertRGB(unsigned char *pBuf, UINT Width, UINT Height)
{
	UINT col, row;
	for ( row=0 ; row<Height ; row++) 
	{
		for (col=0; col<Width; col++) 
		{
			unsigned char* pRed, *pGrn, *pBlu;

			pRed = pBuf + row * Width * 3 + col * 3;
			pGrn = pBuf + row * Width * 3 + col * 3 + 1;
			pBlu = pBuf + row * Width * 3 + col * 3 + 2;

			unsigned char unChar;
			unChar = *pRed;
			*pRed = *pBlu;
			*pBlu = unChar;
		}
	}
}

BOOL CJpegCodeDlg::WriteJPEGFile(LPCSTR lpstrFileName, BYTE *dataBuf, UINT widthPix, UINT height, BOOL color, int quality)
{
	if (dataBuf==NULL)
		return FALSE;
	if (widthPix==0)
		return FALSE;
	if (height==0)
		return FALSE;

	LPBYTE tmp;
	if (!color) 
	{
		tmp = (BYTE*)new BYTE[widthPix*height];
		if (tmp==NULL) 
		{
			return FALSE;
		}

		UINT row,col;
		for (row=0;row<height;row++) 
		{
			for (col=0;col<widthPix;col++) 
			{
				LPBYTE pRed, pGrn, pBlu;
				pRed = dataBuf + row * widthPix * 3 + col * 3;
				pGrn = dataBuf + row * widthPix * 3 + col * 3 + 1;
				pBlu = dataBuf + row * widthPix * 3 + col * 3 + 2;

				// 计算图像亮度值
				int lum = (int)(.299 * (double)(*pRed) + .587 * (double)(*pGrn) + .114 * (double)(*pBlu));
				LPBYTE pGray;
				pGray = tmp + row * widthPix + col;
				*pGray = (BYTE)lum;
			}
		}
	}
    //定义压缩信息
	struct jpeg_compress_struct cinfo;
     //定义缓冲区
	FILE * outfile;			
	int row_stride;		
    //定义错误信息
	struct jpeg_error_mgr jerr;
    //为JPEG文件压缩对象分配内存并对其初始化
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);

      //打开文件并设定数据目标 
	if ((outfile = fopen(lpstrFileName, "wb")) == NULL) 
	{
		return FALSE;
	}

	jpeg_stdio_dest(&cinfo, outfile);

	//设置压缩参数
	cinfo.image_width = widthPix; 	
	cinfo.image_height = height;
	if (color) 
	{
		cinfo.input_components = 3;	
		cinfo.in_color_space = JCS_RGB; 	
	} 
	else 
	{
		cinfo.input_components = 1;	
		cinfo.in_color_space = JCS_GRAYSCALE; 
	}

   jpeg_set_defaults(&cinfo);
   jpeg_set_quality(&cinfo, quality, TRUE );

  //开始压缩
  jpeg_start_compress(&cinfo, TRUE);
  //写入扫描线
  row_stride = widthPix * 3;

  while (cinfo.next_scanline < cinfo.image_height) 
  {
   
	LPBYTE outRow;
	if (color) 
	{
		outRow = dataBuf + (cinfo.next_scanline * widthPix * 3);
	} 
	else 
	{
		outRow = tmp + (cinfo.next_scanline * widthPix);
	}

    (void) jpeg_write_scanlines(&cinfo, &outRow, 1);
  }
  //完成压缩
  jpeg_finish_compress(&cinfo);
  fclose(outfile);
  //释放压缩对象
  jpeg_destroy_compress(&cinfo);

  if (!color)
	  delete [] tmp;
  
  return TRUE;
}












⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?