static size_t rgb_info(const ss_t *rgb, const struct RGB_Info *ri) { if (rgb && ri) { const size_t ss = ss_size(rgb), ps = ri->bpp / 8; size_t cmax = ri->bpp == 32 ? 0xffffffff : 0xffffffff & ((1 << ri->bpp) - 1), uqp = 0, i; const char *p = ss_get_buffer_r(rgb); sb_t *bs = sb_alloc(0); sb_eval(&bs, cmax); switch (ps) { case 4: RGB_COUNT_LOOP(i, p, ss, ps, bs, cmax, uqp); break; case 3: RGB_COUNT_LOOP(i, p, ss, ps, bs, cmax, uqp); break; case 2: RGB_COUNT_LOOP(i, p, ss, ps, bs, cmax, uqp); break; case 1: RGB_COUNT_LOOP(i, p, ss, ps, bs, cmax, uqp); break; default: break; } unsigned pixels = (unsigned)(ri->width * ri->height); unsigned l = (uqp * 100) / pixels, r = ((uqp * 10000) / pixels) % 100; printf("%ix%i %i bpp, %i chn; %u px; %u unique px" " (%u.%u%%)", (int)ri->width, (int)ri->height, (int)ri->bpp, (int)ri->chn, pixels, (unsigned)uqp, l, r); if (ps == 3 || ps == 4) { size_t ur, ug, ub, ua, urg, ugb, urb; RGBC_COUNT_LOOP(i, p, ss, ps, bs, 0, ur); RGBC_COUNT_LOOP(i, p, ss, ps, bs, 0, ug); RGBC_COUNT_LOOP(i, p, ss, ps, bs, 0, ub); RGBC2_COUNT_LOOP(i, p, ss, ps, bs, 0, urg); RGBC2_COUNT_LOOP(i, p, ss, ps, bs, 1, ugb); RGBC2_COUNT_LOOP(i, p, ss, ps, bs, 2, urb); if (ps == 4) { RGBC_COUNT_LOOP(i, p, ss, ps, bs, 0, ua); } else { ua = 0; } printf("; %u ur; %u ug; %u ub; %u urg; %u ugb; %u urb;" " %u ua", (unsigned)ur, (unsigned)ug, (unsigned)ub, (unsigned)urg, (unsigned)ugb, (unsigned)urb, (unsigned)ua); } printf("\n"); } else { fprintf(stderr, "Error: no pixel data\n"); } return ss_size(rgb); }
int main(int argc, const char **argv) { if (argc < 3) return syntax_error(argv, 5); int csize = atoi(argv[1]), climit0 = atoi(argv[2]); if (csize < 1 || csize > 4) return syntax_error(argv, 6); if (climit0 < 0) return syntax_error(argv, 7); int exit_code = 0; size_t count = 0; size_t cmax = csize == 4 ? 0xffffffff : 0xffffffff & ((1 << (csize * 8)) - 1); size_t climit = climit0 ? S_MIN((size_t)climit0, cmax) : cmax; #ifdef COUNTER_USE_BITSET #define COUNTER_SET(val) sb_set(&bs, val) #define COUNTER_POPCOUNT sb_popcount(bs) sb_t *bs = sb_alloc(0); sb_eval(&bs, cmax); #else #define COUNTER_SET(val) sm_uu32_insert(&m, val, 1) #define COUNTER_POPCOUNT sm_size(m) sm_t *m = sm_alloc(SM_U32U32, 0); #endif unsigned char buf[3 * 4 * 128]; int i; ssize_t l; for (;;) { l = read(0, buf, sizeof(buf)); l = (l / csize) * csize; if (l <= 0) break; #define CNTLOOP(inc, val) \ for (i = 0; i < l; i += inc) { \ COUNTER_SET(val); \ count++; \ if (COUNTER_POPCOUNT >= climit) \ goto done; \ } switch (csize) { case 1: CNTLOOP(1, buf[i]); break; case 2: CNTLOOP(2, (size_t)(buf[i] << 8 | buf[i + 1])); break; case 3: CNTLOOP(3, (size_t)(buf[i] << 16 | buf[i + 1] << 8 | buf[i + 2])); break; case 4: CNTLOOP(4, (size_t)buf[i] << 24 | (size_t)buf[i + 1] << 16 | (size_t)buf[i + 2] << 8 | (size_t)buf[i + 3]); break; default: goto done; } #undef CNTLOOP } done: printf(FMT_ZU ", " FMT_ZU, count, COUNTER_POPCOUNT); #ifdef COUNTER_USE_BITSET sb_free(&bs); #else sm_free(&m); #endif return exit_code; }