📄 tiffmedian.c
字号:
iptr = &histogram[ir][ig][ptr->bmin]; for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) *histp += *iptr++; } histp++; } first = ptr->gmin; last = ptr->gmax; break; case BLUE: histp = &hist2[ptr->bmin]; for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) { *histp = 0; for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) { iptr = &histogram[ir][ptr->gmin][ib]; for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) { *histp += *iptr; iptr += B_LEN; } } histp++; } first = ptr->bmin; last = ptr->bmax; break; } /* find median point */ sum2 = ptr->total / 2; histp = &hist2[first]; sum = 0; for (i = first; i <= last && (sum += *histp++) < sum2; ++i) ; if (i == first) i++; /* Create new box, re-allocate points */ new = freeboxes; freeboxes = new->next; if (freeboxes) freeboxes->prev = NULL; if (usedboxes) usedboxes->prev = new; new->next = usedboxes; usedboxes = new; histp = &hist2[first]; for (sum1 = 0, j = first; j < i; j++) sum1 += *histp++; for (sum2 = 0, j = i; j <= last; j++) sum2 += *histp++; new->total = sum1; ptr->total = sum2; new->rmin = ptr->rmin; new->rmax = ptr->rmax; new->gmin = ptr->gmin; new->gmax = ptr->gmax; new->bmin = ptr->bmin; new->bmax = ptr->bmax; switch (axis) { case RED: new->rmax = i-1; ptr->rmin = i; break; case GREEN: new->gmax = i-1; ptr->gmin = i; break; case BLUE: new->bmax = i-1; ptr->bmin = i; break; } shrinkbox(new); shrinkbox(ptr);}static voidshrinkbox(Colorbox* box){ register uint32 *histp; register int ir, ig, ib; if (box->rmax > box->rmin) { for (ir = box->rmin; ir <= box->rmax; ++ir) for (ig = box->gmin; ig <= box->gmax; ++ig) { histp = &histogram[ir][ig][box->bmin]; for (ib = box->bmin; ib <= box->bmax; ++ib) if (*histp++ != 0) { box->rmin = ir; goto have_rmin; } } have_rmin: if (box->rmax > box->rmin) for (ir = box->rmax; ir >= box->rmin; --ir) for (ig = box->gmin; ig <= box->gmax; ++ig) { histp = &histogram[ir][ig][box->bmin]; ib = box->bmin; for (; ib <= box->bmax; ++ib) if (*histp++ != 0) { box->rmax = ir; goto have_rmax; } } }have_rmax: if (box->gmax > box->gmin) { for (ig = box->gmin; ig <= box->gmax; ++ig) for (ir = box->rmin; ir <= box->rmax; ++ir) { histp = &histogram[ir][ig][box->bmin]; for (ib = box->bmin; ib <= box->bmax; ++ib) if (*histp++ != 0) { box->gmin = ig; goto have_gmin; } } have_gmin: if (box->gmax > box->gmin) for (ig = box->gmax; ig >= box->gmin; --ig) for (ir = box->rmin; ir <= box->rmax; ++ir) { histp = &histogram[ir][ig][box->bmin]; ib = box->bmin; for (; ib <= box->bmax; ++ib) if (*histp++ != 0) { box->gmax = ig; goto have_gmax; } } }have_gmax: if (box->bmax > box->bmin) { for (ib = box->bmin; ib <= box->bmax; ++ib) for (ir = box->rmin; ir <= box->rmax; ++ir) { histp = &histogram[ir][box->gmin][ib]; for (ig = box->gmin; ig <= box->gmax; ++ig) { if (*histp != 0) { box->bmin = ib; goto have_bmin; } histp += B_LEN; } } have_bmin: if (box->bmax > box->bmin) for (ib = box->bmax; ib >= box->bmin; --ib) for (ir = box->rmin; ir <= box->rmax; ++ir) { histp = &histogram[ir][box->gmin][ib]; ig = box->gmin; for (; ig <= box->gmax; ++ig) { if (*histp != 0) { box->bmax = ib; goto have_bmax; } histp += B_LEN; } } }have_bmax: ;}static C_cell *create_colorcell(int red, int green, int blue){ register int ir, ig, ib, i; register C_cell *ptr; int mindist, next_n; register int tmp, dist, n; ir = red >> (COLOR_DEPTH-C_DEPTH); ig = green >> (COLOR_DEPTH-C_DEPTH); ib = blue >> (COLOR_DEPTH-C_DEPTH); ptr = (C_cell *)_TIFFmalloc(sizeof (C_cell)); *(ColorCells + ir*C_LEN*C_LEN + ig*C_LEN + ib) = ptr; ptr->num_ents = 0; /* * Step 1: find all colors inside this cell, while we're at * it, find distance of centermost point to furthest corner */ mindist = 99999999; for (i = 0; i < num_colors; ++i) { if (rm[i]>>(COLOR_DEPTH-C_DEPTH) != ir || gm[i]>>(COLOR_DEPTH-C_DEPTH) != ig || bm[i]>>(COLOR_DEPTH-C_DEPTH) != ib) continue; ptr->entries[ptr->num_ents][0] = i; ptr->entries[ptr->num_ents][1] = 0; ++ptr->num_ents; tmp = rm[i] - red; if (tmp < (MAX_COLOR/C_LEN/2)) tmp = MAX_COLOR/C_LEN-1 - tmp; dist = tmp*tmp; tmp = gm[i] - green; if (tmp < (MAX_COLOR/C_LEN/2)) tmp = MAX_COLOR/C_LEN-1 - tmp; dist += tmp*tmp; tmp = bm[i] - blue; if (tmp < (MAX_COLOR/C_LEN/2)) tmp = MAX_COLOR/C_LEN-1 - tmp; dist += tmp*tmp; if (dist < mindist) mindist = dist; } /* * Step 3: find all points within that distance to cell. */ for (i = 0; i < num_colors; ++i) { if (rm[i] >> (COLOR_DEPTH-C_DEPTH) == ir && gm[i] >> (COLOR_DEPTH-C_DEPTH) == ig && bm[i] >> (COLOR_DEPTH-C_DEPTH) == ib) continue; dist = 0; if ((tmp = red - rm[i]) > 0 || (tmp = rm[i] - (red + MAX_COLOR/C_LEN-1)) > 0 ) dist += tmp*tmp; if ((tmp = green - gm[i]) > 0 || (tmp = gm[i] - (green + MAX_COLOR/C_LEN-1)) > 0 ) dist += tmp*tmp; if ((tmp = blue - bm[i]) > 0 || (tmp = bm[i] - (blue + MAX_COLOR/C_LEN-1)) > 0 ) dist += tmp*tmp; if (dist < mindist) { ptr->entries[ptr->num_ents][0] = i; ptr->entries[ptr->num_ents][1] = dist; ++ptr->num_ents; } } /* * Sort color cells by distance, use cheap exchange sort */ for (n = ptr->num_ents - 1; n > 0; n = next_n) { next_n = 0; for (i = 0; i < n; ++i) if (ptr->entries[i][1] > ptr->entries[i+1][1]) { tmp = ptr->entries[i][0]; ptr->entries[i][0] = ptr->entries[i+1][0]; ptr->entries[i+1][0] = tmp; tmp = ptr->entries[i][1]; ptr->entries[i][1] = ptr->entries[i+1][1]; ptr->entries[i+1][1] = tmp; next_n = i; } } return (ptr);}static voidmap_colortable(void){ register uint32 *histp = &histogram[0][0][0]; register C_cell *cell; register int j, tmp, d2, dist; int ir, ig, ib, i; for (ir = 0; ir < B_LEN; ++ir) for (ig = 0; ig < B_LEN; ++ig) for (ib = 0; ib < B_LEN; ++ib, histp++) { if (*histp == 0) { *histp = -1; continue; } cell = *(ColorCells + (((ir>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) + ((ig>>(B_DEPTH-C_DEPTH)) << C_DEPTH) + (ib>>(B_DEPTH-C_DEPTH)))); if (cell == NULL ) cell = create_colorcell( ir << COLOR_SHIFT, ig << COLOR_SHIFT, ib << COLOR_SHIFT); dist = 9999999; for (i = 0; i < cell->num_ents && dist > cell->entries[i][1]; ++i) { j = cell->entries[i][0]; d2 = rm[j] - (ir << COLOR_SHIFT); d2 *= d2; tmp = gm[j] - (ig << COLOR_SHIFT); d2 += tmp*tmp; tmp = bm[j] - (ib << COLOR_SHIFT); d2 += tmp*tmp; if (d2 < dist) { dist = d2; *histp = j; } } }}/* * straight quantization. Each pixel is mapped to the colors * closest to it. Color values are rounded to the nearest color * table entry. */static voidquant(TIFF* in, TIFF* out){ unsigned char *outline, *inputline; register unsigned char *outptr, *inptr; register uint32 i, j; register int red, green, blue; inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in)); outline = (unsigned char *)_TIFFmalloc(imagewidth); for (i = 0; i < imagelength; i++) { if (TIFFReadScanline(in, inputline, i, 0) <= 0) break; inptr = inputline; outptr = outline; for (j = 0; j < imagewidth; j++) { red = *inptr++ >> COLOR_SHIFT; green = *inptr++ >> COLOR_SHIFT; blue = *inptr++ >> COLOR_SHIFT; *outptr++ = histogram[red][green][blue]; } if (TIFFWriteScanline(out, outline, i, 0) < 0) break; } _TIFFfree(inputline); _TIFFfree(outline);}#define SWAP(type,a,b) { type p; p = a; a = b; b = p; }#define GetInputLine(tif, row, bad) \ if (TIFFReadScanline(tif, inputline, row, 0) <= 0) \ bad; \ inptr = inputline; \ nextptr = nextline; \ for (j = 0; j < imagewidth; ++j) { \ *nextptr++ = *inptr++; \ *nextptr++ = *inptr++; \ *nextptr++ = *inptr++; \ }#define GetComponent(raw, cshift, c) \ cshift = raw; \ if (cshift < 0) \ cshift = 0; \ else if (cshift >= MAX_COLOR) \ cshift = MAX_COLOR-1; \ c = cshift; \ cshift >>= COLOR_SHIFT;static voidquant_fsdither(TIFF* in, TIFF* out){ unsigned char *outline, *inputline, *inptr; short *thisline, *nextline; register unsigned char *outptr; register short *thisptr, *nextptr; register uint32 i, j; uint32 imax, jmax; int lastline, lastpixel; imax = imagelength - 1; jmax = imagewidth - 1; inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in)); thisline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short)); nextline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short)); outline = (unsigned char *) _TIFFmalloc(TIFFScanlineSize(out)); GetInputLine(in, 0, goto bad); /* get first line */ for (i = 1; i <= imagelength; ++i) { SWAP(short *, thisline, nextline); lastline = (i >= imax); if (i <= imax) GetInputLine(in, i, break); thisptr = thisline; nextptr = nextline; outptr = outline; for (j = 0; j < imagewidth; ++j) { int red, green, blue; register int oval, r2, g2, b2; lastpixel = (j == jmax); GetComponent(*thisptr++, r2, red); GetComponent(*thisptr++, g2, green); GetComponent(*thisptr++, b2, blue); oval = histogram[r2][g2][b2]; if (oval == -1) { int ci; register int cj, tmp, d2, dist; register C_cell *cell; cell = *(ColorCells + (((r2>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) + ((g2>>(B_DEPTH-C_DEPTH)) << C_DEPTH ) + (b2>>(B_DEPTH-C_DEPTH)))); if (cell == NULL) cell = create_colorcell(red, green, blue); dist = 9999999; for (ci = 0; ci < cell->num_ents && dist > cell->entries[ci][1]; ++ci) { cj = cell->entries[ci][0]; d2 = (rm[cj] >> COLOR_SHIFT) - r2; d2 *= d2; tmp = (gm[cj] >> COLOR_SHIFT) - g2; d2 += tmp*tmp; tmp = (bm[cj] >> COLOR_SHIFT) - b2; d2 += tmp*tmp; if (d2 < dist) { dist = d2; oval = cj; } } histogram[r2][g2][b2] = oval; } *outptr++ = oval; red -= rm[oval]; green -= gm[oval]; blue -= bm[oval]; if (!lastpixel) { thisptr[0] += blue * 7 / 16; thisptr[1] += green * 7 / 16; thisptr[2] += red * 7 / 16; } if (!lastline) { if (j != 0) { nextptr[-3] += blue * 3 / 16; nextptr[-2] += green * 3 / 16; nextptr[-1] += red * 3 / 16; } nextptr[0] += blue * 5 / 16; nextptr[1] += green * 5 / 16; nextptr[2] += red * 5 / 16; if (!lastpixel) { nextptr[3] += blue / 16; nextptr[4] += green / 16; nextptr[5] += red / 16; } nextptr += 3; } } if (TIFFWriteScanline(out, outline, i-1, 0) < 0) break; }bad: _TIFFfree(inputline); _TIFFfree(thisline); _TIFFfree(nextline); _TIFFfree(outline);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -