From: Soikk <76824648+Soikk@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:59:27 +0000 (+0200) Subject: Initial commit X-Git-Url: https://git.xolatile.top/?a=commitdiff_plain;h=273dbef3da4a60a85db24bf7efd22ec411037dcf;p=soikk-pixel-count.git Initial commit --- 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))))< +#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 0000000..a9c6385 Binary files /dev/null and b/sample.png differ