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

📄 convolve.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
convolve_2d_constant(GLint srcWidth, GLint srcHeight,
                     const GLfloat src[][4],
                     GLint filterWidth, GLint filterHeight,
                     const GLfloat filter[][4],
                     GLfloat dest[][4],
                     const GLfloat borderColor[4])
{
   const GLint halfFilterWidth = filterWidth / 2;
   const GLint halfFilterHeight = filterHeight / 2;
   GLint i, j, n, m;

   for (j = 0; j < srcHeight; j++) {
      for (i = 0; i < srcWidth; i++) {
         GLfloat sumR = 0.0;
         GLfloat sumG = 0.0;
         GLfloat sumB = 0.0;
         GLfloat sumA = 0.0;
         for (m = 0; m < filterHeight; m++) {
            for (n = 0; n < filterWidth; n++) {
               const GLint f = m * filterWidth + n;
               const GLint is = i + n - halfFilterWidth;
               const GLint js = j + m - halfFilterHeight;
               if (is < 0 || is >= srcWidth ||
                   js < 0 || js >= srcHeight) {
                  sumR += borderColor[RCOMP] * filter[f][RCOMP];
                  sumG += borderColor[GCOMP] * filter[f][GCOMP];
                  sumB += borderColor[BCOMP] * filter[f][BCOMP];
                  sumA += borderColor[ACOMP] * filter[f][ACOMP];
               }
               else {
                  const GLint k = js * srcWidth + is;
                  sumR += src[k][RCOMP] * filter[f][RCOMP];
                  sumG += src[k][GCOMP] * filter[f][GCOMP];
                  sumB += src[k][BCOMP] * filter[f][BCOMP];
                  sumA += src[k][ACOMP] * filter[f][ACOMP];
               }
            }
         }
         dest[j * srcWidth + i][RCOMP] = sumR;
         dest[j * srcWidth + i][GCOMP] = sumG;
         dest[j * srcWidth + i][BCOMP] = sumB;
         dest[j * srcWidth + i][ACOMP] = sumA;
      }
   }
}


static void
convolve_2d_replicate(GLint srcWidth, GLint srcHeight,
                      const GLfloat src[][4],
                      GLint filterWidth, GLint filterHeight,
                      const GLfloat filter[][4],
                      GLfloat dest[][4])
{
   const GLint halfFilterWidth = filterWidth / 2;
   const GLint halfFilterHeight = filterHeight / 2;
   GLint i, j, n, m;

   for (j = 0; j < srcHeight; j++) {
      for (i = 0; i < srcWidth; i++) {
         GLfloat sumR = 0.0;
         GLfloat sumG = 0.0;
         GLfloat sumB = 0.0;
         GLfloat sumA = 0.0;
         for (m = 0; m < filterHeight; m++) {
            for (n = 0; n < filterWidth; n++) {
               const GLint f = m * filterWidth + n;
               GLint is = i + n - halfFilterWidth;
               GLint js = j + m - halfFilterHeight;
               GLint k;
               if (is < 0)
                  is = 0;
               else if (is >= srcWidth)
                  is = srcWidth - 1;
               if (js < 0)
                  js = 0;
               else if (js >= srcHeight)
                  js = srcHeight - 1;
               k = js * srcWidth + is;
               sumR += src[k][RCOMP] * filter[f][RCOMP];
               sumG += src[k][GCOMP] * filter[f][GCOMP];
               sumB += src[k][BCOMP] * filter[f][BCOMP];
               sumA += src[k][ACOMP] * filter[f][ACOMP];
            }
         }
         dest[j * srcWidth + i][RCOMP] = sumR;
         dest[j * srcWidth + i][GCOMP] = sumG;
         dest[j * srcWidth + i][BCOMP] = sumB;
         dest[j * srcWidth + i][ACOMP] = sumA;
      }
   }
}


