📄 cmv.c~
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cmv.h"static inline int color_c(int n) { if(!n) return 0; n &= -n; int i = 0; for(; n>>=1; ++i); return i;}static inline void set_bits(int *p, int x1, int x2, int b) { if (x1 < 0 || x1 > 255 || x2 < 0 || x2 > 255 || x1 > x2) { fprintf(stderr, "threshold range error: %d %d\n", x1, x2); exit(-1); } for (; x1<=x2; ++x1) p[x1] |= b;}void cmv_init(struct cmv_data * restrict data, const char * restrict filename) { FILE *in = fopen(filename, "r"); if (in == NULL) { perror(filename); exit(-1); } int c; if (fscanf(in, "%d", &c) != 1) { fprintf(stderr, "read color_n error\n"); exit(-1); } if (c <= 0 || c > INT_BITS) { fprintf(stderr, "too many colors: %d\n", c); exit(-1); } data->color_n = c; if ((data->th = malloc(c * 6 * sizeof(int))) == NULL) { perror("malloc"); exit(-1); } memset(data->thresh, 0, sizeof(data->thresh)); int b = 1; int i; int *t; for (i=0; i<c; ++i) { t = data->th[i]; if (fscanf(in, "%d %d %d %d %d %d", t, t+1, t+2, t+3, t+4, t+5) != 6) { fprintf(stderr, "read threshold error\n"); exit(-1); } set_bits(data->thresh[0], t[0], t[1], b); set_bits(data->thresh[1], t[2], t[3], b); set_bits(data->thresh[2], t[4], t[5], b); b <<= 1; } if ((data->remap = malloc(c * sizeof(int))) == NULL) { perror("malloc"); exit(-1); } for (i=0; i<c; ++i) { if (fscanf(in, "%d", &b) != 1) { fprintf(stderr, "read remap error\n"); exit(-1); } if (b > c || b < 0) { fprintf(stderr, "invalid remap: %d\n", b); exit(-1); } data->remap[i] = b; } if ((data->clist = malloc(c * sizeof(int))) == NULL) { perror("malloc"); exit(-1); } if ((data->cmax = malloc(c * sizeof(struct reg_t *))) == NULL) { perror("malloc"); exit(-1); } if ((data->rgb = malloc((c+1) * 3 * sizeof(int))) == NULL) { perror("malloc"); exit(-1); } if (fscanf(in, "%d", &c) != 1) { fprintf(stderr, "read rgb_n error\n"); exit(-1); } if (c > data->color_n + 1 || c < 0) { fprintf(stderr, "invalid rgb_n: %d\n", c); exit(-1); } for (i=0; i<c; ++i) { if (fscanf(in, "%d", &b) != 1) { fprintf(stderr, "read rgb_i error\n"); exit(-1); } if (b > data->color_n || b < 0) { fprintf(stderr, "rgb_i invalid: %d\n", b); exit(-1); } t = data->rgb[b]; if (fscanf(in, "%d %d %d", t, t+1, t+2) != 3) { fprintf(stderr, "read rgb error\n"); exit(-1); } if (t[0] < 0 || t[0] > 255 || t[1] < 0 || t[1] > 255 || t[2] < 0 || t[2] > 255) { fprintf(stderr, "rgb invalid\n"); exit(-1); } } if (fscanf(in, "%d", &c) != 1) { fprintf(stderr, "read size_min error\n"); exit(-1); } if (c < 0) { fprintf(stderr, "size_min invalid: %d\n", c); exit(-1); } data->size_min = c; if (fscanf(in, "%d", &c) != 1) { fprintf(stderr, "read max_rle error\n"); exit(-1); } if ((data->rle = malloc(c * sizeof(struct rle_t))) == NULL) { perror("malloc"); exit(-1); } data->rle_max = c; if (fscanf(in, "%d", &c) != 1) { fprintf(stderr, "read max_reg error\n"); exit(-1); } if ((data->reg = malloc(c * sizeof(struct reg_t))) == NULL) { perror("malloc"); exit(-1); } data->reg_max = c; fclose(in);}static inline void classify(struct cmv_data * restrict data, const unsigned char * restrict py) { const unsigned char *pu = py + Y_SIZE; const unsigned char *pv = pu + U_SIZE; int *m = data->map; int i, j; for (j=0; j<H_2; ++j) { for (i=0; i<W_2; ++i) { *(m++) = data->remap[color_c(data->thresh[0][*py] & data->thresh[1][*(pu++)] & data->thresh[2][*(pv++)])]; py += 2; } *(m++) = -1; py += W; }}static inline void encode(struct cmv_data * data) { struct rle_t *r = data->rle; int *l = data->map; int *p = data->map; int y = 0; for (;;) { int *b = p; int t = *p; while (*(++p) == t); if (t == -1) { l += (W_2 + 1); // next line r->color = 0; // change color_end to 0 r->x2 = (W_2 + 1); ++r; if (++y == H_2) break; } else if (t) { // [x1, x2), true 0 is not added r->color = t; r->x1 = b - l; r->x2 = p - l; r->parent = r; ++r; } } data->rle_end = r; y = r - data->rle; if (y > data->rle_max) { fprintf(stderr, "rle overflow: %d\n", y); exit(-1); }}static inline void connect(struct cmv_data * data) { // l1: first line // l2: second line struct rle_t *l1 = data->rle; struct rle_t *l2 = data->rle; while ((l2++)->color); int y = 1; for (;;) { if (l1->color == l2->color) { if (!l1->color) { if (++y == H_2) break; } else if (l2->x1 >= l1->x1 && l2->x1 < l1->x2) { // safe l2->parent = l1->parent; } else if (l1->x1 >= l2->x1 && l1->x1 < l2->x2) { if (l1->parent > l2->parent) { // l2->parent is better ((struct rle_t *)(l1->parent))->parent = l2->parent; } else if(l1->parent < l2->parent) { // l1->parent is better ((struct rle_t *)(l2->parent))->parent = l1->parent; l2->parent = l1->parent; // base is important } } } int t = l2->x2 - l1->x2; if (t >= 0) ++l1; if (t <= 0) ++l2; } for (l1 = data->rle; l1<data->rle_end; ++l1) { if (l1->color) { l1->parent = ((struct rle_t *)(l1->parent))->parent; } }}static inline int max(int a, int b) { return(a > b ? a : b);}static inline int min(int a, int b) { return(a < b ? a : b);}static inline int sum(int x, int dx) { x <<= 1; return(dx * (x + dx - 1) >> 1);}static inline void extract(struct cmv_data * data) { struct rle_t *r = data->rle; struct reg_t *g = data->reg; int y = 0; for (;;) { if (r->color) { if (r->parent == r) { int t = r->x2 - r->x1; r->parent = g; g->color = r->color; g->x1 = r->x1; g->x2 = r->x2; g->size = t; g->y1 = y; g->y2 = y; g->cx = sum(r->x1, t); g->cy = y * t; ++g; } else { int t = r->x2 - r->x1; struct reg_t *tg = (struct reg_t *)((struct rle_t *)(r->parent))->parent; tg->x1 = min(tg->x1, r->x1); tg->x2 = max(tg->x2, r->x2); tg->size += t; tg->y2 = y; tg->cx += sum(r->x1, t); tg->cy += y * t; } } else { if (++y == H_2) break; } ++r; } data->reg_end = g; y = g - data->reg; if (y > data->reg_max) { fprintf(stderr, "reg overflow: %d\n", y); exit(-1); }}static inline void separate(struct cmv_data * data) { memset(data->clist, 0, sizeof(data->color_n * sizeof(int))); struct reg_t *g = data->reg; for (; g<data->reg_end; ++g) { int c = g->size; if (c > data->size_min) { g->cx /= c; g->cy /= c; c = g->color - 1; //cmv_ctable[c][cmv_clist[c]] = g; if (!data->clist[c]) data->cmax[c] = g; else if (g->size > data->cmax[c]->size) data->cmax[c] = g; ++data->clist[c]; } } /* int i = 0; for (; i<cdata->color_n; ++i) { if (cdata->clist[i] > MAX_RPC) { fprintf(stderr, "rpc overflow: %d\n", cdata->clist[i]); exit(-1); } } */}void cmv_process(struct cmv_data * restrict data, const unsigned char * restrict src) { classify(data, src); encode(data); connect(data); extract(data); separate(data);}void cmv_reinit(struct cmv_data * restrict data, int ch, int i, int target, int type) { if (ch < 0 || ch > 2) { fprintf(stderr, "channel error\n"); exit(-1); } i = 1 << i; if (type) data->thresh[ch][target] |= i; else data->thresh[ch][target] &= ~i;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -