bitmap 转为jpg文件_PNG图片转换成bitmap

该程序从PNG文件读取数据,将其转换为Bitmap格式,并进一步将Bitmap保存为JPG文件。通过处理PNG文件的IHDR块,解析宽度、高度、位深等信息,然后使用zlib库进行数据解压缩,最终写入到Bitmap文件中。
摘要由CSDN通过智能技术生成

#include

#include

#include

#include

#include

#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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值