📄 xvsmooth.c
字号:
/* * xvsmooth.c - smoothing/color dither routines for XV * * Contains: * byte *SmoothResize(src8, swide, shigh, dwide, dhigh, * rmap, gmap, bmap, rdmap, gdmap, bdmap, maplen) * byte *Smooth24(pic824, is24, swide, shigh, dwide, dhigh, * rmap, gmap, bmap) * byte *DoColorDither(pic24, pic8, w, h, rmap,gmap,bmap, * rdisp, gdisp, bdisp, maplen) * byte *Do332ColorDither(pic24, pic8, w, h, rmap,gmap,bmap, * rdisp, gdisp, bdisp, maplen) */#include "copyright.h"#include "xv.h"static int smoothX PARM((byte *, byte *, int, int, int, int, int, byte *, byte *, byte *));static int smoothY PARM((byte *, byte *, int, int, int, int, int, byte *, byte *, byte *));static int smoothXY PARM((byte *, byte *, int, int, int, int, int, byte *, byte *, byte *));/***************************************************/byte *SmoothResize(srcpic8, swide, shigh, dwide, dhigh, rmap, gmap, bmap, rdmap, gdmap, bdmap, maplen) byte *srcpic8, *rmap, *gmap, *bmap, *rdmap, *gdmap, *bdmap; int swide, shigh, dwide, dhigh, maplen;{ /* generic interface to Smooth and ColorDither code. given an 8-bit-per, swide * shigh image with colormap rmap,gmap,bmap, will generate a new 8-bit-per, dwide * dhigh image, which is dithered using colors found in rdmap, gdmap, bdmap arrays */ /* returns ptr to a dwide*dhigh array of bytes, or NULL on failure */ byte *pic24, *pic8; pic24 = Smooth24(srcpic8, 0, swide, shigh, dwide, dhigh, rmap, gmap, bmap); if (pic24) { pic8 = DoColorDither(pic24, NULL, dwide, dhigh, rmap, gmap, bmap, rdmap, gdmap, bdmap, maplen); free(pic24); return pic8; } return (byte *) NULL;} /***************************************************/byte *Smooth24(pic824, is24, swide, shigh, dwide, dhigh, rmap, gmap, bmap) byte *pic824, *rmap, *gmap, *bmap; int is24, swide, shigh, dwide, dhigh;{ /* does a SMOOTH resize from pic824 (which is either a swide*shigh, 8-bit pic, with colormap rmap,gmap,bmap OR a swide*shigh, 24-bit image, based on whether 'is24' is set) into a dwide * dhigh 24-bit image returns a dwide*dhigh 24bit image, or NULL on failure (malloc) */ /* rmap,gmap,bmap should be 'desired' colors */ byte *pic24, *pp; int *cxtab, *pxtab; int y1Off, cyOff; int ex, ey, cx, cy, px, py, apx, apy, x1, y1; int cA, cB, cC, cD; int pA, pB, pC, pD; int retval, bperpix; cA = cB = cC = cD = 0; pp = pic24 = (byte *) malloc((size_t) (dwide * dhigh * 3)); if (!pic24) { fprintf(stderr,"unable to malloc pic24 in 'Smooth24()'\n"); return pic24; } bperpix = (is24) ? 3 : 1; /* decide which smoothing routine to use based on type of expansion */ if (dwide < swide && dhigh < shigh) retval = smoothXY(pic24, pic824, is24, swide, shigh, dwide, dhigh, rmap, gmap, bmap); else if (dwide < swide && dhigh >= shigh) retval = smoothX (pic24, pic824, is24, swide, shigh, dwide, dhigh, rmap, gmap, bmap); else if (dwide >= swide && dhigh < shigh) retval = smoothY (pic24, pic824, is24, swide, shigh, dwide, dhigh, rmap, gmap, bmap); else { /* dwide >= swide && dhigh >= shigh */ /* cx,cy = original pixel in pic824. px,py = relative position of pixel ex,ey inside of cx,cy as percentages +-50%, +-50%. 0,0 = middle of pixel */ /* we can save a lot of time by precomputing cxtab[] and pxtab[], both dwide arrays of ints that contain values for the equations: cx = (ex * swide) / dwide; px = ((ex * swide * 100) / dwide) - (cx * 100) - 50; */ cxtab = (int *) malloc(dwide * sizeof(int)); if (!cxtab) { free(pic24); return NULL; } pxtab = (int *) malloc(dwide * sizeof(int)); if (!pxtab) { free(pic24); free(cxtab); return NULL; } for (ex=0; ex<dwide; ex++) { cxtab[ex] = (ex * swide) / dwide; pxtab[ex] = (((ex * swide)* 100) / dwide) - (cxtab[ex] * 100) - 50; } for (ey=0; ey<dhigh; ey++) { byte *pptr, rA, gA, bA, rB, gB, bB, rC, gC, bC, rD, gD, bD; ProgressMeter(0, (dhigh)-1, ey, "Smooth"); cy = (ey * shigh) / dhigh; py = (((ey * shigh) * 100) / dhigh) - (cy * 100) - 50; if (py<0) { y1 = cy-1; if (y1<0) y1=0; } else { y1 = cy+1; if (y1>shigh-1) y1=shigh-1; } cyOff = cy * swide * bperpix; /* current line */ y1Off = y1 * swide * bperpix; /* up or down one line, depending */ if ((ey&15) == 0) WaitCursor(); for (ex=0; ex<dwide; ex++) { rA = rB = rC = rD = gA = gB = gC = gD = bA = bB = bC = bD = 0; cx = cxtab[ex]; px = pxtab[ex]; if (px<0) { x1 = cx-1; if (x1<0) x1=0; } else { x1 = cx+1; if (x1>swide-1) x1=swide-1; } if (is24) { pptr = pic824 + y1Off + x1*bperpix; /* corner pixel */ rA = *pptr++; gA = *pptr++; bA = *pptr++; pptr = pic824 + y1Off + cx*bperpix; /* up/down center pixel */ rB = *pptr++; gB = *pptr++; bB = *pptr++; pptr = pic824 + cyOff + x1*bperpix; /* left/right center pixel */ rC = *pptr++; gC = *pptr++; bC = *pptr++; pptr = pic824 + cyOff + cx*bperpix; /* center pixel */ rD = *pptr++; gD = *pptr++; bD = *pptr++; } else { /* 8-bit picture */ cA = pic824[y1Off + x1]; /* corner pixel */ cB = pic824[y1Off + cx]; /* up/down center pixel */ cC = pic824[cyOff + x1]; /* left/right center pixel */ cD = pic824[cyOff + cx]; /* center pixel */ } /* quick check */ if (!is24 && cA == cB && cB == cC && cC == cD) { /* set this pixel to the same color as in pic8 */ *pp++ = rmap[cD]; *pp++ = gmap[cD]; *pp++ = bmap[cD]; } else { /* compute weighting factors */ apx = abs(px); apy = abs(py); pA = (apx * apy) / 100; pB = (apy * (100 - apx)) / 100; pC = (apx * (100 - apy)) / 100; pD = 100 - (pA + pB + pC); if (is24) { *pp++ = ((int) (pA * rA))/100 + ((int) (pB * rB))/100 + ((int) (pC * rC))/100 + ((int) (pD * rD))/100; *pp++ = ((int) (pA * gA))/100 + ((int) (pB * gB))/100 + ((int) (pC * gC))/100 + ((int) (pD * gD))/100; *pp++ = ((int) (pA * bA))/100 + ((int) (pB * bB))/100 + ((int) (pC * bC))/100 + ((int) (pD * bD))/100; } else { /* 8-bit pic */ *pp++ = ((int) (pA * rmap[cA]))/100 + ((int)(pB * rmap[cB]))/100 + ((int) (pC * rmap[cC]))/100 + ((int)(pD * rmap[cD]))/100; *pp++ = ((int) (pA * gmap[cA]))/100 + ((int)(pB * gmap[cB]))/100 + ((int) (pC * gmap[cC]))/100 + ((int)(pD * gmap[cD]))/100; *pp++ = ((int)(pA * bmap[cA]))/100 + ((int)(pB * bmap[cB]))/100 + ((int)(pC * bmap[cC]))/100 + ((int)(pD * bmap[cD]))/100; } } } } free(cxtab); free(pxtab); retval = 0; /* okay */ } if (retval) { /* one of the Smooth**() methods failed */ free(pic24); pic24 = (byte *) NULL; } return pic24;}/***************************************************/static int smoothX(pic24, pic824, is24, swide, shigh, dwide, dhigh, rmap, gmap, bmap)byte *pic24, *pic824, *rmap, *gmap, *bmap;int is24, swide, shigh, dwide, dhigh;{ byte *cptr, *cptr1; int i, j; int *lbufR, *lbufG, *lbufB; int pixR, pixG, pixB, bperpix; int pcnt0, pcnt1, lastpix, pixcnt, thisline, ypcnt; int *pixarr, *paptr; /* returns '0' if okay, '1' if failed (malloc) */ /* for case where pic8 is shrunk horizontally and stretched vertically maps pic8 into an dwide * dhigh 24-bit picture. Only works correctly when swide>=dwide and shigh<=dhigh */ /* 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; cptr = pic824; cptr1 = cptr + swide * bperpix; for (i=0; i<dhigh; i++) { ProgressMeter(0, (dhigh)-1, i, "Smooth"); if ((i&15) == 0) WaitCursor(); ypcnt = (((i*shigh)<<6) / dhigh) - 32; if (ypcnt<0) ypcnt = 0; pcnt1 = ypcnt & 0x3f; /* 64ths of NEXT line to use */ pcnt0 = 64 - pcnt1; /* 64ths of THIS line to use */ thisline = ypcnt>>6; cptr = pic824 + thisline * swide * bperpix; if (thisline+1 < shigh) cptr1 = cptr + swide * bperpix; else cptr1 = cptr; if (is24) { for (j=0; j<swide; j++) { lbufR[j] = ((int) ((*cptr++ * pcnt0) + (*cptr1++ * pcnt1))) >> 6; lbufG[j] = ((int) ((*cptr++ * pcnt0) + (*cptr1++ * pcnt1))) >> 6; lbufB[j] = ((int) ((*cptr++ * pcnt0) + (*cptr1++ * pcnt1))) >> 6; } } else { /* 8-bit input pic */ for (j=0; j<swide; j++, cptr++, cptr1++) { lbufR[j] = ((int)((rmap[*cptr]* pcnt0) + (rmap[*cptr1]* pcnt1))) >> 6; lbufG[j] = ((int)((gmap[*cptr]* pcnt0) + (gmap[*cptr1]* pcnt1))) >> 6; lbufB[j] = ((int)((bmap[*cptr]* pcnt0) + (bmap[*cptr1]* pcnt1))) >> 6; } } 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; /* this NEVER happens: quiets compilers */ *pic24++ = pixR / pixcnt; *pic24++ = pixG / pixcnt; *pic24++ = pixB / pixcnt; lastpix = *paptr; pixR = pixG = pixB = pixcnt = 0; } if (j<swide) { pixR += lbufR[j]; pixG += lbufG[j]; pixB += lbufB[j]; pixcnt++; } } } free(lbufR); free(lbufG); free(lbufB); free(pixarr); return 0;} /***************************************************/static int smoothY(pic24, pic824, is24, swide, shigh, dwide, dhigh, rmap, gmap, bmap)byte *pic24, *pic824, *rmap, *gmap, *bmap;int is24, swide, shigh, dwide, dhigh;{ byte *clptr, *cptr, *cptr1; int i, j, bperpix; int *lbufR, *lbufG, *lbufB, *pct0, *pct1, *cxarr, *cxptr; int lastline, thisline, linecnt; int retval; /* returns '0' if okay, '1' if failed (malloc) */ /* for case where pic8 is shrunk vertically and stretched horizontally maps pic8 into a dwide * dhigh 24-bit picture. Only works correctly when swide<=dwide and shigh>=dhigh */ retval = 0; /* no probs, yet... */ bperpix = (is24) ? 3 : 1; lbufR = lbufG = lbufB = pct0 = pct1 = cxarr = NULL; lbufR = (int *) calloc((size_t) dwide, sizeof(int)); lbufG = (int *) calloc((size_t) dwide, sizeof(int)); lbufB = (int *) calloc((size_t) dwide, sizeof(int)); pct0 = (int *) calloc((size_t) dwide, sizeof(int)); pct1 = (int *) calloc((size_t) dwide, sizeof(int)); cxarr = (int *) calloc((size_t) dwide, sizeof(int)); if (!lbufR || !lbufG || !lbufB || !pct0 || ! pct1 || !cxarr) { retval = 1; goto smyexit; } for (i=0; i<dwide; i++) { /* precompute some handy tables */ int cx64; cx64 = (((i * swide) << 6) / dwide) - 32; if (cx64<0) cx64 = 0; pct1[i] = cx64 & 0x3f; pct0[i] = 64 - pct1[i]; cxarr[i] = cx64 >> 6; } lastline = linecnt = 0; for (i=0, clptr=pic824; i<=shigh; i++, clptr+=swide*bperpix) { 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 */ for (j=0; j<dwide; j++) { *pic24++ = lbufR[j] / linecnt; *pic24++ = lbufG[j] / linecnt; *pic24++ = lbufB[j] / linecnt; } xvbzero( (char *) lbufR, dwide * sizeof(int)); /* clear out line bufs */ xvbzero( (char *) lbufG, dwide * sizeof(int)); xvbzero( (char *) lbufB, dwide * sizeof(int)); linecnt = 0; lastline = thisline; } for (j=0, cxptr=cxarr; j<dwide; j++, cxptr++) { cptr = clptr + *cxptr * bperpix; if (*cxptr < swide-1) cptr1 = cptr + 1*bperpix; else cptr1 = cptr; if (is24) { lbufR[j] += ((int)((*cptr++ * pct0[j]) + (*cptr1++ * pct1[j]))) >> 6; lbufG[j] += ((int)((*cptr++ * pct0[j]) + (*cptr1++ * pct1[j]))) >> 6; lbufB[j] += ((int)((*cptr++ * pct0[j]) + (*cptr1++ * pct1[j]))) >> 6; } else { /* 8-bit input pic */ lbufR[j] += ((int)((rmap[*cptr]*pct0[j])+(rmap[*cptr1]*pct1[j]))) >> 6; lbufG[j] += ((int)((gmap[*cptr]*pct0[j])+(gmap[*cptr1]*pct1[j]))) >> 6; lbufB[j] += ((int)((bmap[*cptr]*pct0[j])+(bmap[*cptr1]*pct1[j]))) >> 6; } } linecnt++; } smyexit: if (lbufR) free(lbufR); if (lbufG) free(lbufG); if (lbufB) free(lbufB); if (pct0) free(pct0); if (pct1) free(pct1); if (cxarr) free(cxarr); return retval;} /***************************************************/static int smoothXY(pic24, pic824, is24, swide, shigh, dwide, dhigh, rmap, gmap, bmap)byte *pic24, *pic824, *rmap, *gmap, *bmap;int is24, swide, shigh, dwide, dhigh;{ byte *cptr; int i,j; int *lbufR, *lbufG, *lbufB; int pixR, pixG, pixB, bperpix; int lastline, thisline, lastpix, linecnt, pixcnt; int *pixarr, *paptr; /* returns '0' if okay, '1' if failed (malloc) */ /* shrinks pic8 into a dwide * dhigh 24-bit picture. Only works correctly when swide>=dwide and shigh>=dhigh (ie, the picture is shrunk on both
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -