e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
1b10db2002-10-08Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland) /* included w/ defines in colortable.c */ /* **! module Image **! class colortable */
7a49a11999-04-10Mirar (Pontus Hagland) void NCTLU_FLAT_CUBICLES_NAME(rgb_group *s, NCTLU_DESTINATION *d, int n, struct neo_colortable *nct, struct nct_dither *dith, int rowlen)
2e63c01997-11-01Mirar (Pontus Hagland) { struct nctlu_cubicles *cubs; struct nctlu_cubicle *cub; int red,green,blue;
362a472003-03-21Marcus Comstedt  int redm,greenm,bluem;
2e63c01997-11-01Mirar (Pontus Hagland)  int redgreen; struct nct_flat_entry *fe=nct->u.flat.entries; int mindist; rgbl_group sf=nct->spacefactor; nct_dither_encode_function *dither_encode=dith->encode; nct_dither_got_function *dither_got=dith->got; nct_dither_line_function *dither_newline=dith->newline; int rowpos=0,cd=1,rowcount=0; cubs=&(nct->lu.cubicles); if (!(cubs->cubicles)) {
ccaee01997-11-03Mirar (Pontus Hagland)  int n2=cubs->r*cubs->g*cubs->b;
2e63c01997-11-01Mirar (Pontus Hagland)  CHRONO("init flat/cubicles");
a3b84b2015-04-18Martin Nilsson  cub=cubs->cubicles=calloc(sizeof(struct nctlu_cubicle), n2);
13670c2015-05-25Martin Nilsson 
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  if (!cub) Pike_error("out of memory\n");
2e63c01997-11-01Mirar (Pontus Hagland) 
ccaee01997-11-03Mirar (Pontus Hagland)  while (n2--) /* initiate all to empty */
2e63c01997-11-01Mirar (Pontus Hagland)  { cub->n=0; cub->index=NULL; cub++; } /* yes, could be faster with a memset... */ } CHRONO("begin flat/cubicles");
362a472003-03-21Marcus Comstedt  red=cubs->r; redm=red-1; green=cubs->g; greenm=green-1; blue=cubs->b; bluem=blue-1;
2e63c01997-11-01Mirar (Pontus Hagland)  redgreen=red*green; if (dith->firstline) (dith->firstline)NCTLU_LINE_ARGS; while (n--) { int r,g,b; struct lookupcache *lc; int m; int *ci;
7a49a11999-04-10Mirar (Pontus Hagland)  rgbl_group val;
2e63c01997-11-01Mirar (Pontus Hagland)  if (dither_encode) { val=(dither_encode)(dith,rowpos,*s); } else {
7a49a11999-04-10Mirar (Pontus Hagland)  val.r=s->r; val.g=s->g; val.b=s->b;
2e63c01997-11-01Mirar (Pontus Hagland)  }
7a49a11999-04-10Mirar (Pontus Hagland)  lc=nct->lookupcachehash+COLORLOOKUPCACHEHASHVALUE(val.r,val.g,val.b);
2e63c01997-11-01Mirar (Pontus Hagland)  if (lc->index!=-1 &&
7a49a11999-04-10Mirar (Pontus Hagland)  lc->src.r==val.r && lc->src.g==val.g && lc->src.b==val.b)
2e63c01997-11-01Mirar (Pontus Hagland)  { NCTLU_CACHE_HIT_WRITE; goto done_pixel; } lc->src=*s;
13670c2015-05-25Martin Nilsson 
362a472003-03-21Marcus Comstedt  r=((val.r*red+redm)>>8); g=((val.g*green+greenm)>>8); b=((val.b*blue+bluem)>>8);
2e63c01997-11-01Mirar (Pontus Hagland)  cub=cubs->cubicles+r+g*red+b*redgreen;
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  if (!cub->index) /* need to build that cubicle */ _build_cubicle(nct,r,g,b,red,green,blue,cub); /* now, compare with the colors in that cubicle */ m=cub->n; ci=cub->index;
7a3c2a2016-01-30Martin Nilsson  mindist=256*256*100; /* max dist is 256^2*3 */
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  while (m--) {
7a49a11999-04-10Mirar (Pontus Hagland)  int dist=sf.r*SQ(fe[*ci].color.r-val.r)+ sf.g*SQ(fe[*ci].color.g-val.g)+ sf.b*SQ(fe[*ci].color.b-val.b);
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  if (dist<mindist) { lc->dest=fe[*ci].color; mindist=dist; lc->index=*ci; NCTLU_CACHE_HIT_WRITE; }
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  ci++; } done_pixel:
f458a61999-04-09Per Hedbor  if (dither_encode)
2e63c01997-11-01Mirar (Pontus Hagland)  {
f458a61999-04-09Per Hedbor  if (dither_got) dither_got(dith,rowpos,*s,NCTLU_DITHER_GOT);
2e63c01997-11-01Mirar (Pontus Hagland)  s+=cd; d+=cd; rowpos+=cd; if (++rowcount==rowlen) { rowcount=0; if (dither_newline) (dither_newline)NCTLU_LINE_ARGS; } } else { d++; s++; } } CHRONO("end flat/cubicles"); }
7a49a11999-04-10Mirar (Pontus Hagland) void NCTLU_FLAT_FULL_NAME(rgb_group *s, NCTLU_DESTINATION *d, int n, struct neo_colortable *nct, struct nct_dither *dith, int rowlen)
2e63c01997-11-01Mirar (Pontus Hagland) { /* no need to build any data, we're using full scan */ rgbl_group sf=nct->spacefactor;
07fc8b2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t mprim=nct->u.flat.numentries;
2e63c01997-11-01Mirar (Pontus Hagland)  struct nct_flat_entry *feprim=nct->u.flat.entries; nct_dither_encode_function *dither_encode=dith->encode; nct_dither_got_function *dither_got=dith->got; nct_dither_line_function *dither_newline=dith->newline; int rowpos=0,cd=1,rowcount=0; CHRONO("begin flat/full map"); if (dith->firstline) (dith->firstline)NCTLU_LINE_ARGS; while (n--) { int rgbr,rgbg,rgbb; int mindist;
0af1852000-08-11Henrik Grubbström (Grubba)  ptrdiff_t m;
2e63c01997-11-01Mirar (Pontus Hagland)  struct nct_flat_entry *fe; struct lookupcache *lc;
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  if (dither_encode) { rgbl_group val; val=dither_encode(dith,rowpos,*s); rgbr=val.r; rgbg=val.g; rgbb=val.b; } else { rgbr=s->r; rgbg=s->g; rgbb=s->b; } /* cached? */ lc=nct->lookupcachehash+COLORLOOKUPCACHEHASHVALUE(rgbr,rgbg,rgbb); if (lc->index!=-1 && lc->src.r==rgbr && lc->src.g==rgbg && lc->src.b==rgbb) { NCTLU_CACHE_HIT_WRITE; goto done_pixel; } lc->src=*s;
7a3c2a2016-01-30Martin Nilsson  mindist=256*256*100; /* max dist is 256^2*3 */
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  fe=feprim; m=mprim;
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  while (m--)
c3d8431998-01-11Mirar (Pontus Hagland)  if (fe->no!=-1)
2e63c01997-11-01Mirar (Pontus Hagland)  {
c3d8431998-01-11Mirar (Pontus Hagland)  int dist= sf.r*SQ(fe->color.r-rgbr)+ sf.g*SQ(fe->color.g-rgbg)+ sf.b*SQ(fe->color.b-rgbb);
13670c2015-05-25Martin Nilsson 
c3d8431998-01-11Mirar (Pontus Hagland)  if (dist<mindist) { lc->dest=fe->color; mindist=dist;
cc7cf42015-10-14Martin Nilsson  lc->index = (int)fe->no;
c3d8431998-01-11Mirar (Pontus Hagland)  NCTLU_CACHE_HIT_WRITE; }
13670c2015-05-25Martin Nilsson 
c3d8431998-01-11Mirar (Pontus Hagland)  fe++; } else fe++;
2e63c01997-11-01Mirar (Pontus Hagland)  done_pixel:
f458a61999-04-09Per Hedbor  if (dither_encode)
2e63c01997-11-01Mirar (Pontus Hagland)  {
f458a61999-04-09Per Hedbor  if (dither_got) dither_got(dith,rowpos,*s,NCTLU_DITHER_GOT);
2e63c01997-11-01Mirar (Pontus Hagland)  s+=cd; d+=cd; rowpos+=cd; if (++rowcount==rowlen) { rowcount=0;
13670c2015-05-25Martin Nilsson  if (dither_newline)
2e63c01997-11-01Mirar (Pontus Hagland)  (dither_newline)NCTLU_LINE_ARGS; } } else { d++; s++; } } CHRONO("end flat/full map"); }
7a49a11999-04-10Mirar (Pontus Hagland) void NCTLU_FLAT_RIGID_NAME(rgb_group *s, NCTLU_DESTINATION *d, int n, struct neo_colortable *nct, struct nct_dither *dith, int rowlen)
cbfa641999-04-08Mirar (Pontus Hagland) {
07fc8b2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t mprim = nct->u.flat.numentries; struct nct_flat_entry *feprim = nct->u.flat.entries;
cbfa641999-04-08Mirar (Pontus Hagland)  nct_dither_encode_function *dither_encode=dith->encode; nct_dither_got_function *dither_got=dith->got; nct_dither_line_function *dither_newline=dith->newline; int rowpos=0,cd=1,rowcount=0; int *index; int r,g,b; int i; if (!nct->lu.rigid.index) { CHRONO("init flat/rigid map"); build_rigid(nct); } index=nct->lu.rigid.index; r=nct->lu.rigid.r; g=nct->lu.rigid.g; b=nct->lu.rigid.b; CHRONO("begin flat/rigid map"); if (dith->firstline) (dith->firstline)NCTLU_LINE_ARGS; while (n--) {
f458a61999-04-09Per Hedbor  rgbl_group val;
13670c2015-05-25Martin Nilsson 
cbfa641999-04-08Mirar (Pontus Hagland)  if (dither_encode) { val=dither_encode(dith,rowpos,*s); } else {
f458a61999-04-09Per Hedbor  val.r=s->r; val.g=s->g; val.b=s->b;
cbfa641999-04-08Mirar (Pontus Hagland)  }
f458a61999-04-09Per Hedbor  i=index[((val.r*r)>>8)+ r*(((val.g*g)>>8)+ ((val.b*b)>>8)*g)];
cbfa641999-04-08Mirar (Pontus Hagland)  NCTLU_RIGID_WRITE;
f458a61999-04-09Per Hedbor  if (dither_encode)
cbfa641999-04-08Mirar (Pontus Hagland)  {
f458a61999-04-09Per Hedbor  if (dither_got) dither_got(dith,rowpos,*s,NCTLU_DITHER_RIGID_GOT); s+=cd; d+=cd; rowpos+=cd; if (++rowcount==rowlen) { rowcount=0;
13670c2015-05-25Martin Nilsson  if (dither_newline)
f458a61999-04-09Per Hedbor  (dither_newline)NCTLU_LINE_ARGS; }
cbfa641999-04-08Mirar (Pontus Hagland)  } else { d++; s++; } } CHRONO("end flat/rigid map"); }
7a49a11999-04-10Mirar (Pontus Hagland) void NCTLU_CUBE_NAME(rgb_group *s, NCTLU_DESTINATION *d, int n, struct neo_colortable *nct, struct nct_dither *dith, int rowlen)
2e63c01997-11-01Mirar (Pontus Hagland) { int red,green,blue; int hred,hgreen,hblue; int redm,greenm,bluem; float redf,greenf,bluef; struct nct_cube *cube=&(nct->u.cube); rgbl_group sf=nct->spacefactor; int rowpos=0,cd=1,rowcount=0; rgbl_group rgb; nct_dither_encode_function *dither_encode=dith->encode; nct_dither_got_function *dither_got=dith->got; nct_dither_line_function *dither_newline=dith->newline; red=cube->r; hred=red/2; redm=red-1; green=cube->g; hgreen=green/2; greenm=green-1; blue=cube->b; hblue=blue/2; bluem=blue-1;
cc7cf42015-10-14Martin Nilsson  redf = (float)(255.0/redm); greenf = (float)(255.0/greenm); bluef = (float)(255.0/bluem);
2e63c01997-11-01Mirar (Pontus Hagland)  CHRONO("begin cube map"); if (!cube->firstscale && red && green && blue) { if (!dither_encode) while (n--) { NCTLU_CUBE_FAST_WRITE(s); d++; s++; } else { if (dith->firstline) (dith->firstline)NCTLU_LINE_ARGS; while (n--) { rgb=dither_encode(dith,rowpos,*s); NCTLU_CUBE_FAST_WRITE(&rgb);
7a49a11999-04-10Mirar (Pontus Hagland)  if (dither_got) NCTLU_CUBE_FAST_WRITE_DITHER_GOT(&rgb);
2e63c01997-11-01Mirar (Pontus Hagland)  s+=cd; d+=cd; rowpos+=cd; if (++rowcount==rowlen) { rowcount=0;
13670c2015-05-25Martin Nilsson  if (dither_newline)
2e63c01997-11-01Mirar (Pontus Hagland)  (dither_newline)NCTLU_LINE_ARGS; } } } } else { if (dith->firstline) (dith->firstline)NCTLU_LINE_ARGS; while (n--) /* similar to _find_cube_dist() */ {
34a3482016-04-09Martin Nilsson  int mindist; struct lookupcache *lc;
7a49a11999-04-10Mirar (Pontus Hagland)  rgbl_group val;
2e63c01997-11-01Mirar (Pontus Hagland)  if (dither_encode) { val=dither_encode(dith,rowpos,*s); } else {
7a49a11999-04-10Mirar (Pontus Hagland)  val.r=s->r; val.g=s->g; val.b=s->b;
2e63c01997-11-01Mirar (Pontus Hagland)  }
7a49a11999-04-10Mirar (Pontus Hagland)  lc=nct->lookupcachehash+COLORLOOKUPCACHEHASHVALUE(val.r,val.g,val.b);
2e63c01997-11-01Mirar (Pontus Hagland)  if (lc->index!=-1 &&
7a49a11999-04-10Mirar (Pontus Hagland)  lc->src.r==val.r && lc->src.g==val.g && lc->src.b==val.b)
2e63c01997-11-01Mirar (Pontus Hagland)  { NCTLU_CACHE_HIT_WRITE; goto done_pixel; } lc->src=*s; if (red && green && blue) {
7a49a11999-04-10Mirar (Pontus Hagland)  lc->dest.r=((int)(((val.r*red+hred)>>8)*redf)); lc->dest.g=((int)(((val.g*green+hgreen)>>8)*greenf)); lc->dest.b=((int)(((val.b*blue+hblue)>>8)*bluef));
2e63c01997-11-01Mirar (Pontus Hagland) 
34a3482016-04-09Martin Nilsson  lc->index=
7a49a11999-04-10Mirar (Pontus Hagland)  ((val.r*red+hred)>>8)+ (((val.g*green+hgreen)>>8)+ ((val.b*blue+hblue)>>8)*green)*red;
2e63c01997-11-01Mirar (Pontus Hagland)  NCTLU_CACHE_HIT_WRITE; mindist=
7a49a11999-04-10Mirar (Pontus Hagland)  sf.r*SQ(val.r-lc->dest.r)+ sf.g*SQ(val.g-lc->dest.g)+ sf.b*SQ(val.b-lc->dest.b);
2e63c01997-11-01Mirar (Pontus Hagland)  } else { mindist=10000000;
34a3482016-04-09Martin Nilsson  }
2e63c01997-11-01Mirar (Pontus Hagland)  if (mindist>=cube->disttrig) {
34a3482016-04-09Martin Nilsson  /* check scales to get better distance if possible */ int i; int nc=cube->r*cube->g*cube->b; struct nct_scale *sc=cube->firstscale;
2e63c01997-11-01Mirar (Pontus Hagland)  while (sc) { /* what step is closest? project... */
f6b3b52016-02-12Martin Nilsson  i = (int)((sc->steps * (((int)val.r-(int)sc->low.r)*sc->vector.r + ((int)val.g-(int)sc->low.g)*sc->vector.g + ((int)val.b-(int)sc->low.b)*sc->vector.b)) * sc->invsqvector);
2e63c01997-11-01Mirar (Pontus Hagland)  if (i<0) i=0; else if (i>=sc->steps) i=sc->steps-1;
13670c2015-05-25Martin Nilsson  if (sc->no[i]>=nc)
2e63c01997-11-01Mirar (Pontus Hagland)  {
07fc8b2000-08-10Henrik Grubbström (Grubba)  double f= i * sc->mqsteps;
f6b3b52016-02-12Martin Nilsson  int drgbr = sc->low.r + (int)(sc->vector.r*f); int drgbg = sc->low.g + (int)(sc->vector.g*f); int drgbb = sc->low.b + (int)(sc->vector.b*f);
2e63c01997-11-01Mirar (Pontus Hagland) 
7a49a11999-04-10Mirar (Pontus Hagland)  int ldist=sf.r*SQ(val.r-drgbr)+ sf.g*SQ(val.g-drgbg)+sf.b*SQ(val.b-drgbb);
2e63c01997-11-01Mirar (Pontus Hagland)  if (ldist<mindist) { lc->dest.r=(unsigned char)drgbr; lc->dest.g=(unsigned char)drgbg; lc->dest.b=(unsigned char)drgbb;
844eae1997-11-07Mirar (Pontus Hagland)  lc->index=sc->no[i];
2e63c01997-11-01Mirar (Pontus Hagland)  mindist=ldist; NCTLU_CACHE_HIT_WRITE; } }
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  nc+=sc->realsteps;
13670c2015-05-25Martin Nilsson 
2e63c01997-11-01Mirar (Pontus Hagland)  sc=sc->next;
34a3482016-04-09Martin Nilsson  } }
2e63c01997-11-01Mirar (Pontus Hagland) done_pixel:
f458a61999-04-09Per Hedbor  if (dither_encode) { if (dither_got)
7a49a11999-04-10Mirar (Pontus Hagland)  dither_got(dith,rowpos,*s,NCTLU_DITHER_GOT);
2e63c01997-11-01Mirar (Pontus Hagland)  s+=cd; d+=cd; rowpos+=cd; if (++rowcount==rowlen) { rowcount=0; if (dither_newline) (dither_newline)NCTLU_LINE_ARGS; } } else { d++; s++; } } } CHRONO("end cube map"); }
74b0981999-04-09Mirar (Pontus Hagland) void (*NCTLU_SELECT_FUNCTION(struct neo_colortable *nct)) (rgb_group *s, NCTLU_DESTINATION *d, int n, struct neo_colortable *nct, struct nct_dither *dith, int rowlen) { switch (nct->type) {
13670c2015-05-25Martin Nilsson  case NCT_CUBE:
3519932000-09-08Henrik Grubbström (Grubba) #ifdef COLORTABLE_DEBUG fprintf(stderr, "COLORTABLE " DEFINETOSTR(NCTLU_SELECT_FUNCTION) ":" DEFINETOSTR(NCTLU_DESTINATION) " => " DEFINETOSTR(NCTLU_CUBE_NAME) "\n"); #endif /* COLORTABLE_DEBUG */
f405062003-04-02Martin Stjernholm  return &NCTLU_CUBE_NAME;
74b0981999-04-09Mirar (Pontus Hagland)  case NCT_FLAT: switch (nct->lookup_mode) { case NCT_FULL:
3519932000-09-08Henrik Grubbström (Grubba) #ifdef COLORTABLE_DEBUG fprintf(stderr, "COLORTABLE " DEFINETOSTR(NCTLU_SELECT_FUNCTION) ":" DEFINETOSTR(NCTLU_DESTINATION) " => " DEFINETOSTR(NCTLU_FLAT_FULL_NAME) "\n"); #endif /* COLORTABLE_DEBUG */
f405062003-04-02Martin Stjernholm  return &NCTLU_FLAT_FULL_NAME;
74b0981999-04-09Mirar (Pontus Hagland)  case NCT_RIGID:
3519932000-09-08Henrik Grubbström (Grubba) #ifdef COLORTABLE_DEBUG fprintf(stderr, "COLORTABLE " DEFINETOSTR(NCTLU_SELECT_FUNCTION) ":" DEFINETOSTR(NCTLU_DESTINATION) " => " DEFINETOSTR(NCTLU_FLAT_RIGID_NAME) "\n"); #endif /* COLORTABLE_DEBUG */
f405062003-04-02Martin Stjernholm  return &NCTLU_FLAT_RIGID_NAME;
74b0981999-04-09Mirar (Pontus Hagland)  case NCT_CUBICLES:
3519932000-09-08Henrik Grubbström (Grubba) #ifdef COLORTABLE_DEBUG fprintf(stderr, "COLORTABLE " DEFINETOSTR(NCTLU_SELECT_FUNCTION) ":" DEFINETOSTR(NCTLU_DESTINATION) " => " DEFINETOSTR(NCTLU_FLAT_CUBICLES_NAME) "\n"); #endif /* COLORTABLE_DEBUG */
f405062003-04-02Martin Stjernholm  return &NCTLU_FLAT_CUBICLES_NAME;
74b0981999-04-09Mirar (Pontus Hagland)  }
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
4247ec2013-02-16Henrik Grubbström (Grubba) 
74b0981999-04-09Mirar (Pontus Hagland)  default:
5aad932002-08-15Marcus Comstedt  Pike_fatal("lookup select (%s:%d) couldn't find the lookup mode\n",
74b0981999-04-09Mirar (Pontus Hagland)  __FILE__,__LINE__); }
9282fd2015-09-27Martin Nilsson  UNREACHABLE(return 0);
74b0981999-04-09Mirar (Pontus Hagland) } int NCTLU_EXECUTE_FUNCTION(struct neo_colortable *nct, rgb_group *s, NCTLU_DESTINATION *d, int len, int rowlen) { struct nct_dither dith; if (nct->type==NCT_NONE) return 0; image_colortable_initiate_dither(nct,&dith,rowlen); (NCTLU_SELECT_FUNCTION(nct))(s,d,len,nct,&dith,rowlen); image_colortable_free_dither(&dith); return 1; }