diff options
Diffstat (limited to 'source/blender/imbuf/intern/ham.c')
-rw-r--r-- | source/blender/imbuf/intern/ham.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/source/blender/imbuf/intern/ham.c b/source/blender/imbuf/intern/ham.c new file mode 100644 index 00000000000..f9c6cf996a0 --- /dev/null +++ b/source/blender/imbuf/intern/ham.c @@ -0,0 +1,290 @@ +/** + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ham.c + * + * $Id$ + */ + +#include "BLI_blenlib.h" + +#include "imbuf.h" +#include "imbuf_patch.h" +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "IMB_cmap.h" +#include "IMB_hamx.h" +#include "IMB_ham.h" + +extern short alpha_col0; + +#define HAMB 0x0100 +#define HAMG 0x0400 +#define HAMR 0x0200 +#define HAMC 0x1000 +#define HAMFREE 0x2000 + +static void addhamdither(short x, unsigned char *dit, + short dmax, unsigned char *rgb, + unsigned short *ham, + short type, short round, short shift) +/* short x, dmax, type, round, shift; */ +/* uchar *dit, *rgb; */ +/* unsigned short *ham; */ +{ + short dx = 0; + short c1, c2; + + for (;x>0;x--){ + if (ham[0] & (HAMFREE | type)){ + c2 = c1 = *rgb; + + /* wrap dither */ + while (dx >= dmax) dx -= dmax; + + c1 += dit[dx]; + if (c1 > 255) c1 = 255; + c2 += round; + if (c2 > 255) c2 = 255; + + if (c1 != c2){ + c1 >>= shift; c2 >>= shift; + if (ham[1] & HAMFREE){ + ham[0] = type + c1; + ham[1] = type + c2; + } else if (ham[1] & type){ + ham[0] = type + c1; + } else if ((ham[2] & (type | HAMFREE)) == type){ + ham[0] = type + c1; + } else if ((ham[1] & HAMC) | (ham[2] & HAMC)){ + ham[0] = type + c1; + } + } + } + rgb += 4; + ham ++; + dx ++; + } +} + +static void convhamscanl(short x, short y, + unsigned char *rgbbase, + unsigned char coltab[][4], + short *deltab, + short bits) +/* short x, y, bits; */ +/* uchar *rgbbase; */ +/* uchar coltab[][4]; */ +/* short *deltab; */ +{ + int a, r, g, b, lr, lg, lb, dr, dg, db, col, fout, type, x2; + int round, shift; + uchar *rgb, dit[2]; + unsigned short *ham, *hambase; + + /* Opzet: + eerst wordt het gehele plaatje afgelopen, waarbij kleurovergangen gecodeerd + worden: FGRB XXXX XXXX + F - vrije kleurwaarde, mag door ieder veranderd worden + G/R/B - groen/rood/blauw ham overgang, alleen door die kleur te veranderen + XXXX XXXX - N bits waarde. + + 0000 XXXX XXXX is palet kleur. + + daarna wordt eerst de groen dither toegevoegd, dan de rood dither en + tenslotte wordt blauwdither toegevoegd + */ + + if ((hambase = (unsigned short *) malloc((x+4) * sizeof(unsigned short)))==0) return; + + lb = coltab[0][1]; + lg = coltab[0][2]; + lr = coltab[0][3]; + type = col = 0; + + ham = hambase; + rgb = rgbbase; + + shift = 8 - bits; + round = 1 << (shift - 1); + + /* om te voorkomen dat er 'ruis' ontstaat aan het einde van de regel */ + for (x2 = 3; x2 >= 0; x2 --) hambase[x + x2] = HAMFREE; + + for (x2 = x ;x2 > 0; x2--){ + r = rgb[0] + round; + g = rgb[1] + round; + b = rgb[2] + round; + a = rgb[3]; + + if (a < 128 && alpha_col0) { + a = 1; + } else a = 0; + + if (b > 255) b = 255; + if (g > 255) { + g = 255; + } + if (r > 255) r = 255; + + r >>= shift; + g >>= shift; + b >>= shift; + + if ((b-lb) | (g-lg) | (r-lr) | a){ + if (a) { + col = 0; + type = HAMC; + } else { + col = ((b << (2 * bits)) + (g << bits) + r) << 1; + fout = deltab[col + 1]; + col = deltab[col]; + type = HAMC; + + dr = quadr[lr-r]; + dg = quadr[lg-g]; + db = quadr[lb-b]; + + if ((dr+dg) <= fout){ + fout = dr+dg; + col = b; + type = HAMB; + } + if ((dg+db) <= fout){ + fout = dg+db; + col = r; + type = HAMR; + } + if ((dr+db) <= fout){ + fout = dr+db; + col = g; + type = HAMG; + } + } + + switch(type){ + case HAMG: + lg = g; + break; + case HAMR: + lr = r; + break; + case HAMB: + lb = b; + break; + default: + lb = coltab[col][1]; + lg = coltab[col][2]; + lr = coltab[col][3]; + } + *ham = type + col; + } else *ham = HAMG + HAMFREE + g; + + rgb += 4; + ham ++; + } + + + if (y & 1){ + dit[0] = 0 << (shift - 2); + dit[1] = 3 << (shift - 2); + } else { + dit[0] = 2 << (shift - 2); + dit[1] = 1 << (shift - 2); + } + + addhamdither(x,dit,2,rgbbase+2,hambase,HAMG, round, shift); + + if ((y & 1)==0){ + dit[0] = 3 << (shift - 2); + dit[1] = 0 << (shift - 2); + } else { + dit[0] = 1 << (shift - 2); + dit[1] = 2 << (shift - 2); + } + + addhamdither(x,dit,2,rgbbase+3,hambase,HAMR, round, shift); + addhamdither(x,dit,2,rgbbase+1,hambase,HAMB, round, shift); + + + ham = hambase; + rgb = rgbbase; + rgb += 3; + + for (x2=x;x2>0;x2--){ + type = *(ham++); + if (type & HAMG) type |= HAMR | HAMB; + + *rgb = (type & 0xff) | ((type & (HAMR | HAMB)) >> shift); + rgb += 4; + } + + free (hambase); +} + + +short imb_converttoham(struct ImBuf *ibuf) +/* struct ImBuf* ibuf; */ +{ + unsigned int coltab[256],*rect; + short x,y,* deltab; + int mincol; + + memcpy(coltab,ibuf->cmap,4 * ibuf->maxcol); + + mincol = ibuf->mincol; + if (alpha_col0 && mincol == 0) mincol = 1; + + if (ibuf->ftype == AN_hamx) { + deltab = imb_coldeltatab((uchar *) coltab, 0, ibuf->maxcol, 4); + } else { + ibuf->cbits = ibuf->depth - 2; + imb_losecmapbits(ibuf, coltab); + deltab = imb_coldeltatab((uchar *) coltab, mincol, ibuf->maxcol, ibuf->cbits); + } + + rect = ibuf->rect; + x=ibuf->x; + y=ibuf->y; + + if (ibuf->ftype == AN_hamx){ + IMB_dit2(ibuf, 2, 4); + IMB_dit2(ibuf, 1, 4); + IMB_dit2(ibuf, 0, 4); + imb_convhamx(ibuf, coltab, deltab); + } else { + for(;y > 0; y--){ + convhamscanl(x, y, rect, coltab, deltab, ibuf->cbits); + rect += x; + } + } + + return (TRUE); +} |