注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

简单代码

寻找代码的灵魂

 
 
 

日志

 
 
关于我

对于本博客内所有原创文章和代码的引用必须标明“来源:http://simplesource.blog.163.com/”。如需应用于商业目的必须经本人同意,本人对所有原创文章和代码保留一切权利。 PS:需要部分程序源代码的请留下邮箱地址

一个简单的图像压缩算法  

2008-07-11 17:47:34|  分类: 我的程序 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

  最近在研究图像压缩,其他经典的算法都还没看,先按照自己的想法搞了一个简短的图像压缩算法。算法原理很简单:取一个点,然后把这个点之后的n个与该点差别不大的点个数数出来,然后存储为像素+n的格式,这样如果图像中连续相似的点比较多,就可以大幅度压缩图像。今天一天就把这个东东搞定了,测试了一下,在我可以忍受的图像损失下,一般的图像压缩率可以达到10%以下,跟经典的算法有一定差距,不过这个算法毕竟比较简单,没有用到复杂的数学变换呐。通过这个程序,对图像压缩有了一定的概念,可以研究其他的经典算法了。

  现在把源代码贴出来同大家分享:

// SIC.h文件

#pragma once

class CSIC
{
public:
    CSIC(void);
    ~CSIC(void);

protected:
    // 图像大小
    CSize   m_sizeImg;
    // 像素大小
    int     m_iPixel;

    // 数据空间
    unsigned char * m_cvRoom;
    // 数据长度
    __int64 m_iLength;

    // 压缩数据空间
    unsigned char * m_cvCRoom;
    // 压缩数据长度
    __int64 m_iCLength;

    // 容差
    __int32 m_iAllow;

    // 是否去噪
    bool    m_bChirp;


public:
    // 取得容差
    __int32 GetAllow()
    {
        return m_iAllow;
    }
    // 设置容差
    void SetAllow(__int32 allow)
    {
        m_iAllow = allow;
    }
    // 取得是否去噪
    bool IsChirp()
    {
        return m_bChirp;
    }
    // 是否去噪
    void Chirp(bool bChirp = true)
    {
        m_bChirp = bChirp;
    }
    // 清空
    void Clear()
    {
        if(m_cvRoom)
        {
            delete [] m_cvRoom;
            m_cvRoom = NULL;
        }
        m_iLength = 0;
        if(m_cvCRoom)
        {
            delete [] m_cvCRoom;
            m_cvCRoom = NULL;
        }
        m_iCLength = 0;
        m_sizeImg.cx = 0;
        m_sizeImg.cy = 0;
        m_iPixel = 0;
    }
    // 设置图像
    bool SetImg(CBitmap & bmp)
    {
        BITMAP BMP;
        if(bmp.GetBitmap(&BMP) && SetFormat(BMP.bmWidth, BMP.bmHeight, BMP.bmBitsPixel / 8))
        {
            m_iLength = BMP.bmHeight * BMP.bmWidthBytes;
            m_cvRoom = new unsigned char [m_iLength];
            m_iLength = bmp.GetBitmapBits(m_iLength, m_cvRoom);
            return true;
        }
        return false;
    }
    // 取得图像
    bool GetImg(CBitmap & bmp)
    {
        if(m_cvRoom)
        {
            bmp.CreateBitmap(m_sizeImg.cx, m_sizeImg.cy, 1, m_iPixel * 8, m_cvRoom);
            return true;
        }
        return false;
    }
    // 设置压缩数据
    bool SetData(unsigned char * buffer, __int64 len);
    // 取得压缩数据
    char * GetData(__int64 & len);
    // 设置图像格式
    bool SetFormat(int w, int h, int iPixel)
    {
        if(iPixel != 4 || w <= 0 || h <= 0)
        {
            return false;
        }
        Clear();
        m_sizeImg.cx = w;
        m_sizeImg.cy = h;
        m_iPixel = iPixel;
    }
    // 压缩
    bool Compress();
    // 解压
    bool Decompress();
    // 取得压缩率
    double GetRate()
    {
        if(m_iLength == 0)
        {
            return 1.0;
        }
        else
        {
            return m_iCLength / double(m_iLength);
        }
    }
    // 取得压缩描述
    CString Describe()
    {
        CString txt;
        txt.Format("压缩率 %.4lf%% (%lfK)", GetRate() * 100, m_iCLength / 1024.0);
        return txt;
    }
    // 取得图像大小
    inline CSize GetImgSize()
    {
        return m_sizeImg;
    }
};

