图像压缩_文件压缩zlib的应用

来源:互联网 发布:元数据描述的对象分类 编辑:程序博客网 时间:2024/05/16 08:05
1.JPEG要用JPEG库

http://www.xdp.it/去下个cxImage吧,提出你需要的部分代码就可以了

2.用zlib压缩文件夹

由于要用程序压缩一个文件夹,因此选用zlib库。

zlib中的例子程序zpipe.c中,给出了如何压缩一个文件,这里稍加扩展,对一个文件夹进行压缩。

说来也简单,就是将文件夹/目录下的每个文件找到并压缩到一个文件中。

源代码如下:

 
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <dos.h>
#include <direct.h>
#include <zlib.h>

#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
#  include <fcntl.h>
#  include <io.h>
#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
#  define SET_BINARY_MODE(file)
#endif

#define CHUNK 16384

//#define USE_TAG
#ifdef USE_TAG
#define COMPRESS_FILE_TAG_HEAD "<<<"
#define COMPRESS_FILE_TAG_TAIL ">>>"
#define COMPRESS_FILE_TAG_END_LEN 3    // must be strlen(COMPRESS_FILE_TAG_HEAD) = strlen(COMPRESS_FILE_TAG_TAIL)
#else
#define COMPRESS_FILE_TAG_HEAD ""
#define COMPRESS_FILE_TAG_TAIL ""
#define COMPRESS_FILE_TAG_END_LEN 0    // must be strlen(COMPRESS_FILE_TAG_HEAD) = strlen(COMPRESS_FILE_TAG_TAIL)
#endif

/**//* Compress from file source to file dest until EOF on source.
   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
   allocated for processing, Z_STREAM_ERROR if an invalid compression
   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
   version of the library linked do not match, or Z_ERRNO if there is
   an error reading or writing the files. */
static int def(FILE *source, FILE *dest, int level)
...{
    int ret, flush;
    unsigned have;
    z_stream strm;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];

    /**//* allocate deflate state */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    ret = deflateInit(&strm, level);
    if (ret != Z_OK)
        return ret;

    /**//* compress until end of file */
    do ...{
        strm.avail_in = fread(in, 1, CHUNK, source);
        if (ferror(source)) ...{
            (void)deflateEnd(&strm);
            return Z_ERRNO;
        }
        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
        strm.next_in = in;

        /**//* run deflate() on input until output buffer not full, finish
           compression if all of source has been read in */
        do ...{
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = deflate(&strm, flush);    /**//* no bad return value */
            assert(ret != Z_STREAM_ERROR);  /**//* state not clobbered */
            have = CHUNK - strm.avail_out;
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) ...{
                (void)deflateEnd(&strm);
                return Z_ERRNO;
            }
        } while (strm.avail_out == 0);
        assert(strm.avail_in == 0);     /**//* all input will be used */

        /**//* done when last data in file processed */
    } while (flush != Z_FINISH);
    assert(ret == Z_STREAM_END);        /**//* stream will be complete */

    /**//* clean up and return */
    (void)deflateEnd(&strm);
    return Z_OK;
}

/**//* Decompress from file source to file dest until stream ends or EOF.
   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
   allocated for processing, Z_DATA_ERROR if the deflate data is
   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
   the version of the library linked do not match, or Z_ERRNO if there
   is an error reading or writing the files. */
static int inf(FILE *source, FILE *dest)
...{
    int ret;
    unsigned have;
    z_stream strm;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];

    /**//* allocate inflate state */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);
    if (ret != Z_OK)
        return ret;

    /**//* decompress until deflate stream ends or end of file */
    do ...{
        strm.avail_in = fread(in, 1, CHUNK, source);
        if (ferror(source)) ...{
            (void)inflateEnd(&strm);
            return Z_ERRNO;
        }
        if (strm.avail_in == 0)
            break;
        strm.next_in = in;

        /**//* run inflate() on input until output buffer not full */
        do ...{
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = inflate(&strm, Z_NO_FLUSH);
            assert(ret != Z_STREAM_ERROR);  /**//* state not clobbered */
            switch (ret) ...{
            case Z_NEED_DICT:
                ret = Z_DATA_ERROR;     /**//* and fall through */
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                (void)inflateEnd(&strm);
                return ret;
            }
            have = CHUNK - strm.avail_out;
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) ...{
                (void)inflateEnd(&strm);
                return Z_ERRNO;
            }
        } while (strm.avail_out == 0);

        /**//* done when inflate() says it's done */
    } while (ret != Z_STREAM_END);

    /**//* clean up and return */
    (void)inflateEnd(&strm);
    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

