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

📄 dither.c

📁 linux下将各类格式图片转换工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  dither.c:		Various dithering routines 	 * *  Adapted by:		Ullrich Hafner *		 *  This file is part of FIASCO (獸籸actal 獻籱age 獳籲d 玈籩quence 獵O籨ec) *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> *//* * Copyright (c) 1995 Erik Corry * All rights reserved. *  * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. *  * IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. *  * ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" * BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *//* *  $Date: 2000/11/27 20:22:51 $ *  $Author: hafner $ *  $Revision: 5.3 $ *  $State: Exp $ */#include "config.h"#if HAVE_STRING_H#	include <string.h>#else /* not HAVE_STRING_H */#	include <strings.h>#endif /* not HAVE_STRING_H */#if STDC_HEADERS#	include <stdlib.h>#endif /* not STDC_HEADERS */#include "types.h"#include "macros.h"#include "error.h"#include "fiasco.h"#include "image.h"#include "misc.h"#include "dither.h"/*****************************************************************************				prototypes  *****************************************************************************/static int display_16_bit (const struct fiasco_renderer *this, unsigned char *ximage,		const fiasco_image_t *fiasco_image);static int display_24_bit_bgr (const struct fiasco_renderer *this, unsigned char *ximage,		    const fiasco_image_t *fiasco_image);static int display_24_bit_rgb (const struct fiasco_renderer *this, unsigned char *ximage,		    const fiasco_image_t *fiasco_image);static int display_32_bit (const struct fiasco_renderer *this, unsigned char *ximage,		const fiasco_image_t *fiasco_image);static intfree_bits_at_bottom (unsigned long a);static intfree_bits_at_top (unsigned long a);static intnumber_of_bits_set (unsigned long a);/*****************************************************************************				public code  *****************************************************************************/fiasco_renderer_t *fiasco_renderer_new (unsigned long red_mask, unsigned long green_mask,		     unsigned long blue_mask, unsigned bpp,		     int double_resolution)/* *  FIASCO renderer constructor. *  Allocate memory for the FIASCO renderer structure and *  initialize values. *  `red_mask', `green_mask', and `blue_mask' are the corresponding masks *  of the X11R6 XImage structure.  *  `bpp' gives the depth of the image in bits per pixel (16, 24, or 32). *  If `double_resolution' is not 0 the the image width and height is doubled. *  (fast pixel doubling, no interpolation!) * *  Return value: *	pointer to the new structure or NULL on error */{   if (bpp != 16 && bpp != 24 && bpp !=32)   {      set_error (_("Rendering depth of XImage must be 16, 24, or 32 bpp."));      return NULL;   }   else   {      fiasco_renderer_t  *render    = calloc (1, sizeof (fiasco_renderer_t));      renderer_private_t *private   = calloc (1, sizeof (renderer_private_t));      bool_t 	       	  twopixels = (bpp == 16 && double_resolution);      int 		  crval, cbval, i; /* counter */      if (!render || !private)      {	 set_error (_("Out of memory."));	 return NULL;      }      switch (bpp)      {	 case 16:	    render->render = display_16_bit;	    break;	 case 24:	    if (red_mask > green_mask)	       render->render = display_24_bit_rgb;	    else	       render->render = display_24_bit_bgr;	    break;	 case 32:	    render->render = display_32_bit;	    break;	 default:	    break;			/* does not happen */      }      render->private = private;      render->delete  = fiasco_renderer_delete;      private->double_resolution = double_resolution;      private->Cr_r_tab = calloc (256 + 2 * 1024, sizeof (int));      private->Cr_g_tab = calloc (256 + 2 * 1024, sizeof (int));      private->Cb_g_tab = calloc (256 + 2 * 1024, sizeof (int));      private->Cb_b_tab = calloc (256 + 2 * 1024, sizeof (int));      if (!private->Cr_r_tab || !private->Cr_g_tab	  || !private->Cb_b_tab || !private->Cb_g_tab)      {	 set_error (_("Out of memory."));	 return NULL;      }            for (i = 1024; i < 1024 + 256; i++)      {	 cbval = crval  = i - 128 - 1024;	 private->Cr_r_tab [i] =  1.4022 * crval + 0.5;	 private->Cr_g_tab [i] = -0.7145 * crval + 0.5;	 private->Cb_g_tab [i] = -0.3456 * cbval + 0.5; 	 private->Cb_b_tab [i] =  1.7710 * cbval + 0.5;      }      for (i = 0; i < 1024; i++)      {	 private->Cr_r_tab [i] = private->Cr_r_tab [1024];	 private->Cr_g_tab [i] = private->Cr_g_tab [1024];	 private->Cb_g_tab [i] = private->Cb_g_tab [1024]; 	 private->Cb_b_tab [i] = private->Cb_b_tab [1024];      }      for (i = 1024 + 256; i < 2048 + 256; i++)      {	 private->Cr_r_tab [i] = private->Cr_r_tab [1024 + 255];	 private->Cr_g_tab [i] = private->Cr_g_tab [1024 + 255];	 private->Cb_g_tab [i] = private->Cb_g_tab [1024 + 255]; 	 private->Cb_b_tab [i] = private->Cb_b_tab [1024 + 255];      }      private->Cr_r_tab += 1024 + 128;      private->Cr_g_tab += 1024 + 128;      private->Cb_g_tab += 1024 + 128;      private->Cb_b_tab += 1024 + 128;         /*        *  Set up entries 0-255 in rgb-to-pixel value tables.       */      private->r_table = calloc (256 + 2 * 1024, sizeof (unsigned int));      private->g_table = calloc (256 + 2 * 1024, sizeof (unsigned int));      private->b_table = calloc (256 + 2 * 1024, sizeof (unsigned int));      private->y_table = calloc (256 + 2 * 1024, sizeof (unsigned int));      if (!private->r_table || !private->g_table	  || !private->b_table || !private->y_table)      {	 set_error (_("Out of memory."));	 return NULL;      }            for (i = 0; i < 256; i++)      {	 private->r_table [i + 1024]	    = i >> (8 - number_of_bits_set(red_mask));	 private->r_table [i + 1024]	    <<= free_bits_at_bottom (red_mask);	 private->g_table [i + 1024]	    = i >> (8 - number_of_bits_set (green_mask));	 private->g_table [i + 1024]	    <<= free_bits_at_bottom (green_mask);	 private->b_table [i + 1024]	    <<= free_bits_at_bottom (blue_mask);	 private->b_table [i + 1024]	    = i >> (8 - number_of_bits_set (blue_mask));	 if (twopixels)	 {	    private->r_table [i + 1024] = ((private->r_table [i + 1024] << 16)					   | private->r_table [i + 1024]);	    private->g_table [i + 1024] = ((private->g_table [i + 1024] << 16)					   | private->g_table [i + 1024]);	    private->b_table [i + 1024] = ((private->b_table [i + 1024] << 16)					   | private->b_table [i + 1024]);	 }	 private->y_table [i + 1024] = (private->r_table [i + 1024]					| private->g_table [i + 1024]					| private->b_table [i + 1024]);      }      /*       * Spread out the values we have to the rest of the array so that       * we do not need to check for overflow.       */      for (i = 0; i < 1024; i++)      {	 private->r_table [i]              = private->r_table [1024];	 private->r_table [i + 1024 + 256] = private->r_table [1024 + 255];	 private->g_table [i]              = private->g_table [1024];	 private->g_table [i + 1024 + 256] = private->g_table [1024 + 255];	 private->b_table [i]              = private->b_table [1024];	 private->b_table [i + 1024 + 256] = private->b_table [1024 + 255];	 private->y_table [i]              = private->y_table [1024];	 private->y_table [i + 1024 + 256] = private->y_table [1024 + 255];      }      private->r_table += 1024;      private->g_table += 1024;      private->b_table += 1024;      private->y_table += 1024 + 128;      return render;   }   }voidfiasco_renderer_delete (fiasco_renderer_t *renderer)/* *  FIASCO renderer destructor: *  Free memory of 'renderer' structure. * *  No return value. * *  Side effects: *	structure 'renderer' is discarded. */{   if (!renderer)      return;   else   {      renderer_private_t *private = (renderer_private_t *) renderer->private;      Free (private->Cr_g_tab - (1024 + 128));      Free (private->Cr_r_tab - (1024 + 128));      Free (private->Cb_g_tab - (1024 + 128));      Free (private->Cb_b_tab - (1024 + 128));      Free (private->r_table - 1024);      Free (private->g_table - 1024);      Free (private->b_table - 1024);      Free (private->y_table - (1024 + 128));      Free (private);      Free (renderer);   }}intfiasco_renderer_render (const fiasco_renderer_t *renderer,			unsigned char *ximage,			const fiasco_image_t *fiasco_image){   if (!renderer)   {      set_error (_("Parameter `%s' not defined (NULL)."), "renderer");      return 0;   }   else      return renderer->render (renderer, ximage, fiasco_image);}/*****************************************************************************				private code  *****************************************************************************//* *  Erik Corry's multi-byte dither routines. * *  The basic idea is that the Init generates all the necessary *  tables.  The tables incorporate the information about the layout *  of pixels in the XImage, so that it should be able to cope with *  16-bit 24-bit (non-packed) and 32-bit (10-11 bits per *  color!) screens.  At present it cannot cope with 24-bit packed *  mode, since this involves getting down to byte level again. It is *  assumed that the bits for each color are contiguous in the *  longword. *  *  Writing to memory is done in shorts or ints. (Unfortunately, short *  is not very fast on Alpha, so there is room for improvement *  here). There is no dither time check for overflow - instead the *  tables have slack at each end. This is likely to be faster than an *  'if' test as many modern architectures are really bad at *  ifs. Potentially, each '&&' causes a pipeline flush! * *  There is no shifting and fixed point arithmetic, as I really doubt *  you can see the difference, and it costs. This may be just my *  bias, since I heard that Intel is really bad at shifting. */static intnumber_of_bits_set (unsigned long a)/* *  How many 1 bits are there in the longword. *  Low performance, do not call often. */{   if (!a)      return 0;   if (a & 1)      return 1 + number_of_bits_set (a >> 1);   else      return (number_of_bits_set (a >> 1));}static intfree_bits_at_top (unsigned long a)/* *  How many 0 bits are there at most significant end of longword. *  Low performance, do not call often. */{   if(!a)				/* assume char is 8 bits */      return sizeof (unsigned long) * 8;   else if (((long) a) < 0l)		/* assume twos complement */      return 0;   else      return 1 + free_bits_at_top ( a << 1);}static intfree_bits_at_bottom (unsigned long a)/* *  How many 0 bits are there at least significant end of longword. *  Low performance, do not call often. */{   /* assume char is 8 bits */   if (!a)      return sizeof (unsigned long) * 8;   else if(((long) a) & 1l)      return 0;   else      return 1 + free_bits_at_bottom ( a >> 1);}static int display_16_bit (const struct fiasco_renderer *this, unsigned char *ximage,		const fiasco_image_t *fiasco_image)/* *  Convert 'image' to 16 bit color bitmap. *  If 'double_resolution' is true then double image size in both directions. * *  No return value. * *  Side effects: *	'out[]'	is filled with dithered image */{   const image_t      *image;   renderer_private_t *private;   byte_t	      *out;      if (!this)   {      set_error (_("Parameter `%s' not defined (NULL)."), "this");      return 0;   }   if (!ximage)   {      set_error (_("Parameter `%s' not defined (NULL)."), "ximage");      return 0;   }   if (!fiasco_image)   {      set_error (_("Parameter `%s' not defined (NULL)."), "fiasco_image");      return 0;   }   out 	   = (byte_t *) ximage;   image   = cast_image ((fiasco_image_t *) fiasco_image);   if (!image)      return 0;   private = (renderer_private_t *) this->private;      if (image->color)   {      word_t 	   *cbptr, *crptr;	/* pointer to chroma bands */      word_t 	   *yptr;		/* pointers to lumincance band */      int     	    yval, crval, cbval;	/* pixel value in YCbCr color space */      int     	    R, G, B;		/* pixel value in RGB color space */      int     	    n;			/* pixel counter */      int     	    x, y;		/* pixel coordinates */      int 	   *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;      unsigned int *r_table, *g_table, *b_table;      Cr_g_tab = private->Cr_g_tab;      Cr_r_tab = private->Cr_r_tab;      Cb_b_tab = private->Cb_b_tab;      Cb_g_tab = private->Cb_g_tab;      r_table  = private->r_table;      g_table  = private->g_table;      b_table  = private->b_table;      yptr     = image->pixels [Y];      cbptr    = image->pixels [Cb];      crptr    = image->pixels [Cr];      if (image->format == FORMAT_4_2_0)      {	 u_word_t *dst, *dst2;		/* pointers to dithered pixels */	 word_t	  *yptr2;		/* pointers to lumincance band */	 if (private->double_resolution)	 {	    yptr2 = yptr + image->width;	    dst   = (u_word_t *) out;	    dst2  = dst + 4 * image->width;	    for (y = image->height / 2; y; y--)	    {	       for (x = image->width / 2; x; x--)	       {#ifdef HAVE_SIGNED_SHIFT		  crval = *crptr++ >> 4;		  cbval = *cbptr++ >> 4;		  yval  = (*yptr++ >> 4) + 128;#else /* not HAVE_SIGNED_SHIFT */		  crval = *crptr++ / 16;		  cbval = *cbptr++ / 16;		  yval  = *yptr++  / 16 + 128;#endif /* not HAVE_SIGNED_SHIFT */		  R = yval + Cr_r_tab [crval];		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];		  B = yval + Cb_b_tab [cbval];		  *dst++ = r_table [R] | g_table [G] | b_table [B];		  *dst++ = r_table [R] | g_table [G] | b_table [B];	       #ifdef HAVE_SIGNED_SHIFT		  yval  = (*yptr++ >> 4) + 128;#else /* not HAVE_SIGNED_SHIFT */		  yval  = *yptr++  / 16 + 128;#endif /* not HAVE_SIGNED_SHIFT */		  R = yval + Cr_r_tab [crval];		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];		  B = yval + Cb_b_tab [cbval];

⌨️ 快捷键说明

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