当前位置:编程学习 > C#/ASP.NET >>

求图像压缩算法

--------------------编程问答-------------------- 请大家帮忙 --------------------编程问答-------------------- 所占空间大小比原图小2-3倍? --------------------编程问答-------------------- 右键看我发的三张图的大小啊

20k的png:http://img.my.csdn.net/uploads/201205/03/1336011498_9094.png
7k的png:http://img.my.csdn.net/uploads/201205/03/1336011600_7018.png
11k的gif:http://img.my.csdn.net/uploads/201205/03/1336011600_4627.gif

这三张图内容都是一样的,只是质量和色彩有差别,因为图片颜色比较单一,所以这个损失可以接受 --------------------编程问答--------------------
首先,JPG对于你这种只有文字和一些纯色的图像的压缩效果必然是比较差的,而这种图像的因为颜色比较单调,像PNG这种无损的压缩效果也是能较好的压缩效果的,这个图转换成GIF或者8位的PNG也不会出现色差,因为她总的颜色不超过256种, C#如果直接用Save保存 格式 PixelFormat24bppRGB 或PixelFormat32bppARGB 的图像为GIF,则他会先要帮你转换为8位的,这个转换时内部实现的,你无法控制,因此效果就不好。 如果你是win vista以上的系统,GDI1.1则提供了一个ConvertFormat函数,可以很好的控制不同色深之间的转换。然后再保存。
 http://msdn.microsoft.com/en-us/library/ms536306(v=vs.85).aspx http://social.msdn.microsoft.com/Forums/en-AU/vcgeneral/thread/260a977d-d6fd-4ccb-9ad7-6579da1c405b

--------------------编程问答-------------------- 你这个

1)调色板

2)emf
--------------------编程问答-------------------- --------------------编程问答-------------------- http://freeimage.sourceforge.net/sourcecode.html


using (FreeImageAPI.FreeImageBitmap fiBitmap = FreeImageAPI.FreeImageBitmap.FromHbitmap(bmp.GetHbitmap()))
            {
                if (fiBitmap.ColorDepth > 24)
                {
                    fiBitmap.ConvertColorDepth(FreeImageAPI.FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP);
                }

                //quantize using the NeuQuant neural-net quantization algorithm 
                fiBitmap.Quantize(FreeImageAPI.FREE_IMAGE_QUANTIZE.FIQ_NNQUANT, 256);


                fiBitmap.Save("test_z.png", FreeImageAPI.FREE_IMAGE_FORMAT.FIF_PNG, FreeImageAPI.FREE_IMAGE_SAVE_FLAGS.PNG_Z_BEST_COMPRESSION);

                //fiBitmap.Save(ms, FreeImageAPI.FREE_IMAGE_FORMAT.FIF_PNG, FreeImageAPI.FREE_IMAGE_SAVE_FLAGS.PNG_Z_DEFAULT_COMPRESSION);
            } --------------------编程问答-------------------- --------------------编程问答-------------------- 有意思,学习 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 有意思,学习 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 颜色数量少且有较多连续色块时最好用GIF,如果还嫌大,则可再根据用途进行压缩(比如:如果是用于ASP.NET,则可使用gzip压缩) --------------------编程问答--------------------  4KB+- --------------------编程问答-------------------- --------------------编程问答-------------------- png是相對很小的 --------------------编程问答-------------------- 6.8K太大了。2K的飘过。。。

--------------------编程问答-------------------- 用LZMA算法吧,直接压缩索引过的bmp,试了下,可以小于1.4k --------------------编程问答-------------------- 看完后,我只有一个感觉,房价太贵了! --------------------编程问答-------------------- 18楼,21楼多谢

请教21楼兄弟c#可以直接处理吗 --------------------编程问答-------------------- 呼唤牛人出现!!!!!!!秒杀剪子!!!

2K那个,,你咋弄的呢 --------------------编程问答-------------------- 我也不懂 --------------------编程问答-------------------- 不明白 --------------------编程问答-------------------- 来个1.6k的,
--------------------编程问答-------------------- 地址错了。
--------------------编程问答--------------------
引用 29 楼  的回复:
地址错了。


