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

📄 pixops.c

📁 这是符合Linux操作系统标准的POIXS 的pixops-2.0.5源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright (C) 2000 Red Hat, Inc. * Portions copyright (C) 2004 VMware, Inc. * This file is part of the Pixops Library. * * The pixops library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * The pixops library 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 Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* * pixops.c -- * *      Implements C routines for image scaling. Some functions also have an *      MMX-accelerated implementation, see the corresponding .S files for the *      code. */#include <math.h>#include <stdlib.h>#include "pixops.h"#include "pixops-internal.h"#include "convert.h"#define SUBSAMPLE_BITS 4#define SUBSAMPLE (1 << SUBSAMPLE_BITS)#define SUBSAMPLE_MASK ((1 << SUBSAMPLE_BITS)-1)#define SCALE_SHIFT 16static intget_check_shift (int check_size){  int check_shift = 0;  return_val_if_fail (check_size >= 0, 4);  while (!(check_size & 1))    {      check_shift++;      check_size >>= 1;    }  return check_shift;}static voidpixops_scale_nearest (uint8 *dest_buf,		      int render_x0,		      int render_y0,		      int render_x1,		      int render_y1,		      int dest_rowstride,		      int dest_bytes_per_pixel,                      int dest_depth,		      boolean dest_has_alpha,		      const uint8  *src_buf,		      int src_width,		      int src_height,		      int src_rowstride,		      int src_bytes_per_pixel,                      int src_depth,                      uint32 *src_colormap,		      boolean src_has_alpha,		      double scale_x,		      double scale_y){   int i, j;   int x;   int x_step = (1 << SCALE_SHIFT) / scale_x;   int y_step = (1 << SCALE_SHIFT) / scale_y;   int src_bppdepth = BPPDEPTH(src_bytes_per_pixel << 3, src_depth);   int dest_bppdepth = BPPDEPTH(dest_bytes_per_pixel << 3, dest_depth);   /*    * Define this bogus type so the macro loop will work    */   typedef unsigned char uint24;#define INNER_LOOP(op, SRC_BPP, DEST_BPP, INDEXED) \  for (j=0; j < (render_x1 - render_x0); j++) { \     const unsigned char *p = src + (x >> SCALE_SHIFT) * (SRC_BPP >> 3); \     unsigned int pix; \     if (SRC_BPP == 24 && INDEXED == FALSE) { \        pix = op((p[0] | (p[1] << 8) | (p[2] << 16))); \     } else if (INDEXED == TRUE) { \        pix = op(src_colormap[*p]); \     } else { \        pix = op((*(uint##SRC_BPP *) p)); \     } \     if (DEST_BPP == 24) { \        dest[0] = pix & 0xff; \        dest[1] = (pix >> 8) & 0xff; \        dest[2] = (pix >> 16) & 0xff; \     } else { \        *((uint##DEST_BPP *) dest) = (uint##DEST_BPP) pix; \     } \     dest += DEST_BPP >> 3; \     x += x_step; \  } \  break;   for (i = 0; i < (render_y1 - render_y0); i++) {      const uint8 *src  = src_buf         + (((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT)         * src_rowstride;      uint8 *dest = dest_buf + i * dest_rowstride;      x = render_x0 * x_step + x_step / 2;      switch(src_bppdepth) {      case 8:	 switch(dest_bppdepth) {	 case 8:	    INNER_LOOP(CONVERT_NOP, 8, 8, TRUE);	 case 15:	    INNER_LOOP(CONVERT_24_TO_15, 8, 16, TRUE);	 case 16:	    INNER_LOOP(CONVERT_24_TO_16, 8, 16, TRUE);	 case 24:	    INNER_LOOP(CONVERT_NOP, 8, 24, TRUE);	 case 32:	    INNER_LOOP(CONVERT_NOP, 8, 32, TRUE);	 }	 break;      case 15:         switch(dest_bppdepth) {	 case 8:	    INNER_LOOP(CONVERT_15_TO_8BGR, 16, 8, FALSE);         case 15:            INNER_LOOP(CONVERT_NOP, 16, 16, FALSE);         case 16:            INNER_LOOP(CONVERT_15_TO_16, 16, 16, FALSE);         case 24:            INNER_LOOP(CONVERT_15_TO_24, 16, 24, FALSE);         case 32:            INNER_LOOP(CONVERT_15_TO_24, 16, 32, FALSE);         }         break;      case 16:	 switch(dest_bppdepth) {	 case 8:	    INNER_LOOP(CONVERT_16_TO_8BGR, 16, 8, FALSE);         case 15:            INNER_LOOP(CONVERT_16_TO_15, 16, 16, FALSE);         case 16:            INNER_LOOP(CONVERT_NOP, 16, 16, FALSE);         case 24:            INNER_LOOP(CONVERT_16_TO_24, 16, 24, FALSE);         case 32:            INNER_LOOP(CONVERT_16_TO_24, 16, 32, FALSE);	 }         break;      case 24:         switch(dest_bppdepth) {	 case 8:	    INNER_LOOP(CONVERT_24_TO_8BGR, 24, 8, FALSE);         case 15:            INNER_LOOP(CONVERT_24_TO_15, 24, 16, FALSE);         case 16:            INNER_LOOP(CONVERT_24_TO_16, 24, 16, FALSE);         case 24:            INNER_LOOP(CONVERT_NOP, 24, 24, FALSE);         case 32:            INNER_LOOP(CONVERT_NOP, 24, 32, FALSE);         }         break;      case 32:         switch(dest_bppdepth) {	 case 8:	    INNER_LOOP(CONVERT_24_TO_8BGR, 32, 8, FALSE);         case 15:            INNER_LOOP(CONVERT_24_TO_15, 32, 16, FALSE);         case 16:            INNER_LOOP(CONVERT_24_TO_16, 32, 16, FALSE);         case 24:            INNER_LOOP(CONVERT_NOP, 32, 24, FALSE);         case 32:            INNER_LOOP(CONVERT_NOP, 32, 32, FALSE);         }         break;      }   }#undef INNER_LOOP}static voidpixops_scale_composite_nearest (uint8 *dest_buf,                                int render_x0,                                int render_y0,                                int render_x1,                                int render_y1,                                int dest_rowstride,                                int dest_channels,                                boolean dest_has_alpha,                                const uint8  *src_buf,                                int src_width,                                int src_height,                                int src_rowstride,                                int src_channels,                                boolean src_has_alpha,                                double scale_x,                                double scale_y,                                int overall_alpha){  int i, j;  int x;  int x_step = (1 << SCALE_SHIFT) / scale_x;  int y_step = (1 << SCALE_SHIFT) / scale_y;  for (i = 0; i < (render_y1 - render_y0); i++) {     const uint8 *src  = src_buf        + (((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT)        * src_rowstride;     uint8       *dest = dest_buf + i * dest_rowstride;     x = render_x0 * x_step + x_step / 2;     for (j=0; j < (render_x1 - render_x0); j++) {        const uint8 *p = src + (x >> SCALE_SHIFT) * src_channels;        unsigned int  a0;        if (src_has_alpha)           a0 = (p[3] * overall_alpha) / 0xff;        else           a0 = overall_alpha;        switch (a0) {        case 0:           break;        case 255:           dest[0] = p[0];           dest[1] = p[1];           dest[2] = p[2];           if (dest_has_alpha)              dest[3] = 0xff;           break;        default:           if (dest_has_alpha) {              unsigned int w0 = 0xff * a0;              unsigned int w1 = (0xff - a0) * dest[3];              unsigned int w = w0 + w1;              dest[0] = (w0 * p[0] + w1 * dest[0]) / w;              dest[1] = (w0 * p[1] + w1 * dest[1]) / w;              dest[2] = (w0 * p[2] + w1 * dest[2]) / w;              dest[3] = w / 0xff;           } else {              unsigned int a1 = 0xff - a0;              unsigned int tmp;              tmp = a0 * p[0] + a1 * dest[0] + 0x80;              dest[0] = (tmp + (tmp >> 8)) >> 8;              tmp = a0 * p[1] + a1 * dest[1] + 0x80;              dest[1] = (tmp + (tmp >> 8)) >> 8;              tmp = a0 * p[2] + a1 * dest[2] + 0x80;              dest[2] = (tmp + (tmp >> 8)) >> 8;           }           break;        }        dest += dest_channels;        x += x_step;     }  }}static voidpixops_scale_composite_color_nearest (uint8 *dest_buf,                                      int render_x0,                                      int render_y0,                                      int render_x1,                                      int render_y1,                                      int dest_rowstride,                                      int dest_channels,                                      boolean dest_has_alpha,                                      const uint8  *src_buf,                                      int src_width,                                      int src_height,                                      int src_rowstride,                                      int src_channels,                                      boolean src_has_alpha,                                      double scale_x,                                      double scale_y,                                      int overall_alpha,                                      int check_x,                                      int check_y,                                      int check_size,                                      uint32 color1,                                      uint32 color2){  int i, j;  int x;  int x_step = (1 << SCALE_SHIFT) / scale_x;  int y_step = (1 << SCALE_SHIFT) / scale_y;  int r1, g1, b1, r2, g2, b2;  int check_shift = get_check_shift (check_size);  for (i = 0; i < (render_y1 - render_y0); i++) {     const uint8 *src  = src_buf +        (((i + render_y0) * y_step + y_step/2) >> SCALE_SHIFT)        * src_rowstride;     uint8 *dest = dest_buf + i * dest_rowstride;     x = render_x0 * x_step + x_step / 2;     if (((i + check_y) >> check_shift) & 1) {        r1 = (color2 & 0xff0000) >> 16;        g1 = (color2 & 0xff00) >> 8;        b1 = color2 & 0xff;        r2 = (color1 & 0xff0000) >> 16;        g2 = (color1 & 0xff00) >> 8;        b2 = color1 & 0xff;     } else {        r1 = (color1 & 0xff0000) >> 16;        g1 = (color1 & 0xff00) >> 8;        b1 = color1 & 0xff;        r2 = (color2 & 0xff0000) >> 16;        g2 = (color2 & 0xff00) >> 8;        b2 = color2 & 0xff;     }     for (j=0 ; j < (render_x1 - render_x0); j++) {        const uint8 *p = src + (x >> SCALE_SHIFT) * src_channels;        int a0;        int tmp;        if (src_has_alpha)           a0 = (p[3] * overall_alpha + 0xff) >> 8;        else           a0 = overall_alpha;        switch (a0) {        case 0:           if (((j + check_x) >> check_shift) & 1) {              dest[0] = r2;              dest[1] = g2;              dest[2] = b2;           } else {              dest[0] = r1;              dest[1] = g1;              dest[2] = b1;           }           break;        case 255:           dest[0] = p[0];           dest[1] = p[1];           dest[2] = p[2];           break;        default:           if (((j + check_x) >> check_shift) & 1) {              tmp = ((int) p[0] - r2) * a0;              dest[0] = r2 + ((tmp + (tmp >> 8) + 0x80) >> 8);              tmp = ((int) p[1] - g2) * a0;              dest[1] = g2 + ((tmp + (tmp >> 8) + 0x80) >> 8);              tmp = ((int) p[2] - b2) * a0;              dest[2] = b2 + ((tmp + (tmp >> 8) + 0x80) >> 8);           } else {              tmp = ((int) p[0] - r1) * a0;              dest[0] = r1 + ((tmp + (tmp >> 8) + 0x80) >> 8);              tmp = ((int) p[1] - g1) * a0;              dest[1] = g1 + ((tmp + (tmp >> 8) + 0x80) >> 8);              tmp = ((int) p[2] - b1) * a0;              dest[2] = b1 + ((tmp + (tmp >> 8) + 0x80) >> 8);           }           break;        }        if (dest_channels == 4)           dest[3] = 0xff;        dest += dest_channels;        x += x_step;     }  }}static voidcomposite_pixel (uint8 *dest,                 int dest_x,                 int dest_bytes_per_pixel,                 int dest_depth,                 int dest_has_alpha,		 int src_has_alpha,                 int check_size,                 uint32 color1,                 uint32 color2,		 uint r, uint g, uint b, uint a){  if (dest_has_alpha) {     unsigned int w0 = a - (a >> 8);     unsigned int w1 = ((0xff0000 - a) >> 8) * dest[3];     unsigned int w = w0 + w1;     if (w != 0) {        dest[0] = (r - (r >> 8) + w1 * dest[0]) / w;        dest[1] = (g - (g >> 8) + w1 * dest[1]) / w;        dest[2] = (b - (b >> 8) + w1 * dest[2]) / w;        dest[3] = w / 0xff00;     } else {        dest[0] = 0;        dest[1] = 0;        dest[2] = 0;        dest[3] = 0;     }  } else {     dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;     dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;     dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;  }}static uint8 *composite_line (int *weights,                int n_x,                int n_y,		uint8 *dest,                int dest_x,                uint8 *dest_end,                int dest_bytes_per_pixel,                int dest_depth,                int dest_has_alpha,		uint8 **src,                int src_bytes_per_pixel,                int src_depth,                uint32 *src_colormap,                boolean src_has_alpha,		int x_init,                int x_step,                int src_width,		int check_size,                uint32 color1,                uint32 color2){   int x = x_init;   int i, j;   while (dest < dest_end) {      int x_scaled = x >> SCALE_SHIFT;      unsigned int r = 0, g = 0, b = 0, a = 0;      int *pixel_weights;      pixel_weights = weights         + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK)         * n_x * n_y;      for (i=0; i<n_y; i++) {         uint8 *q = src[i] + x_scaled * src_bytes_per_pixel;         int *line_weights = pixel_weights + n_x * i;         for (j=0; j<n_x; j++) {            unsigned int ta;            if (src_has_alpha)               ta = q[3] * line_weights[j];            else               ta = 0xff * line_weights[j];

⌨️ 快捷键说明

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