截屏为什么都说应该保存为 PNG 格式

一直都是使用 JPG 存储截屏的。后来发现文件越来越大,放大后的问题越来越难看。

搜到一篇文章,先摘录部分(http://blog.sina.com.cn/s/blog_46dac66f010004ox.html)

 

PNG 是软件截屏的最佳选择(体积最小;最清晰);JPG 是根本错误的选择;gif是可以接受的选择;bmp是 最愚蠢的过时方案——绝大多数情况下,这些断言都是成立的。

简言之,软件截屏用 PNG,别用 JPG。

其实,根本不应该把png与jpg比,因为两者完全适合不同的场景。如果要比较,应该是PNG 与 GIF 比;而JPG 并无特别适合的对比格式(或与 JPG2000 比)。

JPG 适用于自然或人物照片 颜色数量多、但边界和颜色过渡不尖锐,反而有很强的连续性。多数非专业的数码相机,拍摄照片后都保存为 JPG 格式。JPG 照片,可以在视觉效果损失很小的情况下,文件尺寸极明显降低。比如,把原大小 3MB的 JPG 照片,另存为500KB,效果仍然可以接受。

软件界面保存为 JPG,很容易出现失真 在文字、线条周围,出现斑点、模糊。如果要提高质量,JPG的体积也会迅速增长。但即使如此,失真现象仍难避免。真是费力不讨好。

便携式网络图形(英語:Portable Network Graphics,PNG)是一种支持无损压缩的位图图形格式,支持索引、灰度、RGB三种颜色方案以及Alpha通道等特性。PNG的开发目标是改善并取代GIF作为适合网络传输的格式而不需专利许可,所以被广泛应用于互联网及其他方面上。

PNG另一个非正式的名称来源为递归缩写:“PNG is Not GIF”。

PNG圖片大多數都使用PNG作为扩展名,其互联网媒体类型为image/png。[1]PNG于1997年3月作为知识性RFC 2083发布,于2004年作为ISO/IEC标准发布。

上面的图都是同样的截屏,保存为不同格式。

在放大 200% 后,发现 JPG 表现明显偏差。

 

 

JPG 图片的大小是 101 KB

 

PNG 格式的图片只有 64 KB

 

 

相比来说,大小明显小了很多。因此如果你更多使用软件截图的话,建议还是使用 PNG。

对于一张图少 50KB,如果你的文章中有超过 10 张图,你可能会少 500 KB。虽然目前的网络速度已经非常快了,但是能在达到目的的情况下尽量减少数据传输,是非常划算的。

https://www.ossez.com/t/png/180

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个简单的C++ MFC截图功能的实现,其中使用了GDI+库来保存为.png格式片: ``` #include <afxwin.h> #include <gdiplus.h> // 需要添加GDI+库的引用 using namespace Gdiplus; class CScreenshotDlg : public CDialogEx { public: CScreenshotDlg(CWnd* pParent = nullptr) : CDialogEx(IDD_SCREENSHOT_DIALOG, pParent) {} protected: virtual void DoDataExchange(CDataExchange* pDX) override { CDialogEx::DoDataExchange(pDX); } virtual BOOL OnInitDialog() override; afx_msg void OnCaptureButtonClicked(); DECLARE_MESSAGE_MAP() private: CWnd* m_pParentWnd; }; BEGIN_MESSAGE_MAP(CScreenshotDlg, CDialogEx) ON_BN_CLICKED(IDC_CAPTURE_BUTTON, &CScreenshotDlg::OnCaptureButtonClicked) END_MESSAGE_MAP() BOOL CScreenshotDlg::OnInitDialog() { CDialogEx::OnInitDialog(); m_pParentWnd = GetDesktopWindow(); return TRUE; } void CScreenshotDlg::OnCaptureButtonClicked() { CRect rect; m_pParentWnd->GetWindowRect(rect); CDC* pDC = m_pParentWnd->GetDC(); CDC memDC; memDC.CreateCompatibleDC(pDC); CBitmap bmp; bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); memDC.SelectObject(&bmp); memDC.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY); GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); CLSID encoderClsid; GetEncoderClsid(L"image/png", &encoderClsid); Image image(bmp); image.Save(L"capture.png", &encoderClsid, NULL); GdiplusShutdown(gdiplusToken); ReleaseDC(pDC); memDC.DeleteDC(); } int main() { AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0); CScreenshotDlg dlg; dlg.DoModal(); return 0; } ``` 其中,GetEncoderClsid函数是获取.png格式编码器的CLSID的函数,实现如下: ``` 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*)(malloc(size)); if (pImageCodecInfo == NULL) return -1; GetImageEncoders(num, size, pImageCodecInfo); for (UINT i = 0; i < num; ++i) { if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0) { *pClsid = pImageCodecInfo[i].Clsid; free(pImageCodecInfo); return i; } } free(pImageCodecInfo); return -1; } ``` 这个实现中,我们首先获取了父窗口的大小和DC,然后创建了一个兼容DC和位,并将父窗口的像复制到位中。接着,我们使用GDI+库创建了一个Image对象,并使用Save函数将其保存为.png格式像。注意,该函数需要传入.png格式的编码器的CLSID,因此我们使用了GetEncoderClsid函数获取该编码器的CLSID。最后,我们释放了DC和位,关闭了GDI+库。 希望这个实现对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HoneyMoose

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值