这个如何实现?色彩不能改,表格不止1种颜色,但也不会超过3种
--------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 其实我很纳闷,纯色块上写文字,Div不是更好… --------------------编程问答--------------------
引用 33 楼  的回复:
其实我很纳闷,纯色块上写文字,Div不是更好…


div没问题,已经完成了,img的布局逻辑等也已经实现,只是切片有些大。 --------------------编程问答-------------------- --------------------编程问答-------------------- 我靠,哪儿的房子啊。这么贵 --------------------编程问答--------------------
引用 36 楼  的回复:
我靠,哪儿的房子啊。这么贵


数据是假的,不过京沪2w貌似也买不到城里面 --------------------编程问答-------------------- --------------------编程问答-------------------- 六环外,鉴定完毕。。。 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 23 楼  的回复:
看完后,我只有一个感觉,房价太贵了!

顶! --------------------编程问答-------------------- 比较新鲜 --------------------编程问答-------------------- 进来膜拜大神。楼主找到解决方法后不要忘了贴最佳方案。 --------------------编程问答-------------------- lyserver(江南春)所贴的图像 只使用了3种颜色,大小为1705字节。于是我也想到了用PixelFormat4bppIndexed格式来保存为PNG图像,结果为2529字节,比lyserver的大,于是我去用右键属性去看lyserver发的PNG图像的位深,发现居然是2位的,那么也就意味着一个像素只用 2个位,四个像素才使用一个字节。这肯定比我PixelFormat4bppIndexed这个占用的空间小。可问题是:


GDI或者GDI+有2位色深的图像,我记得只有1、4、8、16、24、32位的啊,连GDI+的位深常数里也没有PixelFormat2bppIndexed 这个枚举值啊,不知道哪位能解释下哦。 --------------------编程问答-------------------- 下面代码产生16色的PNG图像,大小为2.6K。
色彩采样用了最简单的方法,既使用最先碰到的16色。

如果要应对更多的输入(比如更多色彩),则可以采用其他采样算法,比如OctTree算法,比如clustering算法等等。

void ToPNG4bit()
{
    Bitmap source = new Bitmap("1336011498_9094.png");
    Bitmap target = new Bitmap(source.Width, source.Height, PixelFormat.Format4bppIndexed);

    List<Color> paletteColors = new List<Color>();
    BitmapData bm = target.LockBits(new Rectangle(0, 0, target.Width, target.Height), ImageLockMode.ReadWrite, target.PixelFormat);
    for (int y = 0; y < source.Height; y++)
    {
        for (int x = 0; x < source.Width; x++)
        {
            Color color = source.GetPixel(x, y);
            int index = GetNearestMatch(paletteColors, color);
            
            byte b = Marshal.ReadByte(bm.Scan0, bm.Stride * y + x / 2);
            if ((x & 1) == 1)
            {
                b = (byte)(index + (b & 0xF0));
            }
            else
            {
                b = (byte)((index << 4) + (b & 0x0F));
            }
            Marshal.WriteByte(bm.Scan0, bm.Stride * y + x / 2, b);
        }
    }
    target.UnlockBits(bm);
    ColorPalette palette = target.Palette;
    paletteColors.CopyTo(palette.Entries);
    target.Palette = palette;

    target.Save("B2-05.png", ImageFormat.Png); // 大小为2552bytes
}

private static int GetNearestMatch(List<Color> palette, Color color)
{
    int index = 0;
    int minDiff = int.MaxValue;
    for (int i = 0; i < palette.Count; i++)
    {
        int diff =
            Math.Abs(palette[i].R - color.R) +
            Math.Abs(palette[i].G - color.G) +
            Math.Abs(palette[i].B - color.B);
        if( diff == 0)
        {
            return i;
        }
        if (diff < minDiff)
        {
            index = i;
            minDiff = diff;
        }
    }
    if (palette.Count < 16)
    {
        index = palette.Count;
        palette.Add(color);
    }
    return index;
}
--------------------编程问答--------------------
引用 45 楼  的回复:
下面代码产生16色的PNG图像,大小为2.6K。
色彩采样用了最简单的方法,既使用最先碰到的16色。

如果要应对更多的输入(比如更多色彩),则可以采用其他采样算法,比如OctTree算法,比如clustering算法等等。
C# code

