大多的开源或不开源的软件处理jpg图像的时候均使用libjpeg开源库,目前最新版本为libjpeg-8b,下载链接为

http://freshmeat.net/projects/libjpeg

里面很多makefile文件,linux下不多说,在win32下,构建vc6工程只要将.vc6后缀名搜索出,将make*dsp.vc6修改为make*dsp.dsp,所有make*dsw.vc6修改为make*dsw.dsw,这里得到makeadsw.dsw和makejdsw.dsw,前者为所有编解码及测试程序工程,后者为简单的libjpeg工程。对于libjpeg的makejdsw生成了一个win32的的.lib库,这里可将库名称修改为libjpeg.lib。这样我们可参考编码程序将图片编码为jpeg图片了。

比如,现在我们利用GDI+打开任意格式图片,而后得到图片的解码数据,便可编译为jpeg图片了。

ps:为何不用GDI+直接保存jpg图片,因GDI+中生成的jpeg质量不满意,嘿嘿

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// jpeg
void write_my_jpeg()
{
    // 初始化数据
    Bitmap bitmap(_T("a.bmp"));
    int iWidth = bitmap.GetWidth();
    int iHeight = bitmap.GetHeight();
    unsigned char *pDataConv = new unsigned char[iWidth * iHeight * 3];
    init_data(bitmap, pDataConv);
    struct jpeg_compress_struct jcs;
    // 声明错误处理器,并赋值给jcs.err域
    struct jpeg_error_mgr jem;
    jcs.err = jpeg_std_error(&jem);
    jpeg_create_compress(&jcs);
    FILE * f = _wfopen(_T("my.jpg"), _T("wb"));
    if (f==NULL)
    {
        delete [] pDataConv;
        return;
    }
    jpeg_stdio_dest(&jcs, f);
    jcs.image_width = iWidth;    // 为图的宽和高,单位为像素
    jcs.image_height = iHeight;
    jcs.input_components = 3;   // 在此为1,表示灰度图, 如果是彩色位图,则为3
    jcs.in_color_space = JCS_RGB; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像
     
    jpeg_set_defaults(&jcs);
    // 指定亮度及色度质量
    jcs.q_scale_factor[0] = jpeg_quality_scaling(100);
    jcs.q_scale_factor[1] = jpeg_quality_scaling(100);
        // 图像采样率,默认为2 * 2
    jcs.comp_info[0].v_samp_factor = 1;
    jcs.comp_info[0].h_samp_factor = 1;
        // 设定编码jpeg质量
    jpeg_set_quality (&jcs, 100, true);
    jpeg_start_compress(&jcs, TRUE);
    JSAMPROW row_pointer[1];   // 一行位图
    int row_stride;      // 每一行的字节数
    row_stride = jcs.image_width * 3; // 如果不是索引图,此处需要乘以3
    // 对每一行进行压缩
    while (jcs.next_scanline < jcs.image_height)
       {
        row_pointer[0] = (JSAMPROW)(pDataConv + jcs.next_scanline * row_stride);   
        jpeg_write_scanlines(&jcs, row_pointer, 1);
    }
    jpeg_finish_compress(&jcs);
    jpeg_destroy_compress(&jcs);
    //
    delete [] pDataConv;
}

// 数据转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// data
void init_data(Bitmap &bitmap, unsigned char *pDataConv)
{  
    // Btimap
     
    int iWidth = bitmap.GetWidth();
    int iHeight = bitmap.GetHeight();
    Gdiplus::BitmapData bitmapData;
    Gdiplus::Rect rectPiece(0, 0, iWidth, iHeight);
    // lock,获取Bitmap数据
    bitmap.LockBits(&rectPiece, Gdiplus::ImageLockModeWrite,
        PixelFormat32bppARGB, &bitmapData);
    int iBitmapPieceStride = bitmapData.Stride;
    unsigned long *pBitmapPiecePixels = (unsigned long*)bitmapData.Scan0;
    // 获取像素点数据
    unsigned long ulColorValueTemp = 0;
    unsigned char usR, usG, usB;
    for (int y = 0; y != iHeight; ++y)
    {
        for (int x = 0; x != iWidth; ++x)
        {
            ulColorValueTemp = pBitmapPiecePixels[y * iBitmapPieceStride / 4 + x];
            usR = (ulColorValueTemp >> 16);
            usG = (ulColorValueTemp >> 8);
            usB = ulColorValueTemp;
            *pDataConv = usR;
            ++pDataConv;
            *pDataConv = usG;
            ++pDataConv;
            *pDataConv = usB;
            ++pDataConv;
        }
    }
    //
//  memcpy(pDataConv, pBitmapPiecePixels, iWidth * iHeight * 3);
    bitmap.UnlockBits(&bitmapData);
}

默认情况下,不管是GDI+,还是CxImage,OpenCV等常见的开源库均只提供了设定质量的函数,即

1
jpeg_set_quality()

正常情况下,这样也可以满足我们的基本需求,但对于有些图片,比如黑色背景,写白色字体的图片,在压缩时,基本设定质量最高为100,但压缩质量仍不满意,原因便在压缩时的图像采样率上,ASDSee保存jpeg图片格式时,有选择采样率的2 * 1和1* 2,而libjpeg默认为2 * 2,因此会发现ACDSee质量要好些的缘故,如果不介意,可以直接设定为1 * 1,质量会更好些,不过对于这样的图片压缩后的图片大小可能大于原bmp图片大小,具体情况请读者自行参考。