static void
convolve_sep_reduce(GLint srcWidth, GLint srcHeight,
                    const GLfloat src[][4],
                    GLint filterWidth, GLint filterHeight,
                    const GLfloat rowFilt[][4],
                    const GLfloat colFilt[][4],
                    GLfloat dest[][4])
{
   GLint dstWidth, dstHeight;
   GLint i, j, n, m;

   if (filterWidth >= 1)
      dstWidth = srcWidth - (filterWidth - 1);
   else
      dstWidth = srcWidth;

   if (filterHeight >= 1)
      dstHeight = srcHeight - (filterHeight - 1);
   else
      dstHeight = srcHeight;

   if (dstWidth <= 0 || dstHeight <= 0)
      return;

   for (j = 0; j < dstHeight; j++) {
      for (i = 0; i < dstWidth; i++) {
         GLfloat sumR = 0.0;
         GLfloat sumG = 0.0;
         GLfloat sumB = 0.0;
         GLfloat sumA = 0.0;
         for (m = 0; m < filterHeight; m++) {
            for (n = 0; n < filterWidth; n++) {
               GLint k = (j + m) * srcWidth + i + n;
               sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
               sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
               sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
               sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
            }
         }
         dest[j * dstWidth + i][RCOMP] = sumR;
         dest[j * dstWidth + i][GCOMP] = sumG;
         dest[j * dstWidth + i][BCOMP] = sumB;
         dest[j * dstWidth + i][ACOMP] = sumA;
      }
   }
}


static void
convolve_sep_constant(GLint srcWidth, GLint srcHeight,
                      const GLfloat src[][4],
                      GLint filterWidth, GLint filterHeight,
                      const GLfloat rowFilt[][4],
                      const GLfloat colFilt[][4],
                      GLfloat dest[][4],
                      const GLfloat borderColor[4])
{
   const GLint halfFilterWidth = filterWidth / 2;
   const GLint halfFilterHeight = filterHeight / 2;
   GLint i, j, n, m;

   for (j = 0; j < srcHeight; j++) {
      for (i = 0; i < srcWidth; i++) {
         GLfloat sumR = 0.0;
         GLfloat sumG = 0.0;
         GLfloat sumB = 0.0;
         GLfloat sumA = 0.0;
         for (m = 0; m < filterHeight; m++) {
            for (n = 0; n < filterWidth; n++) {
               const GLint is = i + n - halfFilterWidth;
               const GLint js = j + m - halfFilterHeight;
               if (is < 0 || is >= srcWidth ||
                   js < 0 || js >= srcHeight) {
                  sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
                  sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
                  sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
                  sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
               }
               else {
                  GLint k = js * srcWidth + is;
                  sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
                  sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
                  sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
                  sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
               }

            }
         }
         dest[j * srcWidth + i][RCOMP] = sumR;
         dest[j * srcWidth + i][GCOMP] = sumG;
         dest[j * srcWidth + i][BCOMP] = sumB;
         dest[j * srcWidth + i][ACOMP] = sumA;
      }
   }
}


static void
convolve_sep_replicate(GLint srcWidth, GLint srcHeight,
                       const GLfloat src[][4],
                       GLint filterWidth, GLint filterHeight,
                       const GLfloat rowFilt[][4],
                       const GLfloat colFilt[][4],
                       GLfloat dest[][4])
{
   const GLint halfFilterWidth = filterWidth / 2;
   const GLint halfFilterHeight = filterHeight / 2;
   GLint i, j, n, m;

   for (j = 0; j < srcHeight; j++) {
      for (i = 0; i < srcWidth; i++) {
         GLfloat sumR = 0.0;
         GLfloat sumG = 0.0;
         GLfloat sumB = 0.0;
         GLfloat sumA = 0.0;
         for (m = 0; m < filterHeight; m++) {
            for (n = 0; n < filterWidth; n++) {
               GLint is = i + n - halfFilterWidth;
               GLint js = j + m - halfFilterHeight;
               GLint k;
               if (is < 0)
                  is = 0;
               else if (is >= srcWidth)
                  is = srcWidth - 1;
               if (js < 0)
                  js = 0;
               else if (js >= srcHeight)
                  js = srcHeight - 1;
               k = js * srcWidth + is;
               sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
               sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
               sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
               sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
            }
         }
         dest[j * srcWidth + i][RCOMP] = sumR;
         dest[j * srcWidth + i][GCOMP] = sumG;
         dest[j * srcWidth + i][BCOMP] = sumB;
         dest[j * srcWidth + i][ACOMP] = sumA;
      }
   }
}



