| 1171 | // that the PNG file produced will not be compressed any. |
| 1172 | |
| 1173 | flag WritePNG(CONST Bitmap *b, FILE *file) |
| 1174 | { |
| 1175 | dword rglCrc[256], crc, dwT, dwAdler; |
| 1176 | int n, k, ib = 0, x, y, s1 = 1, s2 = 0, i; |
| 1177 | byte rgbHead[13], *rgb; |
| 1178 | KV kv; |
| 1179 | |
| 1180 | // Initialize CRC table for chunk CRC's. |
| 1181 | for (n = 0; n < 256; n++) { |
| 1182 | crc = n; |
| 1183 | for (k = 0; k < 8; k++) |
| 1184 | crc = (crc & 1) ? (0xEDB88320L ^ (crc >> 1)) : (crc >> 1); |
| 1185 | rglCrc[n] = crc; |
| 1186 | } |
| 1187 | |
| 1188 | // PNG signature |
| 1189 | CONST byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; |
| 1190 | fwrite(png_signature, 1, 8, file); |
| 1191 | |
| 1192 | // IHDR chunk |
| 1193 | dwT = LFlipB(b->x); |
| 1194 | CopyRgb((pbyte)&dwT, rgbHead, 4); |
| 1195 | dwT = LFlipB(b->y); |
| 1196 | CopyRgb((pbyte)&dwT, rgbHead + 4, 4); |
| 1197 | rgbHead[8] = 8; // Bit depth |
| 1198 | rgbHead[9] = 2; // Color type: Truecolor (RGB) |
| 1199 | rgbHead[10] = 0; // Compression method |
| 1200 | rgbHead[11] = 0; // Filter method |
| 1201 | rgbHead[12] = 0; // Interlace method |
| 1202 | WritePNGChunk(file, "IHDR", rgbHead, 13, rglCrc); |
| 1203 | |
| 1204 | // Deflate block (no compression) |
| 1205 | int cbRow, cbDataBmp, cRowBlock, cBlock, iBlock, cbBlock; |
| 1206 | cbRow = b->x*cbPixelK + 1; |
| 1207 | cbDataBmp = cbRow * b->y; |
| 1208 | cRowBlock = 65535 / cbRow; |
| 1209 | cBlock = (b->y + (cRowBlock - 1)) / cRowBlock; |
| 1210 | |
| 1211 | rgb = PAllocate(2 + 5*cBlock + cbDataBmp + 4, |
| 1212 | "PNG data"); // zlib header + deflate + data + adler32 |
| 1213 | if (rgb == NULL) |
| 1214 | return fFalse; |
| 1215 | rgb[ib++] = 0x78; // Zlib header for no compression |
| 1216 | rgb[ib++] = 0x01; |
| 1217 | |
| 1218 | for (iBlock = 0; iBlock < cBlock; iBlock++) { |
| 1219 | // Uncompressed deflate block |
| 1220 | cbBlock = cbRow * ((iBlock+1)*cRowBlock <= b->y ? cRowBlock : |
| 1221 | b->y - iBlock*cRowBlock); |
| 1222 | rgb[ib++] = (iBlock >= cBlock-1); // 0x1 for final block, no compression |
| 1223 | rgb[ib++] = cbBlock & 0xff; |
| 1224 | rgb[ib++] = (cbBlock >> 8) & 0xff; |
| 1225 | rgb[ib++] = ~cbBlock & 0xff; |
| 1226 | rgb[ib++] = (~cbBlock >> 8) & 0xff; |
| 1227 | |
| 1228 | for (y = iBlock*cRowBlock; y < (iBlock+1)*cRowBlock && y < b->y; y++) { |
| 1229 | rgb[ib++] = 0; |
| 1230 | for (x = 0; x < b->x; x++) { |
no test coverage detected