void ToPNG4bit()
{
    Bitmap source = new Bitmap("1336011498_9094.png")……


这个简单,回头试一下
--------------------编程问答--------------------
引用 44 楼  的回复:
lyserver(江南春)所贴的图像 只使用了3种颜色,大小为1705字节。于是我也想到了用PixelFormat4bppIndexed格式来保存为PNG图像,结果为2529字节,比lyserver的大,于是我去用右键属性去看lyserver发的PNG图像的位深,发现居然是2位的,那么也就意味着一个像素只用 2个位,四个像素才使用一个字节。这肯定比我PixelFormat4bppIndexed这……


2位 存的不实色彩值 是指向 色彩在 自己色彩板 上的编号

两位就是 4个,色彩板最多四个颜色,这四个颜色 可以 有各种色深 24、32


--------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- WPF提供了PngBitmapEncoder类用来存储PGN格式;提供了FormatConvertedBitmap类用来转化格式。
因此,还可以这么做(如果是WinForm或Web,要添加WindowsBase和PresentationCore的引用):

注意例子中调色板写定了4种颜色,这些颜色可以通过类似我在45楼提出的方法获得。

void Test()
{
    BitmapImage source = new BitmapImage();
    source.BeginInit();
    source.UriSource = new Uri("1336011498_9094.png");
    source.EndInit();

    FormatConvertedBitmap target = new FormatConvertedBitmap();
    target.BeginInit();
    {
        target.Source = source;
        List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>()
        {
            System.Windows.Media.Colors.Black,
            System.Windows.Media.Colors.Blue,
            System.Windows.Media.Color.FromRgb(255,208,208),
            System.Windows.Media.Colors.White,
        };
        BitmapPalette myPalette = new BitmapPalette(colors);
        target.DestinationPalette = myPalette;
        target.DestinationFormat = PixelFormats.Indexed2;
    }
    target.EndInit();

    using (FileStream stream = File.OpenWrite("B2-05.png"))
    {
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(target));
        encoder.Save(stream);
    }
}
--------------------编程问答-------------------- 29L的降低画质了吧- - 这样那还可以再小点  1.3k


--------------------编程问答--------------------
引用 24 楼  的回复:
18楼,21楼多谢

请教21楼兄弟c#可以直接处理吗
调用pngout.exe吧,可以直接通过粘贴板把图片传递过去 --------------------编程问答-------------------- 51 楼 更简单 不知道有没有 动态 获得 BitmapPalette 的方法
--------------------编程问答-------------------- jpg的压缩一大堆的压缩算法,范式哈夫曼算法,行程压缩,还有狗屁的离散数学。
自己研究了几个月也还没弄明白。

JPG压缩解压缩的源码上传到我的资源了。
http://download.csdn.net/detail/zanfeng/4274333 --------------------编程问答--------------------
引用 55 楼  的回复:
jpg的压缩一大堆的压缩算法,范式哈夫曼算法,行程压缩,还有狗屁的离散数学。
自己研究了几个月也还没弄明白。

JPG压缩解压缩的源码上传到我的资源了。
http://download.csdn.net/detail/zanfeng/4274333


嗯不要分,收下了,多谢了
--------------------编程问答--------------------
引用 56 楼  的回复:
引用 55 楼  的回复:

jpg的压缩一大堆的压缩算法,范式哈夫曼算法,行程压缩,还有狗屁的离散数学。
自己研究了几个月也还没弄明白。

JPG压缩解压缩的源码上传到我的资源了。
http://download.csdn.net/detail/zanfeng/4274333


嗯不要分,收下了,多谢了

下载了,居然不要分,我看看,有什么心得也共享下。




--------------------编程问答-------------------- 混经验的,学习图片压缩的算法。 --------------------编程问答--------------------
引用 55 楼  的回复:
jpg的压缩一大堆的压缩算法,范式哈夫曼算法,行程压缩,还有狗屁的离散数学。
自己研究了几个月也还没弄明白。

JPG压缩解压缩的源码上传到我的资源了。
http://download.csdn.net/detail/zanfeng/4274333


你的头像看着我真晕 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- RGB/JPEG, DCT变换,Huffman编码 --------------------编程问答-------------------- RGB/JPEG, DCT变换,Huffman编码 --------------------编程问答-------------------- 你这也叫图像压缩?不就图片格式转换了一下而以,兄弟别吓唬人 --------------------编程问答-------------------- --------------------编程问答-------------------- TO jinjazz:
图片本身的大小有是极限的,我的那幅图片实际上3位色调色板索引(丢失了白色),如果还想小,则看你的实际应用了。如果图片解码是由自己实现的,则可以在图片有损压缩的基础上,再使用文件压缩技术(比如这种连续色较多的图片,使用最基本的行程压缩或WMF回放效果应该不错),如果是用于浏览器则可以考虑我前面提到的GZIP压缩。 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答--------------------
引用 45 楼  的回复:
下面代码产生16色的PNG图像,大小为2.6K。
色彩采样用了最简单的方法,既使用最先碰到的16色。

如果要应对更多的输入(比如更多色彩),则可以采用其他采样算法,比如OctTree算法,比如clustering算法等等。
C# code

void ToPNG4bit()
{
    Bitmap source = new Bitmap("1336011498_9094.png")……



都是高手,向你们学习 --------------------编程问答--------------------
引用 67 楼  的回复:
TO jinjazz:
图片本身的大小有是极限的,我的那幅图片实际上3位色调色板索引(丢失了白色),如果还想小,则看你的实际应用了。如果图片解码是由自己实现的,则可以在图片有损压缩的基础上,再使用文件压缩技术(比如这种连续色较多的图片,使用最基本的行程压缩或WMF回放效果应该不错),如果是用于浏览器则可以考虑我前面提到的GZIP压缩。


多谢,这贴让我长进了 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 图做的再小也掩盖不了天价的房子 --------------------编程问答-------------------- --------------------编程问答-------------------- TO jinjazz:
图片本身的大小有是极限的,我的那幅图片实际上3位色调色板索引(丢失了白色),如果还想小,则看你的实际应用了。如果图片解码是由自己实现的,则可以在图片有损压缩的基础上,再使用文件压缩技术(比如这种连续色较多的图片,使用最基本的行程压缩或WMF回放效果应该不错),如果是用于浏览器则可以考虑我前面提到的GZIP压缩。 --------------------编程问答-------------------- --------------------编程问答-------------------- 房子打个0.1折,我可以借钱首付!! --------------------编程问答-------------------- --------------------编程问答-------------------- 学习下其他人怎么做的 --------------------编程问答-------------------- --------------------编程问答-------------------- 楼上比小的,貌似都拼命压缩颜色数,结果丢颜色了,把白的给丢了。

用ImageMagick吧,哪里都通用的

convert xxx.png -strip -colors N -define png:compression-level=9 yyy.png

有.net接口 --------------------编程问答-------------------- --------------------编程问答-------------------- 上面就几个3个颜色, 和一组文字
直接写代码动态生成bmp最小。。。
--------------------编程问答-------------------- --------------------编程问答-------------------- 不知道和H264有没有关系 --------------------编程问答--------------------
引用 23 楼  的回复:
看完后,我只有一个感觉,房价太贵了!

呵呵,很多人都有这个感觉吧 --------------------编程问答-------------------- --------------------编程问答-------------------- 做广告的吧? --------------------编程问答-------------------- 房价太贵伤不起啊! --------------------编程问答-------------------- 哈哈 如果房价能代码压缩下就好了 --------------------编程问答-------------------- --------------------编程问答-------------------- /**
 * GZIP压缩
 * */
public static byte[] compress(String str) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
GZIPOutputStream gOutputStream = new GZIPOutputStream(out);
gOutputStream.write(str.getBytes("UTF-8"));
gOutputStream.finish();
gOutputStream.close();
out.flush();
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();

} --------------------编程问答-------------------- LZ可以考虑GIF的特点 --------------------编程问答-------------------- --------------------编程问答-------------------- 这相当于上海中环的房价呀 --------------------编程问答-------------------- 这个知识很不错哈 --------------------编程问答-------------------- 不错不错
--------------------编程问答-------------------- 都是神呐
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,