// SIC.CPP文件

#include "StdAfx.h"
#include ".\sic.h"

CSIC::CSIC(void)
    : m_cvRoom(NULL)
    , m_cvCRoom(NULL)
    , m_iAllow(0)
    , m_bChirp(false)
{
    Clear();
}

CSIC::~CSIC(void)
{
    Clear();
}

// 压缩
bool CSIC::Compress()
{
    if(m_cvRoom)
    {
        if(m_iPixel == 4)
        {
            if(m_cvCRoom)
            {
                delete [] m_cvCRoom;
            }
            m_iCLength = m_iLength * 3 / 4;
            m_cvCRoom = new unsigned char[m_iCLength];
            __int64 base = 0;
            __int64 len;
            __int64 tmp;
            __int64 index = 0;
            unsigned char r, g, b;
            double sr, sg, sb;
            unsigned char * pc;
            __int32 dr, dg, db;
            while(base < m_iLength)
            {
                r = m_cvRoom[base];
                g = m_cvRoom[base + 1];
                b = m_cvRoom[base + 2];
                sr = r;
                sg = g;
                sb = b;
                for(len = 4; len < m_iLength - base; len += 4)
                {
                    // 计算容差
                    pc = m_cvRoom + base + len;
                    dr = pc[0] - r;
                    dg = pc[1] - g;
                    db = pc[2] - b;
                    if(dr * dr + dg * dg + db * db > m_iAllow)
                    {
                        if(m_bChirp)
                        {
                            // 检查是不是噪点
                            if(len + 4 < m_iLength - base)
                            {
                                pc = m_cvRoom + base + len + 4;
                                dr = pc[0] - r;
                                dg = pc[1] - g;
                                db = pc[2] - b;
                                if(dr * dr + dg * dg + db * db > m_iAllow)
                                {
                                    break;
                                }
                            }
                            if(len + 4 * m_sizeImg.cx + 4 < m_iLength - base)
                            {
                                pc = m_cvRoom + base + len + 4 * m_sizeImg.cx;
                                dr = pc[0] - r;
                                dg = pc[1] - g;
                                db = pc[2] - b;
                                if(dr * dr + dg * dg + db * db > m_iAllow)
                                {
                                    break;
                                }
                                pc = m_cvRoom + base + len + 4 * m_sizeImg.cx + 4;
                                dr = pc[0] - r;
                                dg = pc[1] - g;
                                db = pc[2] - b;
                                if(dr * dr + dg * dg + db * db > m_iAllow)
                                {
                                    break;
                                }
                                pc = m_cvRoom + base + len + 4 * m_sizeImg.cx - 4;
                                dr = pc[0] - r;
                                dg = pc[1] - g;
                                db = pc[2] - b;
                                if(dr * dr + dg * dg + db * db > m_iAllow)
                                {
                                    break;
                                }
                            }
                            if(base + len - 4 * m_sizeImg.cx - 4 > 0)
                            {
                                pc = m_cvRoom + base + len - 4 * m_sizeImg.cx - 4;
                                dr = pc[0] - r;
                                dg = pc[1] - g;
                                db = pc[2] - b;
                                if(dr * dr + dg * dg + db * db > m_iAllow)
                                {
                                    break;
                                }
                                pc = m_cvRoom + base + len - 4 * m_sizeImg.cx;
                                dr = pc[0] - r;
                                dg = pc[1] - g;
                                db = pc[2] - b;
                                if(dr * dr + dg * dg + db * db > m_iAllow)
                                {
                                    break;
                                }
                                pc = m_cvRoom + base + len - 4 * m_sizeImg.cx + 4;
                                dr = pc[0] - r;
                                dg = pc[1] - g;
                                db = pc[2] - b;
                                if(dr * dr + dg * dg + db * db > m_iAllow)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    sr += pc[0];
                    sg += pc[1];
                    sb += pc[2];
                }
                if(len > 8)
                {
                    tmp = len / 4;
                    r = sr / tmp;
                    g = sg / tmp;
                    b = sb / tmp;
                }
                if(r == 0)
                {
                    r = 1;
                }
                m_cvCRoom[index] = r;
                m_cvCRoom[index + 1] = g;
                m_cvCRoom[index + 2] = b;
                index += 3;
                if(len <= 8)
                {
                    len = 4;
                }
                else
                {
                    tmp = len / 4 - 1;
                    if(tmp > 0xFFFF)
                    {
                        tmp = 0xFFFF;
                        len = tmp * 4 + 4;
                    }
                    pc = (unsigned char *)&tmp;
                    m_cvCRoom[index] = 0;
                    m_cvCRoom[index + 1] = pc[0];
                    m_cvCRoom[index + 2] = pc[1];
                    index += 3;
                }
                base += len;
            }
            m_iCLength = index;
        }
        return true;
    }
    return false;
}

// 解压
bool CSIC::Decompress()
{
    if(m_cvCRoom)
    {
        if(m_iPixel == 4)
        {
            if(m_cvRoom)
            {
                delete [] m_cvRoom;
            }
            m_iLength = m_sizeImg.cx * m_sizeImg.cy * m_iPixel;
            m_cvRoom = new unsigned char[m_iLength];
            __int64 base = 0;
            __int32 len;
            __int32 i;
            __int64 index = 0;
            while(base < m_iLength)
            {
                m_cvRoom[base + 3] = 0;
                m_cvRoom[base] = m_cvCRoom[index];
                m_cvRoom[base + 1] = m_cvCRoom[index + 1];
                m_cvRoom[base + 2] = m_cvCRoom[index + 2];
                base += 4;
                if(base < m_iLength && m_cvCRoom[index + 3] == 0)
                {
                    len = *(unsigned __int16 *)(m_cvCRoom + index + 4);
                    for(i = 0; i < len; i++)
                    {
                        m_cvRoom[base + 3] = 0;
                        m_cvRoom[base] = m_cvCRoom[index];
                        m_cvRoom[base + 1] = m_cvCRoom[index + 1];
                        m_cvRoom[base + 2] = m_cvCRoom[index + 2];
                        base += 4;
                        if(base >= m_iLength)
                        {
                            break;
                        }
                    }
                    index += 3;
                    //base -= 4;
                }
                index += 3;
            }
        }
        return true;
    }
    return false;
}

  程序运行时会实时计算当前桌面图像的压缩率,也可以点击测试按钮弹出测试对话框,对指定的图片进行压缩,或者对压缩参数进行设置。

一个简单的图像压缩算法 - 简单代码 - 简单代码

程序运行画面

一个简单的图像压缩算法 - 简单代码 - 简单代码

点击测试按钮,即可对指定图片进行压缩,并查看压缩后的效果

一个简单的图像压缩算法 - 简单代码 - 简单代码

压缩前

一个简单的图像压缩算法 - 简单代码 - 简单代码

压缩后

一个简单的图像压缩算法 - 简单代码 - 简单代码

压缩前

一个简单的图像压缩算法 - 简单代码 - 简单代码

压缩后

全部源代码下载:

一个简单的图片压缩算法(CSDN)

(注:请在32位图形模式下运行本程序)

一个简单的图像压缩算法 - 简单代码 - 简单代码
  评论这张
 
阅读(9609)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018