Chinaunix首页 | 论坛 | 博客
  • 博客访问: 905779
  • 博文数量: 201
  • 博客积分: 8078
  • 博客等级: 中将
  • 技术积分: 2162
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-20 17:22
文章分类

全部博文(201)

文章存档

2013年(3)

2012年(11)

2011年(34)

2010年(25)

2009年(51)

2008年(77)

分类: WINDOWS

2011-01-09 18:09:19


#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <winsock.h>
#include "zlib.h"

#define CHUNK 65536

typedef struct
{
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
}__attribute__((packed)) bitmap_file_header_t;

typedef struct
{
    uint32_t biSize;
    int32_t biWidth;
    int32_t biHeight;
    uint16_t biPlanes;
    uint16_t biBitCount;
    uint32_t biCompression;
    uint32_t biSizeImage;
    int32_t biXPelsPerMeter;
    int32_t biYPelsPerMeter;
    uint32_t biClrUsed;
    uint32_t biClrImportant;
} bitmap_info_header_t;

struct png_header_t {
    int width;
    int height;
    unsigned char bitdepth;
    unsigned char colortype;
    unsigned char comdivssion;
    unsigned char filter;
    unsigned char interlace;
} __attribute__((packed));

int png_chunks_list(FILE * file);
int png_chunk1_read(FILE * file);
int png_header_read(FILE * file);
int png_header_print(struct png_header_t * pnghdr, size_t len, int crc);

static int len_src, len_dst;
static char * png_src, * bmp_dst;
static FILE * bmp_file = NULL;
static struct png_header_t png_hdr;

int png_tranafer_init(void);
int png_tranafer_clean(void);
int png_tranafer_dosave(const char * path);

int main(int argc, char *argv[])
{
    int err;
    FILE * file;
    const char * path = argv[1];

    if (argc != 2) {
        printf("usage: %s filename\n", argv[0]);
        return 0;
    }

    file = fopen(path, "rb");
    assert(file != NULL);

    printf("\n\tFile Name : [%s]\n\n", path);
    if (png_header_read(file)) {
        png_tranafer_init();
         png_chunks_list(file);
        png_tranafer_dosave("kitty.bmp");
    }

    png_tranafer_clean();
    fclose(file);
    return 0;
}

int bitmap_byte_per_pixel(int colortype, int bitdepth)
{
    int bitperpixel, byteperline1, byteperpixel;

    bitperpixel = 0;
    if (colortype & 0x0001)
        bitperpixel = bitdepth;

    if (colortype & 0x0004)
        bitperpixel += bitdepth;

    if (colortype & 0x0002)
        bitperpixel += (bitdepth * 3);

    printf("type: %d, depth: %d, %d\n", colortype, bitdepth, bitperpixel);
    return (bitperpixel / 8);
}

int bitmap_getsize()
{
    int line = bitmap_byte_per_pixel(png_hdr.colortype, png_hdr.bitdepth);
    line = (line * png_hdr.width + 3);
    return (line & ~0x3) * png_hdr.height;
}

int png_tranafer_init(void)
{
    int byteperpixel, byteperline;
    byteperpixel = bitmap_byte_per_pixel(png_hdr.colortype, png_hdr.bitdepth);

    byteperline = byteperpixel * png_hdr.width;
    bmp_dst = malloc(byteperline * png_hdr.height + png_hdr.height);
    len_dst = byteperline * png_hdr.height + png_hdr.height;

    png_src = malloc(byteperline * png_hdr.height + png_hdr.height);
    len_src = 0;

    return 0;
}

