#include #include /* Table of CRCs of all 8-bit messages. */ unsigned long crc_table[256]; /* Flag: has the table been computed? Initially false. */ int crc_table_computed = 0; /* Make the table for a fast CRC. */ void make_crc_table(void) { unsigned long c; int n, k; for (n = 0; n < 256; n++) { c = (unsigned long) n; for (k = 0; k < 8; k++) { if (c & 1) c = 0xedb88320L ^ (c >> 1); else c = c >> 1; } crc_table[n] = c; } crc_table_computed = 1; } /* Update a running CRC with the bytes buf[0..len-1]--the CRC should be initialized to all 1's, and the transmitted value is the 1's complement of the final running CRC (see the crc() routine below)). */ unsigned long update_crc(unsigned long crc, unsigned char *buf, int len) { unsigned long c = crc; int n; if (!crc_table_computed) make_crc_table(); for (n = 0; n < len; n++) { c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); } return c; } /* Return the CRC of the bytes buf[0..len-1]. */ void crc(unsigned char *buf, int len) { DWORD crcdata = update_crc(0xffffffffL, buf, len) ^ 0xffffffffL; for(int i = 0; i < 4; i ++) { buf[len +3 -i] = crcdata & 0xff; crcdata >>= 8; } } void main(void) { BITMAPFILEHEADER fHead; BITMAPINFOHEADER iHead; BYTE *bits; FILE *Fin = fopen("input.bmp", "rb"); fread(&fHead, sizeof(fHead), 1, Fin); fread(&iHead, sizeof(iHead), 1, Fin); bits = new BYTE[iHead.biWidth * iHead.biHeight *3]; fread(bits, iHead.biWidth * iHead.biHeight *3, 1, Fin); fclose(Fin); BYTE buffer[65536]; char *ptr = (char*)buffer; // ----------------------------------------------------------- // シグネチャ作成 sprintf(ptr, "%cPNG%c%c%c%c", 0x89, 0x0d, 0x0a, 0x1a, 0x0a); ptr += 8; // ----------------------------------------------------------- // ヘッダ作成 sprintf(ptr, "%c%c%c%c", 0,0,0,13); ptr += 4; int width = iHead.biWidth; int height = iHead.biHeight; sprintf(ptr, "IHDR" "%c%c%c%c" // width "%c%c%c%c" // height "%c%c%c%c%c", 0,0,width >> 8,width & 0xff, //200, 0,0,height >> 8, height & 0xff, //5, 8,2,0,0,0); // CRC付加 crc((BYTE*)ptr, 13+4); ptr += 13 +4 +4; // ----------------------------------------------------------- // 画像データ準備 // サイズ DWORD size = 1 +2 + 4 + height * (width*3 +1) + 4; // 無圧縮指定 1 // MODE 2 // LEN + NLEN 4 // bit data width*4 // Adler32 4 sprintf(ptr, "%c%c%c%c", 0, (size >> 16) & 0xff, (size >> 8) & 0xff, size & 0xff); ptr += 4; char *basePtr = ptr; sprintf(ptr, "IDAT"); ptr += 4; // 圧縮コードは常に同じ *ptr ++ = 0x78; // モード+チェックも同じ DWORD md = 0x78c0 % 31; if(md) md = 0x78c0 + (31-md); else md = 0x78c0; *ptr ++ = md & 0xff; // わかりにくいよ! *ptr ++ = 0x01; // 無圧縮指定 DWORD len = height * (width*3+1); if(len & 0xffff0000) { puts("画像が大きすぎます"); return; } *ptr ++ = len & 0xff; *ptr ++ = len >> 8; // LEN + NLEN len = ~len; *ptr ++ = len & 0xff; *ptr ++ = len >> 8; DWORD s1, s2; s1 = 1; s2 = 0; BYTE tempBuf[65536]; int iPtr = 0; for(int y = 0; y < height; y ++) { // 未圧縮データのチェックサムを計算(for zlib) tempBuf[iPtr ++] = 0x00; // フィルタタイプ for(int x = 0; x < width; x ++) { tempBuf[iPtr ++] = bits[(height -y -1)*width*3 + x*3 + 2]; tempBuf[iPtr ++] = bits[(height -y -1)*width*3 + x*3 + 1]; tempBuf[iPtr ++] = bits[(height -y -1)*width*3 + x*3 + 0]; } } for(int i = 0; i < iPtr; i ++) { s1 = (s1 + tempBuf[i]) % 65521; s2 = (s2 + s1) % 65521; } tempBuf[iPtr ++] = (s2 >> 8) & 0xff; tempBuf[iPtr ++] = s2 & 0xff; tempBuf[iPtr ++] = (s1 >> 8) & 0xff; tempBuf[iPtr ++] = s1 & 0xff; // データをコピー memcpy(ptr, tempBuf, iPtr); ptr += iPtr; crc((BYTE*)basePtr, size +4); ptr += 4; // ----------------------------------------------------------- // ターミネータ作成 sprintf(ptr, "%c%c%c%c", 0,0,0,0); ptr += 4; sprintf(ptr, "IEND"); // CRC付加 crc((BYTE*)ptr, 4); ptr += 8; // ----------------------------------------------------------- // 書き出し FILE *Fp = fopen("test.png", "wb"); fwrite(buffer, ((DWORD)ptr) - ((DWORD)buffer), 1, Fp); fclose(Fp); }