/**//* report a zlib or i/o error */
static void zerr(int ret)
...{
    fputs("zpipe: ", stderr);
    switch (ret) ...{
    case Z_ERRNO:
        if (ferror(stdin))
            fputs("error reading stdin ", stderr);
        if (ferror(stdout))
            fputs("error writing stdout ", stderr);
        break;
    case Z_STREAM_ERROR:
        fputs("invalid compression level ", stderr);
        break;
    case Z_DATA_ERROR:
        fputs("invalid or incomplete deflate data ", stderr);
        break;
    case Z_MEM_ERROR:
        fputs("out of memory ", stderr);
        break;
    case Z_VERSION_ERROR:
        fputs("zlib version mismatch! ", stderr);
    }
}

    以上就是zpipe.c的几个主要函数:def()、inf()和zerr(),def()是压缩函数,主要使用了zlib的deflate()接口;inf()是压缩函数,主要使用了zlib的inflate()接口;zerr()是错误打印函数。

static int write_zfile_file_header(const char *file,FILE *zfile)
{
    int len;

    len = strlen(file);
    if (fwrite(COMPRESS_FILE_TAG_HEAD, 1, COMPRESS_FILE_TAG_END_LEN, zfile) != COMPRESS_FILE_TAG_END_LEN || ferror(zfile)) 
    {
        fprintf(stderr,"When writing file or dir header to zfile: write error. ");
        return 1;
    }
    if (fwrite(file, 1, len, zfile) != len|| ferror(zfile)) 
    {
        fprintf(stderr,"When writing file or dir header to zfile: write error. ");
        return 1;
    }
    if (fwrite(COMPRESS_FILE_TAG_TAIL, 1, COMPRESS_FILE_TAG_END_LEN, zfile) != COMPRESS_FILE_TAG_END_LEN || ferror(zfile)) 
    {
        fprintf(stderr,"When writing file or dir header to zfile: write error. ");
        return 1;
    }
    return 0;
}
/* compress or decompress from stdin to stdout */
static int compress_dir(char *file_in,FILE *fd_out)
{
    FILE *fd_in;
    struct _finddata_t find_data;
    char file[128];
    long lf;
    int ret;

    write_zfile_file_header(file_in,fd_out);
    sprintf(file,"%s%s",file_in,"/*");
    if((lf = _findfirst(file,&find_data))==-1l)    // LOOKOUT: not eleven, but one and lowercase 'L'
    {
        fprintf(stdout,"file not found. ");
    }
    else
    {
         do 
         {
             if(!strcmp(find_data.name,".") || !strcmp(find_data.name,".."))
                 continue;
            fprintf(stdout,"%s",find_data.name);
            sprintf(file,"%s%s%s",file_in,"/",find_data.name);
            if(find_data.attrib & _A_SUBDIR)
            {
                fprintf(stdout," ---directory--- ");
                ret = compress_dir(file,fd_out);
            }
            else
            {
                write_zfile_file_header(file,fd_out);
                if(access(file, 2) != 0)    //W_OK=2
                {
                    int attrib;
                    
                    attrib = _chmod(file,0);
                    _chmod(file,1,attrib & ~_A_RDONLY);
                    fprintf(stderr,"When writing file:  No privilege to write file %s. ",file);
                    return -1;
                }
                fd_in = fopen(file,"rb+");
                   SET_BINARY_MODE(fd_in);
                ret = def(fd_in, fd_out, Z_DEFAULT_COMPRESSION);

                if (ret != Z_OK)
                    zerr(ret);
                else
                    fprintf(stdout," zip over ");
                fclose(fd_in);
            }
        }while( _findnext(lf, &find_data ) == 0 );
    }
    return 0;
}
int main(int argc, char **argv)
{
    struct _finddata_t find_data;
    FILE *fd_in;
    FILE *fd_out;
    const char *file_dir;
    char file_out[100];
    int ret;
    
     if (argc == 2) 
    {
        file_dir = argv[1];
        if(_findfirst(file_dir,&find_data)==-1l)    // LOOKOUT: not eleven, but one and lowercase 'L'
        {
            fprintf(stderr,"File or dir %s not found. ",file_dir);
            return 1;
        }
        if(find_data.attrib & _A_SUBDIR)
        {
            sprintf(file_out,"%s%s",file_dir,".z");
            fd_out = fopen(file_out,"wb+");
            SET_BINARY_MODE(fd_out);
            
            fprintf(stdout,"Dir %s being Compressed ... ",file_dir);
            ret = compress_dir(file_dir,fd_out);
            fclose(fd_out);
        }
        else
        {
            fprintf(stdout,"File %s being Compressed ... ",file_dir);
            sprintf(file_out,"%s%s",file_dir,".z");
            fd_in = fopen(file_dir,"rb+");
            fd_out = fopen(file_out,"wb+");
               SET_BINARY_MODE(fd_in);
            SET_BINARY_MODE(fd_out);
            ret = def(fd_in, fd_out, Z_DEFAULT_COMPRESSION);
            fclose(fd_in);
            fclose(fd_out);
        }
        if (ret != 0)
        {
            fprintf(stderr,"Compress Error !!!!!!!!!!!!!! ");
            zerr(ret);
        }
        else
            fprintf(stdout,"Compress OK--------------- ");
    }
    else {
        fprintf(stdout,"zod usage: zod [file]/[directory] ");
    }
    getch();

    return 0;
}

    以上就是主要的目录压缩代码,主要是将目录/文件的名称写入后,紧跟着压缩后的数据

    这里只提供了压缩代码,解压代码也依次逆向做出;在解压的时候,有个问题:怎样知道压缩数据开始?这里提供了USE_TAG进行分隔,若诸位有更好的方法,请告诉我。

    注意:这种格式并不通用,要根据你的实际格式要求进行压缩!

    仅供参考。 