void
_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
                        const GLfloat *srcImage, GLfloat *dstImage)
{
   switch (ctx->Pixel.ConvolutionBorderMode[0]) {
      case GL_REDUCE:
         convolve_1d_reduce(*width, (const GLfloat (*)[4]) srcImage,
                            ctx->Convolution1D.Width,
                            (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
                            (GLfloat (*)[4]) dstImage);
         *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
         break;
      case GL_CONSTANT_BORDER:
         convolve_1d_constant(*width, (const GLfloat (*)[4]) srcImage,
                              ctx->Convolution1D.Width,
                              (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
                              (GLfloat (*)[4]) dstImage,
                              ctx->Pixel.ConvolutionBorderColor[0]);
         break;
      case GL_REPLICATE_BORDER:
         convolve_1d_replicate(*width, (const GLfloat (*)[4]) srcImage,
                              ctx->Convolution1D.Width,
                              (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
                              (GLfloat (*)[4]) dstImage);
         break;
      default:
         ;
   }
}


void
_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
                        const GLfloat *srcImage, GLfloat *dstImage)
{
   switch (ctx->Pixel.ConvolutionBorderMode[1]) {
      case GL_REDUCE:
         convolve_2d_reduce(*width, *height,
                            (const GLfloat (*)[4]) srcImage,
                            ctx->Convolution2D.Width,
                            ctx->Convolution2D.Height,
                            (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
                            (GLfloat (*)[4]) dstImage);
         *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
         *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
         break;
      case GL_CONSTANT_BORDER:
         convolve_2d_constant(*width, *height,
                              (const GLfloat (*)[4]) srcImage,
                              ctx->Convolution2D.Width,
                              ctx->Convolution2D.Height,
                              (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
                              (GLfloat (*)[4]) dstImage,
                              ctx->Pixel.ConvolutionBorderColor[1]);
         break;
      case GL_REPLICATE_BORDER:
         convolve_2d_replicate(*width, *height,
                               (const GLfloat (*)[4]) srcImage,
                               ctx->Convolution2D.Width,
                               ctx->Convolution2D.Height,
                               (const GLfloat (*)[4])ctx->Convolution2D.Filter,
                               (GLfloat (*)[4]) dstImage);
         break;
      default:
         ;
      }
}


void
_mesa_convolve_sep_image(const GLcontext *ctx,
                         GLsizei *width, GLsizei *height,
                         const GLfloat *srcImage, GLfloat *dstImage)
{
   const GLfloat *rowFilter = ctx->Separable2D.Filter;
   const GLfloat *colFilter = rowFilter + 4 * MAX_CONVOLUTION_WIDTH;

   switch (ctx->Pixel.ConvolutionBorderMode[2]) {
      case GL_REDUCE:
         convolve_sep_reduce(*width, *height,
                             (const GLfloat (*)[4]) srcImage,
                             ctx->Separable2D.Width,
                             ctx->Separable2D.Height,
                             (const GLfloat (*)[4]) rowFilter,
                             (const GLfloat (*)[4]) colFilter,
                             (GLfloat (*)[4]) dstImage);
         *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
         *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
         break;
      case GL_CONSTANT_BORDER:
         convolve_sep_constant(*width, *height,
                               (const GLfloat (*)[4]) srcImage,
                               ctx->Separable2D.Width,
                               ctx->Separable2D.Height,
                               (const GLfloat (*)[4]) rowFilter,
                               (const GLfloat (*)[4]) colFilter,
                               (GLfloat (*)[4]) dstImage,
                               ctx->Pixel.ConvolutionBorderColor[2]);
         break;
      case GL_REPLICATE_BORDER:
         convolve_sep_replicate(*width, *height,
                                (const GLfloat (*)[4]) srcImage,
                                ctx->Separable2D.Width,
                                ctx->Separable2D.Height,
                                (const GLfloat (*)[4]) rowFilter,
                                (const GLfloat (*)[4]) colFilter,
                                (GLfloat (*)[4]) dstImage);
         break;
      default:
         ;
   }
}



/*
 * This function computes an image's size after convolution.
 * If the convolution border mode is GL_REDUCE, the post-convolution
 * image will be smaller than the original.
 */
void
_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
                                   GLsizei *width, GLsizei *height)
{
   if (ctx->Pixel.Convolution1DEnabled
       && dimensions == 1
       && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
      *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
   }
   else if (ctx->Pixel.Convolution2DEnabled
            && dimensions > 1
            && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
      *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
      *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
   }
   else if (ctx->Pixel.Separable2DEnabled
            && dimensions > 1
            && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
      *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
      *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
   }
}

⌨️ 快捷键说明

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