int png_tranafer_dosave(const char * path)
{
    int err;
    int byteperpixel;

    FILE * file;
    bitmap_file_header_t hdr_file;
    bitmap_info_header_t hdr_info;

    memcpy(&hdr_file.bfType, "BM", 2);
    hdr_file.bfReserved1 = 0;
    hdr_file.bfReserved2 = 0;
    hdr_file.bfOffBits = sizeof(hdr_file);
    hdr_file.bfOffBits += sizeof(hdr_info);
    hdr_file.bfSize = hdr_file.bfOffBits + bitmap_getsize();

    byteperpixel = bitmap_byte_per_pixel(png_hdr.colortype, png_hdr.bitdepth);
    hdr_info.biSize = sizeof(hdr_info);
    hdr_info.biWidth = png_hdr.width;
    hdr_info.biHeight = - png_hdr.height;
    hdr_info.biPlanes = 1;
    hdr_info.biBitCount = byteperpixel * 8;
    hdr_info.biCompression = 0;
    hdr_info.biSizeImage = bitmap_getsize();

    hdr_info.biClrUsed = 0;
    hdr_info.biClrImportant = 0;
    hdr_info.biXPelsPerMeter = 0x1075;
    hdr_info.biYPelsPerMeter = 0x1075;

    assert(len_src < len_dst);
    err = uncompress(bmp_dst, &len_dst, png_src, len_src);
    if (err == Z_OK) {
        int i;
        int line;
        char * data;

         file = fopen(path, "wb");
         fwrite(&hdr_file, sizeof(hdr_file), 1, file);
         fwrite(&hdr_info, sizeof(hdr_info), 1, file);

        data = bmp_dst;
        line = bitmap_byte_per_pixel(png_hdr.colortype, png_hdr.bitdepth);
        line = line * png_hdr.width;

        for (i = 0; i < png_hdr.height; i++) {
            fwrite(data, 1, (line + 3) & ~0x03, file);
            data += line;
            data ++;
        }

         fclose(file);
        return 0;
    }

    printf("ZLIB: %d, %d, %d\n",
             err, png_hdr.width, png_hdr.height);
    return 0;
}

int png_tranafer_clean(void)
{
    free(png_src);
    free(bmp_dst);
    return 0;
}

int png_header_read(FILE * file)
{
    int count;
    char data[8];

    int len, crc;
    int png_len[3] = {0};
    struct png_header_t pnghdr;

    unsigned char signature[8] = {
        0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a
    };

    memset(data, 0, sizeof(data));
    count = fread(data, sizeof(data), 1, file);

    if (memcmp(signature, data, sizeof(signature))) {
        return 0;
    }

    if (!fread(png_len, 8, 1, file)) {
        return 0;
    }
   
    if (memcmp(&png_len[1], "IHDR", 4)) {
        return 0;
    }

    len = htonl(png_len[0]);
       if (len != sizeof(pnghdr) ||
             !fread(&pnghdr, len, 1, file)) {
         return 0;
    }

    if (!fread(&crc, sizeof(crc), 1, file)) {
         return 0;
    }

    printf("LENGTH:[%8d] TYPE:[%s] \n", len, &png_len[1]);
    png_header_print(&pnghdr, len, crc);

    return 1;
}

int png_header_print(struct png_header_t * header, size_t len, int crc)
{
    if (len >= sizeof(png_hdr)) {
         memcpy(&png_hdr, header, sizeof(png_hdr));
        png_hdr.width = htonl(png_hdr.width);
        png_hdr.height = htonl(png_hdr.height);
         printf("\t---------- IHDR Image header ----------\n");
        printf("\tCHUNK DATA\n");
        printf("\t\tWidth (4 bytes): [%d]\n", png_hdr.width);
         printf("\t\tHeight (4 bytes): [%d]\n", png_hdr.height);
        printf("\t\tBitdepth (1 bytes): [%u]\n", png_hdr.bitdepth);
         printf("\t\tColor Type (1 bytes): [%u]\n", png_hdr.colortype);
         printf("\t\tCompression method (1 bytes): [%u]\n", png_hdr.comdivssion);
         printf("\t\tFilter method (1 bytes): [%u]\n", png_hdr.filter);
         printf("\t\tInterlace method (1 bytes): [%u]\n", png_hdr.interlace);
    }

    printf("\tCRC : %08x\n", htonl(crc));
    return 0;
}

int png_chunks_list(FILE * file)
{
    int count = 0;

    count = png_chunk1_read(file);
    while (count > 0)
        count = png_chunk1_read(file);

    return count;
}

static char bitmap[CHUNK * 512];
int png_chunk1_read(FILE * file)
{
    int err, i;
    int len, crc, olen;
    int png_len[3] = {0};
    char data[CHUNK];

    if (fread(png_len, 8, 1, file) == 1) {
         len = htonl(png_len[0]);
        if (len <= 0 || !fread(data, len, 1, file))
             return 0;

         if (fread(&crc, 4, 1, file) != 1)
             return 0;

#if 0
        printf("LENGTH:[%8d] TYPE:[%s] CRC:[%08x]\n",
                 len, &png_len[1], htonl(crc));
#endif

        if (memcmp(&png_len[1], "IDAT", 4))
            return 1;

         printf("CHUNK LENGTH: %d, CRC:[%08x]\n", len, htonl(crc));
        memcpy(png_src + len_src, data, len);
        len_src += len;

        return 1;
    }

    return 0;
}


阅读(7633) | 评论(0) | 转发(0) |
0

上一篇:JSON分析处理

下一篇:编写更好的代码

给主人留下些什么吧!~~