content: /*
   * Copyright (C) 2012 CyberAgent
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package jp.co.cyberagent.android.gpuimage;
  
  import android.opengl.GLES20;
  
  public class GPUImage3x3TextureSamplingFilter extends GPUImageFilter {
      public static final String THREE_X_THREE_TEXTURE_SAMPLING_VERTEX_SHADER = "" +
              "attribute vec4 position;\n" + 
              "attribute vec4 inputTextureCoordinate;\n" + 
              "\n" + 
              "uniform highp float texelWidth; \n" + 
              "uniform highp float texelHeight; \n" + 
              "\n" + 
              "varying vec2 textureCoordinate;\n" + 
              "varying vec2 leftTextureCoordinate;\n" + 
              "varying vec2 rightTextureCoordinate;\n" + 
              "\n" + 
              "varying vec2 topTextureCoordinate;\n" + 
              "varying vec2 topLeftTextureCoordinate;\n" + 
              "varying vec2 topRightTextureCoordinate;\n" + 
              "\n" + 
              "varying vec2 bottomTextureCoordinate;\n" + 
              "varying vec2 bottomLeftTextureCoordinate;\n" + 
              "varying vec2 bottomRightTextureCoordinate;\n" + 
              "\n" + 
              "void main()\n" + 
              "{\n" + 
              "    gl_Position = position;\n" + 
              "\n" + 
              "    vec2 widthStep = vec2(texelWidth, 0.0);\n" + 
              "    vec2 heightStep = vec2(0.0, texelHeight);\n" + 
              "    vec2 widthHeightStep = vec2(texelWidth, texelHeight);\n" + 
              "    vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);\n" + 
              "\n" + 
              "    textureCoordinate = inputTextureCoordinate.xy;\n" + 
              "    leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;\n" + 
              "    rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;\n" + 
              "\n" + 
              "    topTextureCoordinate = inputTextureCoordinate.xy - heightStep;\n" + 
              "    topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;\n" + 
              "    topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;\n" + 
              "\n" + 
              "    bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;\n" + 
              "    bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;\n" + 
              "    bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;\n" + 
              "}";
  
      private int mUniformTexelWidthLocation;
      private int mUniformTexelHeightLocation;
  
      private boolean mHasOverriddenImageSizeFactor = false;
      private float mTexelWidth; 
      private float mTexelHeight;
      private float mLineSize = 1.0f;
  
      public GPUImage3x3TextureSamplingFilter() {
          this(NO_FILTER_VERTEX_SHADER);
      }
  
      public GPUImage3x3TextureSamplingFilter(final String fragmentShader) {
          super(THREE_X_THREE_TEXTURE_SAMPLING_VERTEX_SHADER, fragmentShader);
      }
  
      @Override
      public void onInit() {
          super.onInit();
          mUniformTexelWidthLocation = GLES20.glGetUniformLocation(getProgram(), "texelWidth");
          mUniformTexelHeightLocation = GLES20.glGetUniformLocation(getProgram(), "texelHeight");
          if (mTexelWidth != 0) {
              updateTexelValues();
          }
      }
  
      @Override
      public void onOutputSizeChanged(final int width, final int height) {
          super.onOutputSizeChanged(width, height);
          if (!mHasOverriddenImageSizeFactor) {
              setLineSize(mLineSize);
          }
      }
  
      public void setTexelWidth(final float texelWidth) {
          mHasOverriddenImageSizeFactor = true;
          mTexelWidth = texelWidth;
          setFloat(mUniformTexelWidthLocation, texelWidth);
      }
  
      public void setTexelHeight(final float texelHeight) {
          mHasOverriddenImageSizeFactor = true;
          mTexelHeight = texelHeight;
          setFloat(mUniformTexelHeightLocation, texelHeight);
      }
  
      public void setLineSize(final float size) {
          mLineSize = size;
          mTexelWidth = size / getOutputWidth();
          mTexelHeight = size / getOutputHeight();
          updateTexelValues();
      }
  
      private void updateTexelValues() {
          setFloat(mUniformTexelWidthLocation, mTexelWidth);
          setFloat(mUniformTexelHeightLocation, mTexelHeight);
      }
  }
  