From 273dbef3da4a60a85db24bf7efd22ec411037dcf Mon Sep 17 00:00:00 2001 From: Soikk <76824648+Soikk@users.noreply.github.com> Date: Wed, 22 Jun 2022 22:59:27 +0200 Subject: [PATCH] Initial commit --- README.md | 9 +++ decompress.c | 131 ++++++++++++++++++++++++++++++++++++++++++ download.png | Bin 0 -> 30724 bytes pixel-count.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++ sample.png | Bin 0 -> 2803 bytes 5 files changed, 293 insertions(+) create mode 100644 README.md create mode 100644 decompress.c create mode 100644 download.png create mode 100644 pixel-count.c create mode 100644 sample.png diff --git a/README.md b/README.md new file mode 100644 index 0000000..1854ed1 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Pixel count + Counts the number of pixels of one color in a PNG image encoded in RBG. + Preferably with just one IDAT chunk. + + Built with + + gcc pixel-count.c -lz [-lm] + + lm flag is optional, you might or might not need to link the math library \ No newline at end of file diff --git a/decompress.c b/decompress.c new file mode 100644 index 0000000..dae888d --- /dev/null +++ b/decompress.c @@ -0,0 +1,131 @@ +/* + +Not implemented yet + +Currently using zlib's decompress (sane) + + + + + +uint8_t getCM(uint8_t b){ + uint8_t r = b<<4; + return r>>4; +} + +uint8_t getCINFO(uint8_t b){ + return b>>4; +} + +bool validateCMFFLG(uint8_t CMF, uint8_t FLG){ + uint16_t CMFFLGcheck = (CMF<<8) + FLG; + return getCM(CMF) == 8 && CMFFLGcheck%31 == 0; +} + +typedef bool bit; + + +bool getBit(int n, int bit){ + return n & (1 << bit); +} + +void printBinary(uint8_t n){ + for(int i = 7; i >= 0; --i) + printf("%d", getBit(n, i)); +} + +uint8_t reverseBits(uint8_t n){ + uint8_t r = 0; + for(int i = 0; i < 8; ++i) + r |= ((bool)(n&(1<<(7-i))))<Z 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

SJY~qgU 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 +#include +#include +#include +#include +#include "zlib.h" + +#define HSIZE 8 +#define CSIZE 4 + + +int byteArrayEquals(uint8_t *b1, uint8_t *b2, uint32_t size){ + uint32_t i = 0; + while(i < size && b1[i] == b2[i]) + ++i; + return i == size; +} + +uint8_t paethPredictor(uint8_t a, uint8_t b, uint8_t c){ + uint8_t p = (a + b - c)%256; // initial estimate + uint8_t pa = abs(p - a); // distances to a, b, c + uint8_t pb = abs(p - b); + uint8_t pc = abs(p - c); + // return nearest of a,b,c, + // breaking ties in order a,b,c. + if(pa <= pb && pa <= pc) + return a; + else if(pb <= pc) + return b; + else + return c; +} + +bool matchRGB(uint8_t c1[3], uint8_t c2[3]){ + return (c1[0] == c2[0]) && (c1[1] == c2[1]) && (c1[2] == c2[2]); +} + + +uint8_t PNG[HSIZE] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; +uint8_t IHDR[CSIZE] = {0x49, 0x48, 0x44, 0x52}; +uint8_t IDAT[CSIZE] = {0x49, 0x44, 0x41, 0x54}; +uint8_t IEND[CSIZE] = {0x49, 0x45, 0x4E, 0x44}; + + +int main(){ + + uint32_t pixels = 0; + + FILE *fp = fopen("download.png", "rb"); // File to read + uint8_t red[3] = {0xFF, 0x00, 0x00}; // Color to look for + + // Read PNG header + uint8_t header[HSIZE]; + fread(header, sizeof(uint8_t), HSIZE, fp); + if(!byteArrayEquals(header, PNG, HSIZE)){ + fprintf(stderr, "Invalid PNG signature\n"); + fclose(fp); + return 0; + } + + uint32_t width = 0, height = 0; + uint8_t bitDepth, colorType, compressionMethod, filterMethod, interlaceMethod; + + // Start reading file + while(!feof(fp)){ + + uint8_t lenbuf[CSIZE], ctype[CSIZE], crcbuf[CSIZE]; + + // Read length of chunk + fread(lenbuf, sizeof(uint8_t), CSIZE, fp); + uint32_t len = 0; + for(int i = 0; i < CSIZE; ++i){ + len += lenbuf[i]<<(8*(3-i)); + } + uint8_t *data = calloc(len, sizeof(uint8_t)); + + // Read chunk type + fread(ctype, sizeof(uint8_t), CSIZE, fp); + + // Read data according to type + fread(data, sizeof(uint8_t), len, fp); + if(byteArrayEquals(ctype, IHDR, CSIZE)){ + for(int i = 0; i < 4; ++i){ + width += data[i]<<(8*(3-i)); + height += data[i+4]<<(8*(3-i)); + } + bitDepth = data[8]; + colorType = data[9]; + compressionMethod = data[10]; + filterMethod = data[11]; + interlaceMethod = data[12]; + }else if(byteArrayEquals(ctype, IDAT, CSIZE)){ + + // Only implementing RGB + if(colorType == 2){ + + uint8_t *d = malloc(height*(1 + width*3)*sizeof(uint8_t)); + uLongf nlen; + uncompress((Bytef *)d, &nlen, (Bytef *)data, len); + + for(uint16_t i = 0; i < height; ++i){ + + uint8_t color[3] = {0x00, 0x00, 0x00}; + uint8_t filterType = d[i*(1+width*3) + 0]; + uint8_t bpp = 3*(bitDepth/8); + + for(uint16_t j = 1; j < 1+width*3; ++j){ + + uint8_t ant = (j-bpp < 1) ? 0 : d[i*(1+width*3) + j-bpp]; + uint8_t prev = (i == 0) ? 0 : d[(i-1)*(1+width*3) + j]; + uint8_t antprev = (j-bpp < 1 || i == 0) ? 0 : d[(i-1)*(1+width*3) + j-bpp]; + + switch(filterType){ + case 1: + d[i*(1+width*3) + j] = (d[i*(1+width*3) + j] + ant)%256; + break; + case 2: + d[i*(1+width*3) + j] = (d[i*(1+width*3) + j] + prev)%256; + break; + case 3: + d[i*(1+width*3) + j] = (d[i*(1+width*3) + j] + (uint8_t)floor((ant + prev)/2))%256; + break; + case 4: + d[i*(1+width*3) + j] = (d[i*(1+width*3) + j] + paethPredictor(ant, prev, antprev))%256; + break; + } + + // Stores pixels in pixels array + color[(j-1)%3] = d[i*(1+width*3) + j]; + + // Counts red pixels + if(j%3 == 0 && matchRGB(color, red)){ + ++pixels; + } + } + } + } + } + + // Read CRC checksum + fread(crcbuf, sizeof(uint8_t), CSIZE, fp); + + if(byteArrayEquals(ctype, IEND, CSIZE)){ + break; + } + } + + fclose(fp); + + printf("Pixels: %d\n", pixels); + + return 0; +} \ No newline at end of file diff --git a/sample.png b/sample.png new file mode 100644 index 0000000000000000000000000000000000000000..a9c6385f56e44192c67d94b7589245223fdbaf90 GIT binary patch literal 2803 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