关于libjpeg修改图片质量的讨论相关推荐

  1. mysql 如何修改wait_timeout,interactive_timeout ,和 session ,global 有什么关系

    最近程序出现这样的问题 The last packet successfully received from the server was 38251886 milliseconds ago. The ...

  2. Z-Stack 的应用层参数修改

    Z-Stack 的应用层参数修改 本文件讨论了影响ZigBee Z-Stack 使用和配置的各种全局变量.编译选项和编译器指令.本文件适用于ZigBee Z-Stack 的版本1.4.0.最常见的用于 ...

  3. 树莓派linux iso镜像下载,树莓派(Raspberry Pi)修改系统镜像(img)

    树莓派修改系统镜像 讨论如何使用通过loop设备映射文件,挂载树莓派img中的分区,然后像普通的文件系统那样修改镜像分区中的文件. 有2个关键点 如何确认分区的起始位置,以及分区的范围. 不同版本的l ...

  4. QQ2011 Beta3透明皮肤主界面修改详细教程

    要用到的工具:GFT图片转换.Res解包器(在附件中) GFT图片转换器:要的留言! 首先要用的软件:RDB解压打包软件下载地址:http://www.vdisk.cn/down/index/4802 ...

  5. [数据集] CNRDS上市公司管理层讨论与分析数据(1999-2020年)

    [数据集] 上市公司管理层讨论与分析数据(1999-2020年) 数据描述: 数据包括股票代码.公司简称.会计年度.经营分析时间.经营讨论与分析内容.正面词汇数量.负面词汇数量.句子数量.文字数量.净 ...

  6. 北大林宙辰:追求机器学习研究的美感

    在知乎上有人提问:如何评价北京大学林宙辰老师? 高赞答曰:功底深厚,难以望其项背. 这表现在几个方面-- 1.从外界普遍的标准来看,自2000年至今,他的论文引用量已经高达2w+:同时也是IEEE.I ...

  7. android中ocr解决方案(tesseract)

    2019独角兽企业重金招聘Python工程师标准>>> android应用中ocr的解决方案大致有两种,而采用最多的还是tesseract.小弟就在这里将我最近两天解决思路写下来,如 ...

  8. 2020秋季学期教学委员会第一次全体会议

    ➤ 01会议简介 时间:2020.10.21 11:30-15:00 地点:中央主楼803 参会人员: 教学委员会委员:赵千川,陈峰,石宗英,张佐,师丽,叶朝辉,刘连臣,任艳频,李力,赵虹,耿华,索津 ...

  9. [心得分享] 我在 GitHub 上学习开源

    先祝给位圣诞节快乐! 文章拖了将近一年的时间,我想是时候可以把两年多在 GitHub 开源的经验分享给大家,虽然不及神人级的开发者,但我始终相信,分享.自由.开放.讨论和开发者是开源的核心精神. 如果 ...

最新文章

  1. Hadoop集群的NameNode的备份
  2. 成功解决TypeError: ‘str‘ object is not callable
  3. CVPR2020 Oral | 旷视研究院提出双边分支网络BBN:攻坚长尾分布的现实世界任务
  4. python separator_在Python中使用分隔符变量拆分字符串
  5. 我的docker随笔14:MySQL操作实例
  6. ×××数据库导数据ora-01400错误小计
  7. Python 炫技操作:花式导包的八种方法
  8. 编程之美---电梯调度算法
  9. 使用bus hound发送包的方法
  10. 全开源!Office多人协作应用,在线编辑Word、Excel和PPT文档
  11. 多渠道下门店如何进行会员管理和会员营销
  12. 【PC工具】PC好用的迅雷下载版本合集,hash资源下载方法,石皮版迅雷软件去广告优化增强典藏版...
  13. 美团 SP 30K*15.5?如何看待老生常谈的薪资倒挂现象?
  14. 初学者学python用什么软件,python编程入门软件
  15. 测试你适合的发型软件叫什么,有没有测试发型的app 测试自己适合什么发型
  16. 英汉对照名言隽语(四)
  17. 软件测试相关术语及其含义
  18. 免费python全套教程百度云-老男孩Python视频教程全套完整版!无偿分享~
  19. PS2020从入门到卸载
  20. php计算时间早上中午,php如何判断上午还是下午

热门文章

  1. 函数载入的html触发onload,JS IFRAME动态加载触发onload事件解析
  2. 国内免费可用的stun服务器(2020.7.14)
  3. zemax光学设计第二版
  4. Ubuntu 高亮词汇翻译,划线翻译,鼠标选词翻译,点读机
  5. 基于java的考研自习室音视频通话APP设计
  6. 洛谷P1304哥德巴赫猜想 题解
  7. Netapp磁盘聚合划分
  8. 程序员的面试经历!2020春招四五月份大厂面经 二:(腾讯、网易、斗鱼、富途、美团、快手)
  9. Test-Time Training
  10. 自动装箱中==的使用