Support
Quality
Security
License
Reuse
kandi has reviewed android-gpuimage and discovered the below as its top functions. This is intended to give you an instant insight into android-gpuimage implemented functionality, and help decide if they suit your requirements.
Android filters based on OpenGL (idea from GPUImage for iOS)
Gradle dependency
repositories {
mavenCentral()
}
dependencies {
implementation 'jp.co.cyberagent.android:gpuimage:2.x.x'
}
Sample Code
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
Uri imageUri = ...;
gpuImage = new GPUImage(this);
gpuImage.setGLSurfaceView((GLSurfaceView) findViewById(R.id.surfaceView));
gpuImage.setImage(imageUri); // this loads image on the current thread, should be run in a thread
gpuImage.setFilter(new GPUImageSepiaFilter());
// Later when image should be saved saved:
gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null);
}
Gradle
gradle clean assemble
License
Copyright 2018 CyberAgent, Inc.
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.
How to make smoother borders using Fragment shader in OpenGL?
if ( current.a != 1.0 ) {
// other processing
if (current.a > 0.4) {
if ( (top.a < 0.4 || bottom.a < 0.4 || left.a < 0.4 || right.a < 0.4
|| topLeft.a < 0.4 || topRight.a < 0.4 || bottomLeft.a < 0.4 || bottomRight.a < 0.4 )
{
// Implement 3x3 box blur here
}
}
}
-----------------------
varying vec2 vecUV;
varying vec3 vecPos;
varying vec3 vecNormal;
void main() {
vecUV = uv * 3.0 - 1.0;
vecPos = (modelViewMatrix * vec4(position, 1.0)).xyz;
vecNormal = (modelViewMatrix * vec4(normal, 0.0)).xyz;
gl_Position = projectionMatrix * vec4(vecPos, 1.0);
}
precision highp float;
varying vec2 vecUV;
varying vec3 vecPos;
varying vec3 vecNormal;
uniform sampler2D inputImageTexture;
float normalProbabilityDensityFunction(in float x, in float sigma)
{
return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;
}
vec4 gaussianBlur()
{
// The gaussian operator size
// The higher this number, the better quality the outline will be
// But this number is expensive! O(n2)
const int matrixSize = 11;
// How far apart (in UV coordinates) are each cell in the Gaussian Blur
// Increase this for larger outlines!
vec2 offset = vec2(0.005, 0.005);
const int kernelSize = (matrixSize-1)/2;
float kernel[matrixSize];
// Create the 1-D kernel using a sigma
float sigma = 7.0;
for (int j = 0; j <= kernelSize; ++j)
{
kernel[kernelSize+j] = kernel[kernelSize-j] = normalProbabilityDensityFunction(float(j), sigma);
}
// Generate the normalization factor
float normalizationFactor = 0.0;
for (int j = 0; j < matrixSize; ++j)
{
normalizationFactor += kernel[j];
}
normalizationFactor = normalizationFactor * normalizationFactor;
// Apply the kernel to the fragment
vec4 outputColor = vec4(0.0);
for (int i=-kernelSize; i <= kernelSize; ++i)
{
for (int j=-kernelSize; j <= kernelSize; ++j)
{
float kernelValue = kernel[kernelSize+j]*kernel[kernelSize+i];
vec2 sampleLocation = vecUV.xy + vec2(float(i)*offset.x,float(j)*offset.y);
vec4 sample = texture2D(inputImageTexture, sampleLocation);
outputColor += kernelValue * sample;
}
}
// Divide by the normalization factor, so the weights sum to 1
outputColor = outputColor/(normalizationFactor*normalizationFactor);
return outputColor;
}
void main()
{
// After blurring, what alpha threshold should we define as outline?
float alphaTreshold = 0.3;
// How smooth the edges of the outline it should have?
float outlineSmoothness = 0.1;
// The outline color
vec4 outlineColor = vec4(1.0, 1.0, 1.0, 1.0);
// Sample the original image and generate a blurred version using a gaussian blur
vec4 originalImage = texture2D(inputImageTexture, vecUV);
vec4 blurredImage = gaussianBlur();
float alpha = smoothstep(alphaTreshold - outlineSmoothness, alphaTreshold + outlineSmoothness, blurredImage.a);
vec4 outlineFragmentColor = mix(vec4(0.0), outlineColor, alpha);
gl_FragColor = mix(outlineFragmentColor, originalImage, originalImage.a);
}
-----------------------
varying vec2 vecUV;
varying vec3 vecPos;
varying vec3 vecNormal;
void main() {
vecUV = uv * 3.0 - 1.0;
vecPos = (modelViewMatrix * vec4(position, 1.0)).xyz;
vecNormal = (modelViewMatrix * vec4(normal, 0.0)).xyz;
gl_Position = projectionMatrix * vec4(vecPos, 1.0);
}
precision highp float;
varying vec2 vecUV;
varying vec3 vecPos;
varying vec3 vecNormal;
uniform sampler2D inputImageTexture;
float normalProbabilityDensityFunction(in float x, in float sigma)
{
return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;
}
vec4 gaussianBlur()
{
// The gaussian operator size
// The higher this number, the better quality the outline will be
// But this number is expensive! O(n2)
const int matrixSize = 11;
// How far apart (in UV coordinates) are each cell in the Gaussian Blur
// Increase this for larger outlines!
vec2 offset = vec2(0.005, 0.005);
const int kernelSize = (matrixSize-1)/2;
float kernel[matrixSize];
// Create the 1-D kernel using a sigma
float sigma = 7.0;
for (int j = 0; j <= kernelSize; ++j)
{
kernel[kernelSize+j] = kernel[kernelSize-j] = normalProbabilityDensityFunction(float(j), sigma);
}
// Generate the normalization factor
float normalizationFactor = 0.0;
for (int j = 0; j < matrixSize; ++j)
{
normalizationFactor += kernel[j];
}
normalizationFactor = normalizationFactor * normalizationFactor;
// Apply the kernel to the fragment
vec4 outputColor = vec4(0.0);
for (int i=-kernelSize; i <= kernelSize; ++i)
{
for (int j=-kernelSize; j <= kernelSize; ++j)
{
float kernelValue = kernel[kernelSize+j]*kernel[kernelSize+i];
vec2 sampleLocation = vecUV.xy + vec2(float(i)*offset.x,float(j)*offset.y);
vec4 sample = texture2D(inputImageTexture, sampleLocation);
outputColor += kernelValue * sample;
}
}
// Divide by the normalization factor, so the weights sum to 1
outputColor = outputColor/(normalizationFactor*normalizationFactor);
return outputColor;
}
void main()
{
// After blurring, what alpha threshold should we define as outline?
float alphaTreshold = 0.3;
// How smooth the edges of the outline it should have?
float outlineSmoothness = 0.1;
// The outline color
vec4 outlineColor = vec4(1.0, 1.0, 1.0, 1.0);
// Sample the original image and generate a blurred version using a gaussian blur
vec4 originalImage = texture2D(inputImageTexture, vecUV);
vec4 blurredImage = gaussianBlur();
float alpha = smoothstep(alphaTreshold - outlineSmoothness, alphaTreshold + outlineSmoothness, blurredImage.a);
vec4 outlineFragmentColor = mix(vec4(0.0), outlineColor, alpha);
gl_FragColor = mix(outlineFragmentColor, originalImage, originalImage.a);
}
How to using GPUImage
public static GPUImageFilterGroup setAdjustment(int HueOpacity, float SaturationOpacity, int ShadowOpacity, float WarmOpacity) {
GPUImageFilterGroup filterGroup = new GPUImageFilterGroup();
filterGroup.addFilter(new GPUImageHueFilter(range(HueOpacity, 0.0f, 360.0f)));
filterGroup.addFilter(new GPUImageHighlightShadowFilter(range(ShadowOpacity, 0.0f, 1.0f), range(0, 1.0f, 0.0f)));
filterGroup.addFilter(new GPUImageWhiteBalanceFilter(range((int) WarmOpacity, 4000.0f, 8000.0f), range((int) SaturationOpacity, 0.0f, -2.0f)));
return filterGroup;
}
protected static float range(int percentage, float start, float end) {
return (((end - start) * ((float) percentage)) / 100.0f) + start;
}
private GPUImageView mainImageView;
//The default values
private float SaturationOpacity = 50.0f;
private float WarmOpacity = 50.0f;
private int ShadowOpacity = 0;
private int HueOpacity = 0;
mainImageView.setImage(YOUR BITMAP HERE);
seekBarHue.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
HueOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarShadow.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
ShadowOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarwarm.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
WarmOpacity = (float) i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
-----------------------
public static GPUImageFilterGroup setAdjustment(int HueOpacity, float SaturationOpacity, int ShadowOpacity, float WarmOpacity) {
GPUImageFilterGroup filterGroup = new GPUImageFilterGroup();
filterGroup.addFilter(new GPUImageHueFilter(range(HueOpacity, 0.0f, 360.0f)));
filterGroup.addFilter(new GPUImageHighlightShadowFilter(range(ShadowOpacity, 0.0f, 1.0f), range(0, 1.0f, 0.0f)));
filterGroup.addFilter(new GPUImageWhiteBalanceFilter(range((int) WarmOpacity, 4000.0f, 8000.0f), range((int) SaturationOpacity, 0.0f, -2.0f)));
return filterGroup;
}
protected static float range(int percentage, float start, float end) {
return (((end - start) * ((float) percentage)) / 100.0f) + start;
}
private GPUImageView mainImageView;
//The default values
private float SaturationOpacity = 50.0f;
private float WarmOpacity = 50.0f;
private int ShadowOpacity = 0;
private int HueOpacity = 0;
mainImageView.setImage(YOUR BITMAP HERE);
seekBarHue.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
HueOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarShadow.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
ShadowOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarwarm.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
WarmOpacity = (float) i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
-----------------------
public static GPUImageFilterGroup setAdjustment(int HueOpacity, float SaturationOpacity, int ShadowOpacity, float WarmOpacity) {
GPUImageFilterGroup filterGroup = new GPUImageFilterGroup();
filterGroup.addFilter(new GPUImageHueFilter(range(HueOpacity, 0.0f, 360.0f)));
filterGroup.addFilter(new GPUImageHighlightShadowFilter(range(ShadowOpacity, 0.0f, 1.0f), range(0, 1.0f, 0.0f)));
filterGroup.addFilter(new GPUImageWhiteBalanceFilter(range((int) WarmOpacity, 4000.0f, 8000.0f), range((int) SaturationOpacity, 0.0f, -2.0f)));
return filterGroup;
}
protected static float range(int percentage, float start, float end) {
return (((end - start) * ((float) percentage)) / 100.0f) + start;
}
private GPUImageView mainImageView;
//The default values
private float SaturationOpacity = 50.0f;
private float WarmOpacity = 50.0f;
private int ShadowOpacity = 0;
private int HueOpacity = 0;
mainImageView.setImage(YOUR BITMAP HERE);
seekBarHue.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
HueOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarShadow.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
ShadowOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarwarm.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
WarmOpacity = (float) i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
-----------------------
public static GPUImageFilterGroup setAdjustment(int HueOpacity, float SaturationOpacity, int ShadowOpacity, float WarmOpacity) {
GPUImageFilterGroup filterGroup = new GPUImageFilterGroup();
filterGroup.addFilter(new GPUImageHueFilter(range(HueOpacity, 0.0f, 360.0f)));
filterGroup.addFilter(new GPUImageHighlightShadowFilter(range(ShadowOpacity, 0.0f, 1.0f), range(0, 1.0f, 0.0f)));
filterGroup.addFilter(new GPUImageWhiteBalanceFilter(range((int) WarmOpacity, 4000.0f, 8000.0f), range((int) SaturationOpacity, 0.0f, -2.0f)));
return filterGroup;
}
protected static float range(int percentage, float start, float end) {
return (((end - start) * ((float) percentage)) / 100.0f) + start;
}
private GPUImageView mainImageView;
//The default values
private float SaturationOpacity = 50.0f;
private float WarmOpacity = 50.0f;
private int ShadowOpacity = 0;
private int HueOpacity = 0;
mainImageView.setImage(YOUR BITMAP HERE);
seekBarHue.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
HueOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarShadow.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
ShadowOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarwarm.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
WarmOpacity = (float) i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
-----------------------
public static GPUImageFilterGroup setAdjustment(int HueOpacity, float SaturationOpacity, int ShadowOpacity, float WarmOpacity) {
GPUImageFilterGroup filterGroup = new GPUImageFilterGroup();
filterGroup.addFilter(new GPUImageHueFilter(range(HueOpacity, 0.0f, 360.0f)));
filterGroup.addFilter(new GPUImageHighlightShadowFilter(range(ShadowOpacity, 0.0f, 1.0f), range(0, 1.0f, 0.0f)));
filterGroup.addFilter(new GPUImageWhiteBalanceFilter(range((int) WarmOpacity, 4000.0f, 8000.0f), range((int) SaturationOpacity, 0.0f, -2.0f)));
return filterGroup;
}
protected static float range(int percentage, float start, float end) {
return (((end - start) * ((float) percentage)) / 100.0f) + start;
}
private GPUImageView mainImageView;
//The default values
private float SaturationOpacity = 50.0f;
private float WarmOpacity = 50.0f;
private int ShadowOpacity = 0;
private int HueOpacity = 0;
mainImageView.setImage(YOUR BITMAP HERE);
seekBarHue.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
HueOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarShadow.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
ShadowOpacity = i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarwarm.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
WarmOpacity = (float) i;
mainImageView.setFilter(setAdjustment(HueOpacity,SaturationOpacity, ShadowOpacity, WarmOpacity));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
QUESTION
How to make smoother borders using Fragment shader in OpenGL?
Asked 2021-Nov-28 at 16:45I have been trying to draw border of an Image with transparent background using OpenGL in Android. I am using Fragment Shader & Vertex Shader. (From the GPUImage Library)
Below I have added Fig. A & Fig B.
Fig A.
Fig B.
I have achieved Fig A. With the customised Fragment Shader. But Unable to make the border smoother as in Fig B. I am attaching the Shader code that I have used (to achieve rough border). Can someone here help me on how to make the border smoother?
Here is my Vertex Shader :
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
void main()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
}
Here is my Fragment Shader :
I have calculated 8 pixels around the current pixel. If any one pixel of those 8 is opaque(having alpha greater than 0.4), It it drawn as a border color.
precision mediump float;
uniform sampler2D inputImageTexture;
varying vec2 textureCoordinate;
uniform lowp float thickness;
uniform lowp vec4 color;
void main() {
float x = textureCoordinate.x;
float y = textureCoordinate.y;
vec4 current = texture2D(inputImageTexture, vec2(x,y));
if ( current.a != 1.0 ) {
float offset = thickness * 0.5;
vec4 top = texture2D(inputImageTexture, vec2(x, y - offset));
vec4 topRight = texture2D(inputImageTexture, vec2(x + offset,y - offset));
vec4 topLeft = texture2D(inputImageTexture, vec2(x - offset, y - offset));
vec4 right = texture2D(inputImageTexture, vec2(x + offset, y ));
vec4 bottom = texture2D(inputImageTexture, vec2(x , y + offset));
vec4 bottomLeft = texture2D(inputImageTexture, vec2(x - offset, y + offset));
vec4 bottomRight = texture2D(inputImageTexture, vec2(x + offset, y + offset));
vec4 left = texture2D(inputImageTexture, vec2(x - offset, y ));
if ( top.a > 0.4 || bottom.a > 0.4 || left.a > 0.4 || right.a > 0.4 || topLeft.a > 0.4 || topRight.a > 0.4 || bottomLeft.a > 0.4 || bottomRight.a > 0.4 ) {
if (current.a != 0.0) {
current = mix(color , current , current.a);
} else {
current = color;
}
}
}
gl_FragColor = current;
}
ANSWER
Answered 2021-Nov-28 at 16:45In my filters, the smoothness is achieved by a simple boxblur on the border.. You have decided that alpha > 0.4 is a border. The value of alpha between 0-0.4 in surrounding pixels gives an edge. Just blur this edge with a 3x3 window to get the smooth edge.
if ( current.a != 1.0 ) {
// other processing
if (current.a > 0.4) {
if ( (top.a < 0.4 || bottom.a < 0.4 || left.a < 0.4 || right.a < 0.4
|| topLeft.a < 0.4 || topRight.a < 0.4 || bottomLeft.a < 0.4 || bottomRight.a < 0.4 )
{
// Implement 3x3 box blur here
}
}
}
You need to tweak which edge pixels you blur. The basic issue is that it drops from an opaque to a transparent pixel - what you need is a gradual transition.
Another options is quick anti-aliasing. From my comment below - Scale up 200% and then scale down 50% to original method. Use nearest neighbour scaling. This technique is used for smooth edges on text sometimes.
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
No vulnerabilities reported
Save this library and start creating your kit
Explore Related Topics
Save this library and start creating your kit