http://blog.csdn.net/spacetiller/article/details/1867931


3. 

VC中使用zlib压缩目录结构生成zip文件

注:如果对使用库没有限制的话,推荐使用另外的封装好的库更加方便,比如codeproject上可以找到的ZipUtils等(http://www.codeproject.com/KB/files/zip_utils.aspx)。

 

    使用zlib将文件夹压缩成zip文件时,需要自己读取文件然后写入zip文件。利用官方下载的zlib包中包含的contrib/minizip/zip.h和zip.c代码提供的函数,可以很容易实现这个功能。

    zip.h和zip.c函数接口介绍:
1. zipOpen  打开、创建zip文件
2. zipOpenNewFileInZip  在zip文件中创建新文件
3. zipWriteInFileInZip  将数据写入zip文件中的文件里
4. zipCloseFileInZip    关闭zip文件中的文件
5. zipClose  关闭zip文件

    在VC中将某个目录下的所有文件(包括子目录、空目录)压缩到一个zip文件中的代码如下:

 

[cpp] view plaincopy
  1. //code by MulinB  
  2. //2011-04-28  
  3.   
  4. #define UNICODE  
  5. #define _UNICODE  
  6.   
  7. #include <atlconv.h>  //for W2CA  
  8. #include "zlib/contrib/minizip/zip.h"  
  9.   
  10.   
  11. //最终接口:从某个目录创建zip文件  
  12. void CreateZipFromDir(const CString& dirName, const CString& zipFileName);  
  13.   
  14.   
  15. //将文件添加到zip文件中,注意如果源文件srcFile为空则添加空目录  
  16. //fileNameInZip: 在zip文件中的文件名,包含相对路径  
  17. void AddFileToZip(zipFile zf, const char* fileNameInZip, const char* srcFile)  
  18. {  
  19.   FILE* srcfp = NULL;  
  20.   
  21.   //初始化写入zip的文件信息  
  22.   zip_fileinfo zi;  
  23.   zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =  
  24.   zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;  
  25.   zi.dosDate = 0;  
  26.   zi.internal_fa = 0;  
  27.   zi.external_fa = 0;  
  28.   
  29.   //如果srcFile为空,加入空目录  
  30.   char new_file_name[MAX_PATH];  
  31.   memset(new_file_name, 0, sizeof(new_file_name));  
  32.   strcat(new_file_name, fileNameInZip);  
  33.   if (srcFile == NULL)  
  34.   {  
  35.       strcat(new_file_name, "/");  
  36.   }  
  37.     
  38.   //在zip文件中创建新文件  
  39.   zipOpenNewFileInZip(zf, new_file_name, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);  
  40.   
  41.   if (srcFile != NULL)  
  42.   {  
  43.       //打开源文件  
  44.       srcfp = fopen(srcFile, "rb");  
  45.       if (srcfp == NULL)  
  46.       {  
  47.           MessageBox(_T("无法添加文件") + CString(srcFile) + _T("!"));  
  48.           zipCloseFileInZip(zf); //关闭zip文件  
  49.           return;  
  50.       }  
  51.   
  52.       //读入源文件并写入zip文件  
  53.       char buf[100*1024]; //buffer  
  54.       int numBytes = 0;  
  55.       while( !feof(srcfp) )  
  56.       {  
  57.           numBytes = fread(buf, 1, sizeof(buf), srcfp);  
  58.           zipWriteInFileInZip(zf, buf, numBytes);  
  59.           if( ferror(srcfp) )  
  60.               break;  
  61.       }  
  62.   
  63.       //关闭源文件  
  64.       fclose(srcfp);  
  65.   }  
  66.   
  67.   //关闭zip文件  
  68.   zipCloseFileInZip(zf);  
  69. }  
  70.   
  71.   
  72. //递归添加子目录到zip文件  
  73. void CollectFilesInDirToZip(zipFile zf, const CString& strPath, const CString& parentDir)  
  74. {  
  75.   USES_CONVERSION; //for W2CA  
  76.     
  77.   CString strRelativePath;  
  78.   CFileFind finder;   
  79.   BOOL bWorking = finder.FindFile(strPath + _T("//*.*"));  
  80.   while(bWorking)   
  81.   {   
  82.       bWorking = finder.FindNextFile();   
  83.       if(finder.IsDots())  
  84.           continue;   
  85.         
  86.       if (parentDir == _T(""))  
  87.           strRelativePath = finder.GetFileName();  
  88.       else  
  89.           strRelativePath = parentDir + _T("//") + finder.GetFileName(); //生成在zip文件中的相对路径  
  90.     
  91.       if(finder.IsDirectory())  
  92.       {  
  93.           AddFileToZip(zf, W2CA(strRelativePath), NULL); //在zip文件中生成目录结构  
  94.           CollectFilesInDirToZip(zf, finder.GetFilePath(), strRelativePath); //递归收集子目录文件  
  95.           continue;  
  96.       }  
  97.         
  98.       AddFileToZip(zf, W2CA(strRelativePath), W2CA(finder.GetFilePath())); //将文件添加到zip文件中  
  99.   }  
  100. }  
  101.   
  102.   
  103. //最终接口:从某个目录创建zip文件  
  104. void CreateZipFromDir(const CString& dirName, const CString& zipFileName)  
  105. {  
  106.   USES_CONVERSION; //使用W2CA转换unicode字符集  
  107.   zipFile newZipFile = zipOpen(W2CA(zipFileName), APPEND_STATUS_CREATE); //创建zip文件  
  108.   if (newZipFile == NULL)  
  109.   {  
  110.     MessageBox(_T("无法创建zip文件!"));  
  111.     return;  
  112.   }  
  113.     
  114.   CollectFilesInDirToZip(newZipFile, dirName, _T(""));  
  115.   zipClose(newZipFile, NULL); //关闭zip文件  
  116. }  

http://blog.csdn.net/mulinb/article/details/6393139

4.zlib也可以在内存中对数据进行压缩和解压缩,参考:
http://hispider.googlecode.com/svn/trunk/devel/hispider/src/utils/zstream.c


http://www.cppblog.com/woaidongmao/archive/2011/06/05/148089.html

原创粉丝点击