标准固定
1 寸=3.3333333 厘米
1 英寸=2.54 厘米
求计算机显示器PPI?
比如对角线14英寸,不是寸,即2.54*14=35.56cm
按16:9算出宽和高 高(9x)2+宽(16x)2=对角线35.56cm2 算出宽*高:30.99*17.43cm 即30.99/2.54英寸
像素为1920*1080 PPI=1920*2.54/30.99= 约157PPI(pixel per inch)
求一张图片在某分辨率下的实际尺寸?
比如600PPI(pixel per inch 显示器)或DPI(dots per inch 打印机) ,像素为1920*1080,算宽*高各为多少英寸或厘米?
像素为1920*1080,打印机为600dpi
宽=1920/600 英寸=1920/600*2.54 厘米=8.128 厘米
高=1080/600 英寸=1080/600*2.54 厘米=4.572 厘米
现在改为打印机300dpi,要求实际物理尺寸不变。
宽=width/300 英寸=width/300*2.54 厘米=8.128 厘米
高=height/300 英寸=height/300*2.54 厘米=4.572 厘米
必须缩放图片像素为960*540
所以,不同点数的打印机要按实际物理尺寸打印图片,那必须缩放图片,即改变像素。实际尺寸以打印机为600dpi为标准:currnet_x_pix=old_x_pix/600*currnet_dpi
C#按物理尺寸打印图片 e.Graphics.DrawImage(image,0,0); //按物理尺寸打印标签,600点改为300点的打印机_小黄人软件的博客-CSDN博客
MFC按实际物理尺寸打印图片
方法1.获得打印机点数,按点数转换图片像素
#include "pch.h"
#include "../pch.h"
#include "../utility/utility.h"
#include <atlbase.h> using namespace Gdiplus;
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{UINT num = 0; // number of image encodersUINT size = 0; // size of the image encoder array in bytesImageCodecInfo* pImageCodecInfo = NULL;GetImageEncodersSize(&num, &size);if (size == 0)return -1; // FailurepImageCodecInfo = (ImageCodecInfo*)(malloc(size));if (pImageCodecInfo == NULL)return -1; // FailureGetImageEncoders(num, size, pImageCodecInfo);for (UINT j = 0; j < num; ++j){if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0){*pClsid = pImageCodecInfo[j].Clsid;free(pImageCodecInfo);return j; // Success}}free(pImageCodecInfo);return -1; // Failure
}
BOOL getBMPInfo(LPCTSTR fileName)
{// Initialize GDI+.GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);USES_CONVERSION;Gdiplus::Bitmap* pBitmap = new Gdiplus::Bitmap(T2W(fileName));if (pBitmap == NULL || pBitmap->GetLastStatus() != Gdiplus::Ok) { logger.ERROR_F(__FUNCTION__+to_string(__LINE__)+"出错:" + to_string(pBitmap->GetLastStatus())); delete pBitmap; return FALSE; }logger.INFO_F("水平*垂直分辨率:" +to_string(pBitmap->GetHorizontalResolution()) + "*" + to_string(pBitmap->GetVerticalResolution()));logger.INFO_F("width*height像素:" + to_string(pBitmap->GetWidth())+"*"+ to_string(pBitmap->GetHeight()));logger.INFO_F("600dpi时width*height厘米:" + to_string((float)(pBitmap->GetWidth())*2.54 /600) + "*" + to_string((float)(pBitmap->GetHeight())*2.54 /600));//if (abs(pBitmap->GetHorizontalResolution() - dpi)>0.5 || abs(pBitmap->GetVerticalResolution() - dpi)> 0.5)//{// logger.ERROR_F("水平分辨率" + to_string(pBitmap->GetHorizontalResolution()) + "或垂直分辨率" + to_string(pBitmap->GetVerticalResolution()) + " 错误,应该为" + to_string(dpi));// delete pBitmap;// return FALSE;//}delete pBitmap;return TRUE;
}
BOOL setBMPResolution(LPCTSTR fileName, float dpi)
{LPCTSTR outFileName = "temp.bmp";// Initialize GDI+.GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);USES_CONVERSION;Gdiplus::Bitmap* pBitmap = new Gdiplus::Bitmap(T2W(fileName));if (pBitmap==NULL || pBitmap->GetLastStatus() != Gdiplus::Ok) { logger.ERROR_F("转分辨率出错:" + to_string(pBitmap->GetLastStatus())); delete pBitmap; return FALSE; }Gdiplus::Status status = pBitmap->SetResolution(dpi, dpi);//设置此 Bitmap 的分辨率。if (status != Gdiplus::Ok) { logger.ERROR_F("转分辨率:" + to_string(status)); delete pBitmap; return FALSE; }CLSID clsid;GetEncoderClsid(L"image/bmp", &clsid); //Get the encoderstatus = pBitmap->Save(T2W(outFileName), &clsid);//Save the image into physical memoryif (status != Gdiplus::Ok) { logger.ERROR_F("转分辨率后,保存错误:" + to_string(status)); delete pBitmap; return FALSE; }delete pBitmap;pipe_system("del "+ (CString)fileName+"\n", DELAY); //cmd先删除pipe_system("rename " + (CString)outFileName + " "+ fileName +"\n", DELAY); //cmd重命名为原来的名logger.INFO_F(string(fileName)+"设置分辨率成功:" + to_string(dpi));return TRUE;
}void PrintBitmap(LPCTSTR filename)
{//setBMPResolution(filename, 600);//转为600分辨率getBMPInfo(filename);CPrintDialog printDlg(FALSE);printDlg.GetDefaults(); CDC dc;if (!dc.Attach(printDlg.GetPrinterDC())) {AfxMessageBox(_T("No printer found!")); return;} dc.m_bPrinting = TRUE; DOCINFO di; // Initialise print document details::ZeroMemory (&di, sizeof (DOCINFO));di.cbSize = sizeof (DOCINFO);di.lpszDocName = filename; //显示在打印列表里的名字BOOL bPrintingOK = dc.StartDoc(&di); // Begin a new print job // Get the printing extents// and store in the m_rectDraw field of a // CPrintInfo objectCPrintInfo Info;Info.SetMaxPage(1); // just one page //打印机页面的水平和垂直像素int maxw = dc.GetDeviceCaps(HORZRES);int maxh = dc.GetDeviceCaps(VERTRES); //打印机每英寸像素数int cxInch = dc.GetDeviceCaps(LOGPIXELSX);int cyInch = dc.GetDeviceCaps(LOGPIXELSY);logger.INFO_F("页面:" + to_string(maxw)+"*"+to_string(maxh) + " 打印机DPI:" + to_string(cxInch)+"*"+to_string(cyInch)); //mm 纸尺寸 Info.m_rectDraw.SetRect(0, 0, maxw, maxh);for (UINT page = Info.GetMinPage(); page <= Info.GetMaxPage() && bPrintingOK; page++) {dc.StartPage(); // begin new pageInfo.m_nCurPage = page;CBitmap bitmap;// LoadImage does the trick here, it creates a DIB section// You can also use a resource here// by using MAKEINTRESOURCE() ... etc. if(!bitmap.Attach(::LoadImage(::GetModuleHandle(NULL), filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE))) {AfxMessageBox(_T("Error loading bitmap!")); return;} BITMAP bm;bitmap.GetBitmap(&bm);//获得宽与高// create memory device contextCDC memDC; memDC.CreateCompatibleDC(&dc);CBitmap *pBmp = memDC.SelectObject(&bitmap);memDC.SetMapMode(dc.GetMapMode());dc.StretchBlt(0, 0, bm.bmWidth * cxInch / 600 , bm.bmHeight * cyInch / 600 , &memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);//按600dpi时的实际尺寸打印//dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY); //按图片大小打印// clean upmemDC.SelectObject(pBmp);bPrintingOK = (dc.EndPage() > 0); // end page} if (bPrintingOK)dc.EndDoc(); // end a print jobelse dc.AbortDoc(); // abort job.
}