⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gd_topal.c

📁 Linux/Unix下的绘图函数库(Graphic Drawing Library)
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* If we had a pure transparency color, add it as the last palette entry.   * Skip incrementing the color count so that the dither / matching phase   * won't use it on pixels that shouldn't have been transparent.  We'll   * increment it after all that finishes. */  if (oim->transparent >= 0)    {      /* Save the transparent color. */      nim->red[nim->colorsTotal] = gdTrueColorGetRed (oim->transparent);      nim->green[nim->colorsTotal] = gdTrueColorGetGreen (oim->transparent);      nim->blue[nim->colorsTotal] = gdTrueColorGetBlue (oim->transparent);      nim->alpha[nim->colorsTotal] = gdAlphaTransparent;      nim->open[nim->colorsTotal] = 0;    }  gdFree (boxlist);#endif}/* * These routines are concerned with the time-critical task of mapping input * colors to the nearest color in the selected colormap. * * We re-use the histogram space as an "inverse color map", essentially a * cache for the results of nearest-color searches.  All colors within a * histogram cell will be mapped to the same colormap entry, namely the one * closest to the cell's center.  This may not be quite the closest entry to * the actual input color, but it's almost as good.  A zero in the cache * indicates we haven't found the nearest color for that cell yet; the array * is cleared to zeroes before starting the mapping pass.  When we find the * nearest color for a cell, its colormap index plus one is recorded in the * cache for future use.  The pass2 scanning routines call fill_inverse_cmap * when they need to use an unfilled entry in the cache. * * Our method of efficiently finding nearest colors is based on the "locally * sorted search" idea described by Heckbert and on the incremental distance * calculation described by Spencer W. Thomas in chapter III.1 of Graphics * Gems II (James Arvo, ed.  Academic Press, 1991).  Thomas points out that * the distances from a given colormap entry to each cell of the histogram can * be computed quickly using an incremental method: the differences between * distances to adjacent cells themselves differ by a constant.  This allows a * fairly fast implementation of the "brute force" approach of computing the * distance from every colormap entry to every histogram cell.  Unfortunately, * it needs a work array to hold the best-distance-so-far for each histogram * cell (because the inner loop has to be over cells, not colormap entries). * The work array elements have to be INT32s, so the work array would need * 256Kb at our recommended precision.  This is not feasible in DOS machines. * * To get around these problems, we apply Thomas' method to compute the * nearest colors for only the cells within a small subbox of the histogram. * The work array need be only as big as the subbox, so the memory usage * problem is solved.  Furthermore, we need not fill subboxes that are never * referenced in pass2; many images use only part of the color gamut, so a * fair amount of work is saved.  An additional advantage of this * approach is that we can apply Heckbert's locality criterion to quickly * eliminate colormap entries that are far away from the subbox; typically * three-fourths of the colormap entries are rejected by Heckbert's criterion, * and we need not compute their distances to individual cells in the subbox. * The speed of this approach is heavily influenced by the subbox size: too * small means too much overhead, too big loses because Heckbert's criterion * can't eliminate as many colormap entries.  Empirically the best subbox * size seems to be about 1/512th of the histogram (1/8th in each direction). * * Thomas' article also describes a refined method which is asymptotically * faster than the brute-force method, but it is also far more complex and * cannot efficiently be applied to small subboxes.  It is therefore not * useful for programs intended to be portable to DOS machines.  On machines * with plenty of memory, filling the whole histogram in one shot with Thomas' * refined method might be faster than the present code --- but then again, * it might not be any faster, and it's certainly more complicated. *//* log2(histogram cells in update box) for each axis; this can be adjusted */#define BOX_C0_LOG  (HIST_C0_BITS-3)#define BOX_C1_LOG  (HIST_C1_BITS-3)#define BOX_C2_LOG  (HIST_C2_BITS-3)#define BOX_C0_ELEMS  (1<<BOX_C0_LOG)	/* # of hist cells in update box */#define BOX_C1_ELEMS  (1<<BOX_C1_LOG)#define BOX_C2_ELEMS  (1<<BOX_C2_LOG)#define BOX_C0_SHIFT  (C0_SHIFT + BOX_C0_LOG)#define BOX_C1_SHIFT  (C1_SHIFT + BOX_C1_LOG)#define BOX_C2_SHIFT  (C2_SHIFT + BOX_C2_LOG)/* * The next three routines implement inverse colormap filling.  They could * all be folded into one big routine, but splitting them up this way saves * some stack space (the mindist[] and bestdist[] arrays need not coexist) * and may allow some compilers to produce better code by registerizing more * inner-loop variables. */LOCAL (int)find_nearby_colors (#ifdef ORIGINAL_LIB_JPEG		     j_decompress_ptr cinfo,#else		     gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,#endif		     int minc0, int minc1, int minc2, JSAMPLE colorlist[])/* Locate the colormap entries close enough to an update box to be candidates * for the nearest entry to some cell(s) in the update box.  The update box * is specified by the center coordinates of its first cell.  The number of * candidate colormap entries is returned, and their colormap indexes are * placed in colorlist[]. * This routine uses Heckbert's "locally sorted search" criterion to select * the colors that need further consideration. */{#ifdef ORIGINAL_LIB_JPEG  int numcolors = cinfo->actual_number_of_colors;#else  int numcolors = nim->colorsTotal;#endif  int maxc0, maxc1, maxc2;  int centerc0, centerc1, centerc2;  int i, x, ncolors;  INT32 minmaxdist, min_dist, max_dist, tdist;  INT32 mindist[MAXNUMCOLORS];	/* min distance to colormap entry i */  /* Compute true coordinates of update box's upper corner and center.   * Actually we compute the coordinates of the center of the upper-corner   * histogram cell, which are the upper bounds of the volume we care about.   * Note that since ">>" rounds down, the "center" values may be closer to   * min than to max; hence comparisons to them must be "<=", not "<".   */  maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));  centerc0 = (minc0 + maxc0) >> 1;  maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));  centerc1 = (minc1 + maxc1) >> 1;  maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));  centerc2 = (minc2 + maxc2) >> 1;  /* For each color in colormap, find:   *  1. its minimum squared-distance to any point in the update box   *     (zero if color is within update box);   *  2. its maximum squared-distance to any point in the update box.   * Both of these can be found by considering only the corners of the box.   * We save the minimum distance for each color in mindist[];   * only the smallest maximum distance is of interest.   */  minmaxdist = 0x7FFFFFFFL;  for (i = 0; i < numcolors; i++)    {      /* We compute the squared-c0-distance term, then add in the other two. */#ifdef ORIGINAL_LIB_JPEG      x = GETJSAMPLE (cinfo->colormap[0][i]);#else      x = nim->red[i];#endif      if (x < minc0)	{	  tdist = (x - minc0) * C0_SCALE;	  min_dist = tdist * tdist;	  tdist = (x - maxc0) * C0_SCALE;	  max_dist = tdist * tdist;	}      else if (x > maxc0)	{	  tdist = (x - maxc0) * C0_SCALE;	  min_dist = tdist * tdist;	  tdist = (x - minc0) * C0_SCALE;	  max_dist = tdist * tdist;	}      else	{	  /* within cell range so no contribution to min_dist */	  min_dist = 0;	  if (x <= centerc0)	    {	      tdist = (x - maxc0) * C0_SCALE;	      max_dist = tdist * tdist;	    }	  else	    {	      tdist = (x - minc0) * C0_SCALE;	      max_dist = tdist * tdist;	    }	}#ifdef ORIGINAL_LIB_JPEG      x = GETJSAMPLE (cinfo->colormap[1][i]);#else      x = nim->green[i];#endif      if (x < minc1)	{	  tdist = (x - minc1) * C1_SCALE;	  min_dist += tdist * tdist;	  tdist = (x - maxc1) * C1_SCALE;	  max_dist += tdist * tdist;	}      else if (x > maxc1)	{	  tdist = (x - maxc1) * C1_SCALE;	  min_dist += tdist * tdist;	  tdist = (x - minc1) * C1_SCALE;	  max_dist += tdist * tdist;	}      else	{	  /* within cell range so no contribution to min_dist */	  if (x <= centerc1)	    {	      tdist = (x - maxc1) * C1_SCALE;	      max_dist += tdist * tdist;	    }	  else	    {	      tdist = (x - minc1) * C1_SCALE;	      max_dist += tdist * tdist;	    }	}#ifdef ORIGINAL_LIB_JPEG      x = GETJSAMPLE (cinfo->colormap[2][i]);#else      x = nim->blue[i];#endif      if (x < minc2)	{	  tdist = (x - minc2) * C2_SCALE;	  min_dist += tdist * tdist;	  tdist = (x - maxc2) * C2_SCALE;	  max_dist += tdist * tdist;	}      else if (x > maxc2)	{	  tdist = (x - maxc2) * C2_SCALE;	  min_dist += tdist * tdist;	  tdist = (x - minc2) * C2_SCALE;	  max_dist += tdist * tdist;	}      else	{	  /* within cell range so no contribution to min_dist */	  if (x <= centerc2)	    {	      tdist = (x - maxc2) * C2_SCALE;	      max_dist += tdist * tdist;	    }	  else	    {	      tdist = (x - minc2) * C2_SCALE;	      max_dist += tdist * tdist;	    }	}      mindist[i] = min_dist;	/* save away the results */      if (max_dist < minmaxdist)	minmaxdist = max_dist;    }  /* Now we know that no cell in the update box is more than minmaxdist   * away from some colormap entry.  Therefore, only colors that are   * within minmaxdist of some part of the box need be considered.   */  ncolors = 0;  for (i = 0; i < numcolors; i++)    {      if (mindist[i] <= minmaxdist)	colorlist[ncolors++] = (JSAMPLE) i;    }  return ncolors;}LOCAL (void) find_best_colors (#ifdef ORIGINAL_LIB_JPEG				j_decompress_ptr cinfo,#else				gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,#endif				int minc0, int minc1, int minc2,				int numcolors, JSAMPLE colorlist[],				JSAMPLE bestcolor[])/* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. * This routine uses Thomas' incremental distance calculation method to * find the distance from a colormap entry to successive cells in the box. */{  int ic0, ic1, ic2;  int i, icolor;  register INT32 *bptr;		/* pointer into bestdist[] array */  JSAMPLE *cptr;		/* pointer into bestcolor[] array */  INT32 dist0, dist1;		/* initial distance values */  register INT32 dist2;		/* current distance in inner loop */  INT32 xx0, xx1;		/* distance increments */  register INT32 xx2;  INT32 inc0, inc1, inc2;	/* initial values for increments */  /* This array holds the distance to the nearest-so-far color for each cell */  INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];  /* Initialize best-distance for each cell of the update box */  bptr = bestdist;  for (i = BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS - 1; i >= 0; i--)    *bptr++ = 0x7FFFFFFFL;  /* For each color selected by find_nearby_colors,   * compute its distance to the center of each cell in the box.   * If that's less than best-so-far, update best distance and color number.   */  /* Nominal steps between cell centers ("x" in Thomas article) */#define STEP_C0  ((1 << C0_SHIFT) * C0_SCALE)#define STEP_C1  ((1 << C1_SHIFT) * C1_SCALE)#define STEP_C2  ((1 << C2_SHIFT) * C2_SCALE)  for (i = 0; i < numcolors; i++)    {      int r, g, b;#ifdef ORIGINAL_LIB_JPEG      icolor = GETJSAMPLE (colorlist[i]);      r = GETJSAMPLE (cinfo->colormap[0][icolor]);      g = GETJSAMPLE (cinfo->colormap[1][icolor]);      b = GETJSAMPLE (cinfo->colormap[2][icolor]);#else      icolor = colorlist[i];      r = nim->red[icolor];      g = nim->green[icolor];      b = nim->blue[icolor];#endif      /* Compute (square of) distance from minc0/c1/c2 to this color */      inc0 = (minc0 - r) * C0_SCALE;      dist0 = inc0 * inc0;      inc1 = (minc1 - g) * C1_SCALE;      dist0 += inc1 * inc1;      inc2 = (minc2 - b) * C2_SCALE;      dist0 += inc2 * inc2;      /* Form the initial difference increments */      inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;      inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;      inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;      /* Now loop over all cells in box, updating distance per Thomas method */      bptr = bestdist;      cptr = bestcolor;      xx0 = inc0;      for (ic0 = BOX_C0_ELEMS - 1; ic0 >= 0; ic0--)	{	  dist1 = dist0;	  xx1 = inc1;	  for (ic1 = BOX_C1_ELEMS - 1; ic1 >= 0; ic1--)	    {	      dist2 = dist1;	      xx2 = inc2;	      for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--)		{		  if (dist2 < *bptr)		    {		      *bptr = dist2;		      *cptr = (JSAMPLE) icolor;		    }		  dist2 += xx2;		  xx2 += 2 * STEP_C2 * STEP_C2;		  bptr++;		  cptr++;		}	      dist1 += xx1;	      xx1 += 2 * STEP_C1 * STEP_C1;	    }	  dist0 += xx0;	  xx0 += 2 * STEP_C0 * STEP_C0;	}    }}LOCAL (void)fill_inverse_cmap (#ifdef ORIGINAL_LIB_JPEG		    j_decompress_ptr cinfo,#else		    gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,#endif		    int c0, int c1, int c2)/* Fill the inverse-colormap entries in the update box that contains *//* histogram cell c0/c1/c2.  (Only that one cell MUST be filled, but *//* we can fill as many others as we wish.) */{#ifdef ORIGINAL_LIB_JPEG  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;#endif  hist3d histogram = cquantize->histogram;  int minc0, minc1, minc2;	/* lower left corner of update box */  int ic0, ic1, ic2;  register JSAMPLE *cptr;	/* pointer into bestcolor[] array */  register histptr cachep;	/* pointer into main cache array */  /* This array lists the candidate colormap indexes. */  JSAMPLE colorlist[MAXNUMCOLORS];  int numcolors;		/* number of candidate colors */  /* This array holds the actually closest colormap index for each cell. */  JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];  /* Convert cell coordinates to update box ID */  c0 >>= BOX_C0_LOG;  c1 >>= BOX_C1_LOG;  c2 >>= BOX_C2_LOG;  /* Compute true coordinates of update box's origin corner.   * Actually we compute the coordinates of the center of the corner   * histogram cell, which are the lower bounds of the volume we care about.   */  minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);  minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);  minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);  /* Determine which colormap entries are close enough to be candidates

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -