📄 xvsmooth.c
字号:
axes) */ /* malloc some arrays */ lbufR = (int *) calloc((size_t) swide, sizeof(int)); lbufG = (int *) calloc((size_t) swide, sizeof(int)); lbufB = (int *) calloc((size_t) swide, sizeof(int)); pixarr = (int *) calloc((size_t) swide+1, sizeof(int)); if (!lbufR || !lbufG || !lbufB || !pixarr) { if (lbufR) free(lbufR); if (lbufG) free(lbufG); if (lbufB) free(lbufB); if (pixarr) free(pixarr); return 1; } bperpix = (is24) ? 3 : 1; for (j=0; j<=swide; j++) pixarr[j] = (j*dwide + (15*swide)/16) / swide; lastline = linecnt = pixR = pixG = pixB = 0; cptr = pic824; for (i=0; i<=shigh; i++) { ProgressMeter(0, shigh, i, "Smooth"); if ((i&15) == 0) WaitCursor(); thisline = (i * dhigh + (15*shigh)/16 ) / shigh; if ((thisline != lastline)) { /* copy a line to pic24 */ pixR = pixG = pixB = pixcnt = lastpix = 0; for (j=0, paptr=pixarr; j<=swide; j++,paptr++) { if (*paptr != lastpix) { /* write a pixel to pic24 */ if (!pixcnt) pixcnt = 1; /* NEVER happens: quiets compilers */ *pic24++ = (pixR/linecnt) / pixcnt; *pic24++ = (pixG/linecnt) / pixcnt; *pic24++ = (pixB/linecnt) / pixcnt; lastpix = *paptr; pixR = pixG = pixB = pixcnt = 0; } if (j<swide) { pixR += lbufR[j]; pixG += lbufG[j]; pixB += lbufB[j]; pixcnt++; } } lastline = thisline; xvbzero( (char *) lbufR, swide * sizeof(int)); /* clear out line bufs */ xvbzero( (char *) lbufG, swide * sizeof(int)); xvbzero( (char *) lbufB, swide * sizeof(int)); linecnt = 0; } if (i<shigh) { if (is24) { for (j=0; j<swide; j++) { lbufR[j] += *cptr++; lbufG[j] += *cptr++; lbufB[j] += *cptr++; } } else { for (j=0; j<swide; j++, cptr++) { lbufR[j] += rmap[*cptr]; lbufG[j] += gmap[*cptr]; lbufB[j] += bmap[*cptr]; } } linecnt++; } } free(lbufR); free(lbufG); free(lbufB); free(pixarr); return 0;} /********************************************/byte *DoColorDither(pic24, pic8, w, h, rmap, gmap, bmap, rdisp, gdisp, bdisp, maplen) byte *pic24, *pic8, *rmap, *gmap, *bmap, *rdisp, *gdisp, *bdisp; int w, h, maplen;{ /* takes a 24 bit picture, of size w*h, dithers with the colors in rdisp, gdisp, bdisp (which have already been allocated), and generates an 8-bit w*h image, which it returns. ignores input value 'pic8' returns NULL on error note: the rdisp,gdisp,bdisp arrays should be the 'displayed' colors, not the 'desired' colors if pic24 is NULL, uses the passed-in pic8 (an 8-bit image) as the source, and the rmap,gmap,bmap arrays as the desired colors */ byte *np, *ep, *newpic; short *cache; int r2, g2, b2; int *thisline, *nextline, *thisptr, *nextptr, *tmpptr; int i, j, rerr, gerr, berr, pwide3; int imax, jmax; int key; long cnt1, cnt2; int fserrmap[512]; /* -255 .. 0 .. +255 */ /* compute somewhat non-linear floyd-steinberg error mapping table */ for (i=j=0; i<=0x40; i++,j++) { fserrmap[256+i] = j; fserrmap[256-i] = -j; } for ( ; i<0x80; i++, j += !(i&1) ? 1 : 0) { fserrmap[256+i] = j; fserrmap[256-i] = -j; } for ( ; i<=0xff; i++) { fserrmap[256+i] = j; fserrmap[256-i] = -j; } cnt1 = cnt2 = 0; pwide3 = w*3; imax = h-1; jmax = w-1; ep = (pic24) ? pic24 : pic8; /* attempt to malloc things */ newpic = (byte *) malloc((size_t) (w * h)); cache = (short *) calloc((size_t) (2<<14), sizeof(short)); thisline = (int *) malloc(pwide3 * sizeof(int)); nextline = (int *) malloc(pwide3 * sizeof(int)); if (!cache || !newpic || !thisline || !nextline) { if (newpic) free(newpic); if (cache) free(cache); if (thisline) free(thisline); if (nextline) free(nextline); return (byte *) NULL; } np = newpic; /* get first line of picture */ if (pic24) { for (j=pwide3, tmpptr=nextline; j; j--, ep++) *tmpptr++ = (int) *ep; } else { for (j=w, tmpptr=nextline; j; j--, ep++) { *tmpptr++ = (int) rmap[*ep]; *tmpptr++ = (int) gmap[*ep]; *tmpptr++ = (int) bmap[*ep]; } } for (i=0; i<h; i++) { ProgressMeter(0, h-1, i, "Dither"); if ((i&15) == 0) WaitCursor(); tmpptr = thisline; thisline = nextline; nextline = tmpptr; /* swap */ if (i!=imax) { /* get next line */ if (!pic24) for (j=w, tmpptr=nextline; j; j--, ep++) { *tmpptr++ = (int) rmap[*ep]; *tmpptr++ = (int) gmap[*ep]; *tmpptr++ = (int) bmap[*ep]; } else for (j=pwide3, tmpptr=nextline; j; j--, ep++) *tmpptr++ = (int) *ep; } /* dither a line */ for (j=0, thisptr=thisline, nextptr=nextline; j<w; j++,np++) { int k, d, mind, closest; r2 = *thisptr++; g2 = *thisptr++; b2 = *thisptr++; /* map r2,g2,b2 components (could be outside 0..255 range) into 0..255 range */ if (r2<0 || g2<0 || b2<0) { /* are there any negatives in RGB? */ if (r2<g2) { if (r2<b2) k = 0; else k = 2; } else { if (g2<b2) k = 1; else k = 2; } switch (k) { case 0: g2 -= r2; b2 -= r2; d = (abs(r2) * 3) / 2; /* RED */ r2 = 0; g2 = (g2>d) ? g2 - d : 0; b2 = (b2>d) ? b2 - d : 0; break; case 1: r2 -= g2; b2 -= g2; d = (abs(g2) * 3) / 2; /* GREEN */ r2 = (r2>d) ? r2 - d : 0; g2 = 0; b2 = (b2>d) ? b2 - d : 0; break; case 2: r2 -= b2; g2 -= b2; d = (abs(b2) * 3) / 2; /* BLUE */ r2 = (r2>d) ? r2 - d : 0; g2 = (g2>d) ? g2 - d : 0; b2 = 0; break; } } if (r2>255 || g2>255 || b2>255) { /* any overflows in RGB? */ if (r2>g2) { if (r2>b2) k = 0; else k = 2; } else { if (g2>b2) k = 1; else k = 2; } switch (k) { case 0: g2 = (g2*255)/r2; b2 = (b2*255)/r2; r2=255; break; case 1: r2 = (r2*255)/g2; b2 = (b2*255)/g2; g2=255; break; case 2: r2 = (r2*255)/b2; g2 = (g2*255)/b2; b2=255; break; } } key = ((r2&0xf8)<<6) | ((g2&0xf8)<<1) | (b2>>4); if (key >= (2<<14)) FatalError("'key' overflow in DoColorDither()"); if (cache[key]) { *np = (byte) (cache[key] - 1); cnt1++; } else { /* not in cache, have to search the colortable */ cnt2++; mind = 10000; for (k=closest=0; k<maplen && mind>7; k++) { d = abs(r2 - rdisp[k]) + abs(g2 - gdisp[k]) + abs(b2 - bdisp[k]); if (d<mind) { mind = d; closest = k; } } cache[key] = closest + 1; *np = closest; } /* propogate the error */ rerr = r2 - rdisp[*np]; gerr = g2 - gdisp[*np]; berr = b2 - bdisp[*np]; RANGE(rerr, -255, 255); RANGE(gerr, -255, 255); RANGE(berr, -255, 255); rerr = fserrmap[256+rerr]; gerr = fserrmap[256+gerr]; berr = fserrmap[256+berr]; if (j!=jmax) { /* adjust RIGHT pixel */ thisptr[0] += (rerr*7)/16; thisptr[1] += (gerr*7)/16; thisptr[2] += (berr*7)/16; } if (i!=imax) { /* do BOTTOM pixel */ nextptr[0] += (rerr*5)/16; nextptr[1] += (gerr*5)/16; nextptr[2] += (berr*5)/16; if (j>0) { /* do BOTTOM LEFT pixel */ nextptr[-3] += (rerr*3)/16; nextptr[-2] += (gerr*3)/16; nextptr[-1] += (berr*3)/16; } if (j!=jmax) { /* do BOTTOM RIGHT pixel */ nextptr[3] += rerr/16; nextptr[4] += gerr/16; nextptr[5] += berr/16; } nextptr += 3; } } } free(thisline); free(nextline); free(cache); return newpic;}/********************************************/byte *Do332ColorDither(pic24, pic8, w, h, rmap, gmap, bmap, rdisp, gdisp, bdisp, maplen) byte *pic24, *pic8, *rmap, *gmap, *bmap, *rdisp, *gdisp, *bdisp; int w, h, maplen;{ /* some sort of color dither optimized for the 332 std cmap */ /* takes a 24 bit picture, of size w*h, dithers with the colors in rdisp, gdisp, bdisp (which have already been allocated), and generates an 8-bit w*h image, which it returns. ignores input value 'pic8' returns NULL on error note: the rdisp,gdisp,bdisp arrays should be the 'displayed' colors, not the 'desired' colors if pic24 is NULL, uses the passed-in pic8 (an 8-bit image) as the source, and the rmap,gmap,bmap arrays as the desired colors */ byte *np, *ep, *newpic; int r2, g2, b2; int *thisline, *nextline, *thisptr, *nextptr, *tmpptr; int i, j, rerr, gerr, berr, pwide3; int imax, jmax; long cnt1, cnt2; int fserrmap[512]; /* -255 .. 0 .. +255 */ /* compute somewhat non-linear floyd-steinberg error mapping table */ for (i=j=0; i<=0x40; i++,j++) { fserrmap[256+i] = j; fserrmap[256-i] = -j; } for ( ; i<0x80; i++, j += !(i&1) ? 1 : 0) { fserrmap[256+i] = j; fserrmap[256-i] = -j; } for ( ; i<=0xff; i++) { fserrmap[256+i] = j; fserrmap[256-i] = -j; } cnt1 = cnt2 = 0; pwide3 = w*3; imax = h-1; jmax = w-1; /* attempt to malloc things */ newpic = (byte *) malloc((size_t) (w * h)); thisline = (int *) malloc(pwide3 * sizeof(int)); nextline = (int *) malloc(pwide3 * sizeof(int)); if (!newpic || !thisline || !nextline) { if (newpic) free(newpic); if (thisline) free(thisline); if (nextline) free(nextline); return (byte *) NULL; } np = newpic; ep = (pic24) ? pic24 : pic8; /* get first line of picture */ if (pic24) { for (j=pwide3, tmpptr=nextline; j; j--, ep++) *tmpptr++ = (int) *ep; } else { for (j=w, tmpptr=nextline; j; j--, ep++) { *tmpptr++ = (int) rmap[*ep]; *tmpptr++ = (int) gmap[*ep]; *tmpptr++ = (int) bmap[*ep]; } } for (i=0; i<h; i++) { np = newpic + i*w; ProgressMeter(0, h-1, i, "Dither"); if ((i&127) == 0) WaitCursor(); tmpptr = thisline; thisline = nextline; nextline = tmpptr; /* swap */ if (i!=imax) { /* get next line */ if (!pic24) for (j=w, tmpptr=nextline; j; j--, ep++) { *tmpptr++ = (int) rmap[*ep]; *tmpptr++ = (int) gmap[*ep]; *tmpptr++ = (int) bmap[*ep]; } else for (j=pwide3, tmpptr=nextline; j; j--, ep++) *tmpptr++ = (int) *ep; } /* dither a line, doing odd-lines right-to-left (serpentine) */ thisptr = (i&1) ? thisline + w*3 - 3 : thisline; nextptr = (i&1) ? nextline + w*3 - 3 : nextline; if (i&1) np += w-1; for (j=0; j<w; j++) { int k, d, mind, closest, rb,gb,bb; r2 = *thisptr++; g2 = *thisptr++; b2 = *thisptr++; if (i&1) thisptr -= 6; /* move left */ rb = (r2 + 0x10); /* round top 3 bits */ RANGE(rb,0,255); rb = rb & 0xe0; gb = (g2 + 0x10); /* round 3 bits */ RANGE(gb,0,255); gb = gb & 0xe0; bb = (b2 + 0x20); /* round 2 bits */ RANGE(bb,0,255); bb = bb & 0xc0; *np = rb | (gb>>3) | (bb>>6); /* propogate the error */ rerr = r2 - rdisp[*np]; gerr = g2 - gdisp[*np]; berr = b2 - bdisp[*np]; RANGE(rerr, -255, 255); RANGE(gerr, -255, 255); RANGE(berr, -255, 255); rerr = fserrmap[256+rerr]; gerr = fserrmap[256+gerr]; berr = fserrmap[256+berr]; if (j!=jmax) { /* adjust LEFT/RIGHT pixel */ thisptr[0] += (rerr/2); rerr -= (rerr/2); thisptr[1] += (gerr/2); gerr -= (gerr/2); thisptr[2] += (berr/2); berr -= (berr/2); } if (i!=imax) { /* adjust BOTTOM pixel */ nextptr[0] += rerr; /* possibly all err if we're at l/r edge */ nextptr[1] += gerr; nextptr[2] += berr; } if (i&1) { nextptr -= 3; np--; } else { nextptr += 3; np++; } } } free(thisline); free(nextline); return newpic;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -