Android filters based on OpenGL (idea from GPUImage for iOS)

Overview

GPUImage for Android

License Download Maven Central Build Status

Idea from: iOS GPUImage framework

Goal is to have something as similar to GPUImage as possible. Vertex and fragment shaders are exactly the same. That way it makes it easier to port filters from GPUImage iOS to Android.

Requirements

  • Android 2.2 or higher (OpenGL ES 2.0)

Usage

Gradle dependency

repositories {
    mavenCentral()
}

dependencies {
    implementation 'jp.co.cyberagent.android:gpuimage:2.x.x'
}

Sample Code

With preview:

Java:

@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);
}

Kotlin:

public override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_gallery)

    val imageUri: Uri = ...
    gpuImage = GPUImage(this)
    gpuImage.setGLSurfaceView(findViewById<GLSurfaceView>(R.id.surfaceView))
    gpuImage.setImage(imageUri) // this loads image on the current thread, should be run in a thread
    gpuImage.setFilter(GPUImageSepiaFilter())

    // Later when image should be saved saved:
    gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null)
}

Using GPUImageView

<jp.co.cyberagent.android.gpuimage.GPUImageView
    android:id="@+id/gpuimageview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:gpuimage_show_loading="false"
    app:gpuimage_surface_type="texture_view" /> <!-- surface_view or texture_view -->

Java:

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);

    Uri imageUri = ...;
    gpuImageView = findViewById(R.id.gpuimageview);
    gpuImageView.setImage(imageUri); // this loads image on the current thread, should be run in a thread
    gpuImageView.setFilter(new GPUImageSepiaFilter());

    // Later when image should be saved saved:
    gpuImageView.saveToPictures("GPUImage", "ImageWithFilter.jpg", null);
}

Kotlin:

public override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_gallery)

    val imageUri: Uri = ...
    gpuImageView = findViewById<GPUImageView>(R.id.gpuimageview)
    gpuImageView.setImage(imageUri) // this loads image on the current thread, should be run in a thread
    gpuImageView.setFilter(GPUImageSepiaFilter())

    // Later when image should be saved saved:
    gpuImageView.saveToPictures("GPUImage", "ImageWithFilter.jpg", null)
}

Without preview:

Java:

public void onCreate(final Bundle savedInstanceState) {
    public void onCreate(final Bundle savedInstanceState) {
    Uri imageUri = ...;
    gpuImage = new GPUImage(context);
    gpuImage.setFilter(new GPUImageSobelEdgeDetection());
    gpuImage.setImage(imageUri);
    gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null);
}

Kotlin:

public override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_gallery)
    val imageUri: Uri = ...
    gpuImage = GPUImage(this)
    gpuImage.setFilter(GPUImageSepiaFilter())
    gpuImage.setImage(imageUri)
    gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null)
}

Support status of GPUImage for iOS shaders

  • Saturation
  • Contrast
  • Brightness
  • Levels
  • Exposure
  • RGB
  • RGB Diation
  • Hue
  • White Balance
  • Monochrome
  • False Color
  • Sharpen
  • Unsharp Mask
  • Transform Operation
  • Crop
  • Gamma
  • Highlights and Shadows
  • Haze
  • Sepia Tone
  • Amatorka
  • Miss Etikate
  • Soft Elegance
  • Color Inversion
  • Solarize
  • Vibrance
  • Highlight and Shadow Tint
  • Luminance
  • Luminance Threshold
  • Average Color
  • Average Luminance
  • Average Luminance Threshold
  • Adaptive Threshold
  • Polar Pixellate
  • Pixellate
  • Polka Dot
  • Halftone
  • Crosshatch
  • Sobel Edge Detection
  • Prewitt Edge Detection
  • Canny Edge Detection
  • Threshold Sobel EdgeDetection
  • Harris Corner Detector
  • Noble Corner Detector
  • Shi Tomasi Feature Detector
  • Colour FAST Feature Detector
  • Low Pass Filter
  • High Pass Filter
  • Sketch Filter
  • Threshold Sketch Filter
  • Toon Filter
  • SmoothToon Filter
  • Tilt Shift
  • CGA Colorspace Filter
  • Posterize
  • Convolution 3x3
  • Emboss Filter
  • Laplacian
  • Chroma Keying
  • Kuwahara Filter
  • Kuwahara Radius3 Filter
  • Vignette
  • Gaussian Blur
  • Box Blur
  • Bilateral Blur
  • Motion Blur
  • Zoom Blur
  • iOS Blur
  • Median Filter
  • Swirl Distortion
  • Bulge Distortion
  • Pinch Distortion
  • Sphere Refraction
  • Glass Sphere Refraction
  • Stretch Distortion
  • Dilation
  • Erosion
  • Opening Filter
  • Closing Filter
  • Local Binary Pattern
  • Color Local Binary Pattern
  • Dissolve Blend
  • Chroma Key Blend
  • Add Blend
  • Divide Blend
  • Multiply Blend
  • Overlay Blend
  • Lighten Blend
  • Darken Blend
  • Color Burn Blend
  • Color Dodge Blend
  • Linear Burn Blend
  • Screen Blend
  • Difference Blend
  • Subtract Blend
  • Exclusion Blend
  • HardLight Blend
  • SoftLight Blend
  • Color Blend
  • Hue Blend
  • Saturation Blend
  • Luminosity Blend
  • Normal Blend
  • Source Over Blend
  • Alpha Blend
  • Non Maximum Suppression
  • Thresholded Non Maximum Suppression
  • Directional Non Maximum Suppression
  • Opacity
  • Weak Pixel Inclusion Filter
  • Color Matrix
  • Directional Sobel Edge Detection
  • Lookup
  • Tone Curve (*.acv files)

Others

  • Texture 3x3
  • Gray Scale

Gradle

Make sure that you run the clean target when using maven.

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.
Comments
  • App crashes when the range changes quickly.

    App crashes when the range changes quickly.

    When the sample app is running, if you change the range quickly, sometimes the app will crash. I got the following adb messages:

    01-06 13:35:14.462 14995 15045 E AndroidRuntime: FATAL EXCEPTION: GLThread 4239 01-06 13:35:14.462 14995 15045 E AndroidRuntime: java.util.NoSuchElementException 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at java.util.LinkedList.removeFirstImpl(LinkedList.java:689) 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at java.util.LinkedList.removeFirst(LinkedList.java:676) 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at jp.co.cyberagent.android.gpuimage.GPUImageFilter.runPendingOnDrawTasks(GPUImageFilter.java:127) 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at jp.co.cyberagent.android.gpuimage.GPUImageFilter.onDraw(GPUImageFilter.java:102) 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at jp.co.cyberagent.android.gpuimage.GPUImageFilterGroup.onDraw(GPUImageFilterGroup.java:158) 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at jp.co.cyberagent.android.gpuimage.GPUImageRenderer.onDrawFrame(GPUImageRenderer.java:133) 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1487) 01-06 13:35:14.462 14995 15045 E AndroidRuntime: at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1241) 01-06 13:35:14.472 744 1067 W ActivityManager: Force finishing activity jp.co.cyberagent.android.gpuimage.sample/.activity.ActivityCamera 01-06 13:35:14.492 666 15052 I libcamera: int android::CameraHardware::aeAfAwbThread(): previewaeafawb is waiting

    Looks like a synchronization issue?

    opened by swcai 16
  • Google Play 64-bit requirement

    Google Play 64-bit requirement

    Hi

    does this library support 64 bit?

    I use this library in my app when I upload the Android App Bundle, I get this message :

    image

    I have tried two versions 2.0.3 and 1.4.1 (since I can't see the libgpuimage-library.so in 2.0.3) .

    After analyzing the Android App Bundle :

    image

    here's my Gradle file :

    android {
            compileSdkVersion 29
            dexOptions {
                preDexLibraries = false
                javaMaxHeapSize "4g"
            }
            defaultConfig {
                applicationId "maa.abc"
                minSdkVersion 18
                targetSdkVersion 29
                versionCode 14
                versionName "1.2.0"
                multiDexEnabled true
                renderscriptTargetApi 28
                renderscriptSupportModeEnabled true
                testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
                ndk.abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'armeabi', 'mips', 'mips64'
            }
            buildTypes {
                release {
                    minifyEnabled true
                    shrinkResources true
                    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                }
                debug {
                    minifyEnabled false
                    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                }
            }
            compileOptions {
                sourceCompatibility JavaVersion.VERSION_1_8
                targetCompatibility JavaVersion.VERSION_1_8
            }
            packagingOptions {
                exclude 'META-INF/DEPENDENCIES.txt'
                exclude 'META-INF/LICENSE.txt'
                exclude 'META-INF/NOTICE.txt'
                exclude 'META-INF/NOTICE'
                exclude 'META-INF/LICENSE'
                exclude 'META-INF/DEPENDENCIES'
                exclude 'META-INF/notice.txt'
                exclude 'META-INF/license.txt'
                exclude 'META-INF/dependencies.txt'
                exclude 'META-INF/LGPL2.annotations1'
            }
        }
    
        dependencies {
      implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation project(':appintro')
        /*ANDROID*/
        implementation 'androidx.appcompat:appcompat:1.0.2'
        implementation 'androidx.cardview:cardview:1.0.0'
        implementation 'androidx.exifinterface:exifinterface:1.0.0'
        implementation 'com.android.support:support-annotations:28.0.3'
        implementation 'androidx.legacy:legacy-support-v4:1.0.0'
        implementation 'androidx.multidex:multidex:2.0.1'
        annotationProcessor 'androidx.annotation:annotation:1.1.0'
        implementation 'androidx.recyclerview:recyclerview:1.0.0'
        implementation 'com.google.android.material:material:1.0.0'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    
    
        /*PHOTO FILTERS (CONTAINS NATIVE CODE)*/
        implementation 'cn.ezandroid:EZFilter:2.0.9'
        implementation 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'
    
        /*ANIMATION*/
        implementation 'com.daimajia.easing:library:2.0@aar'
        implementation 'com.daimajia.androidanimations:library:2.3@aar'
    
        /*GLIDE*/
        annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
        implementation 'com.github.bumptech.glide:glide:4.9.0'
    
    
        /*PICK IMAGE /TAKE PICTURE*/
        implementation 'com.github.jkwiecien:EasyImage:1.3.1'
    
        /*TEST IMPLEMENTATION*/
        androidTestImplementation 'androidx.test:runner:1.2.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
        testImplementation 'junit:junit:4.12'
    
    
        /*VIEWS*/
        implementation 'com.github.chrisbanes:PhotoView:2.3.0'
        implementation 'de.hdodenhof:circleimageview:3.0.0'
        implementation 'com.alexvasilkov:gesture-views:2.5.2'
        implementation('com.github.christophesmet:android_maskable_layout:v1.3.1') {
            exclude group: 'com.intellij', module: 'annotations'
        }
        implementation 'com.h6ah4i.android.widget.verticalseekbar:verticalseekbar:1.0.0'
        implementation 'com.github.duanhong169:checkerboarddrawable:1.0.2'
    
    
        /*FIREBASE*/
        implementation "com.google.firebase:firebase-core:17.0.1"
        implementation "com.google.firebase:firebase-storage:18.1.1"
        implementation 'com.google.firebase:firebase-database:18.0.1'
        implementation 'com.firebaseui:firebase-ui-database:5.0.0'
    
        /*HELPER*/
        implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.9'
        implementation 'org.apache.commons:commons-collections4:4.3'
        implementation 'com.github.nanchen2251:CompressHelper:1.0.5'
        implementation 'com.google.code.gson:gson:2.8.5'
        implementation(group: 'uz.shift', name: 'colorpicker', version: '0.5', ext: 'aar')
    
        /*CHANGING FONT*/
        implementation 'io.github.inflationx:viewpump:2.0.2'
        implementation 'io.github.inflationx:calligraphy3:3.1.1'
    }
    
    opened by Mouadabdelghafouraitali 7
  • Use GPUImageFilterGroup causes confusion in the background

    Use GPUImageFilterGroup causes confusion in the background

    When I use GPUImageFilterGroup, the background has a lot of clutter.

    The first time the set group does not have a problem,after the second time, the set group background is confused..

    I use ScaleType.CENTER_INSIDE

    GPUImageFilterGroup group = new GPUImageFilterGroup();
    group.addFilter(new GPUImageSaturationFilter(1.3f));
    group.addFilter(new GPUImageBrightnessFilter(0.2f));
    group.addFilter(new GPUImageContrastFilter(1.3f));
    group.addFilter(new GPUImageWhiteBalanceFilter(5000f,2f));
    surfaceView.setFilter(group);
    

    image

    opened by xiandanin 5
  • Image stretches and crops

    Image stretches and crops

    when i open either the gpuimage-sample,or my own project, smaller images just strech and crop wierdly, how to solve that?

    Trying CENTER_INSIDE scale type doesnt really work....

    1)Original image

    130411155624-lamborghini-dubai-police-4-horizontal-gallery 1

    2)Auto crop and zoomed image in GpuImageSample project

    screenshot_2013-06-28-10-28-09 1

    Thanks,

    Jeet

    opened by jeetdholakia 5
  • useDeprecatedNdk problem

    useDeprecatedNdk problem

    Hi,

    I get build error as:

    Error:Execution failed for task ':library:compileDebugNdk'.

    Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio. Please switch to a supported build system. Consider using CMake or ndk-build integration. For more information, go to: https://d.android.com/r/studio-ui/add-native-code.html#ndkCompile To get started, you can use the sample ndk-build script the Android plugin generated for you at: android-gpuimage-master/library/build/intermediates/ndk/debug/Android.mk Alternatively, you can use the experimental plugin: https://developer.android.com/r/tools/experimental-plugin.html To continue using the deprecated NDK compile for another 60 days, set android.deprecatedNdkCompileLease=1511898978137 in gradle.properties

    opened by oguzgu 4
  • Front Facing Camera Not Full screen

    Front Facing Camera Not Full screen

    jp.co.cyberagent.android.gpuimage.sample.activity.ActivityCamera

    Pls see the screen shot, the front camera is not full screen in some phones? Front cam renders in 1/4 of the screen and last frame of the back camera still in the view.

    screenshot_2016-09-21-15-00-23

    opened by deshan 4
  • Memory Leak Fix & onPictureSavedListener update

    Memory Leak Fix & onPictureSavedListener update

    I also encountered with this memory leak reported here and removed MediaScannerConnection from code and returns image file path instead of uri.

    If file requires to be displayed in gallery, below method can be used as well.

        public static void scanGallery(Activity activity, File modifiedFile) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    Intent mediaScanIntent = new Intent(
                    Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    Uri contentUri = Uri.fromFile(modifiedFile);
                    mediaScanIntent.setData(contentUri);
                    activity.sendBroadcast(mediaScanIntent);
                } else {
                    activity.sendBroadcast(new Intent(
                            Intent.ACTION_MEDIA_MOUNTED,
                            Uri.parse("file://" + Environment.getExternalStorageDirectory())));
                }
        }
    
    opened by yayaa 4
  • Could not find an filter effect for the GPUImageTiltShiftFilter

    Could not find an filter effect for the GPUImageTiltShiftFilter

    I want to find a tilt shift filter effect for android,but I can not see a filter call GPUImageTiltShiftFilter for android which looks like GPUImageTiltShiftFilter for iphone.I try to write it but have the black color.Can you help me? Thanks!

    opened by chunfun 4
  • Question about persisting changes when switching effects

    Question about persisting changes when switching effects

    Hi everyone.

    In your example app the bitmap resets to the original when you switch filters. I'm able to persist changes to the bitmap by first exporting changes to a new bitmap and then setting that new bitmap as the image for the GPUImageView.

    Bitmap newBitmap = mGPUImage.getBitmapWithFilterApplied();          
    mGPUImageView.setImage(newBitmap);
    

    This method takes too much time (almost 1 second to execute) and I assume there must be a more efficient way to do this, maybe by using OpenGL functions. Anybody got an idea how to do this? Any help appreciated.

    opened by primary0 4
  • java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap

    java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap

    0   
    java.lang.RuntimeException: An error occured while executing doInBackground()
    1   
    at android.os.AsyncTask$3.done(AsyncTask.java:299)
    2   
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
    3   
    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
    4   
    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
    5   
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    6   
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    7   
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    8   
    at java.lang.Thread.run(Thread.java:856)
    9   
    Caused by: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41e89060
    10  
    at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)
    11  
    at android.graphics.Canvas.drawBitmap(Canvas.java:1096)
    12  
    at android.graphics.Bitmap.createBitmap(Bitmap.java:617)
    13  
    at android.graphics.Bitmap.createBitmap(Bitmap.java:514)
    14  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.scaleBitmap(GPUImage.java:592)
    15  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.loadResizedImage(GPUImage.java:574)
    16  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.doInBackground(GPUImage.java:540)
    17  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.doInBackground(GPUImage.java:516)
    18  
    at android.os.AsyncTask$2.call(AsyncTask.java:287)
    19  
    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
    20  
    ... 4 more
    21  
    java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41e89060
    22  
    at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)
    23  
    at android.graphics.Canvas.drawBitmap(Canvas.java:1096)
    24  
    at android.graphics.Bitmap.createBitmap(Bitmap.java:617)
    25  
    at android.graphics.Bitmap.createBitmap(Bitmap.java:514)
    26  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.scaleBitmap(GPUImage.java:592)
    27  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.loadResizedImage(GPUImage.java:574)
    28  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.doInBackground(GPUImage.java:540)
    29  
    at jp.co.cyberagent.android.gpuimage.GPUImage$LoadImageTask.doInBackground(GPUImage.java:516)
    30  
    at android.os.AsyncTask$2.call(AsyncTask.java:287)
    31  
    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
    32  
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    33  
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    34  
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    35  
    at java.lang.Thread.run(Thread.java:856)
    

    From the SDK documentation http://developer.android.com/reference/android/graphics/Bitmap.html#createScaledBitmap(android.graphics.Bitmap, int, int, boolean):

    Creates a new bitmap, scaled from an existing bitmap, when possible. If the specified width and height are the same as the current width and height of the source btimap, the source bitmap is returned and now new bitmap is created.
    

    I think this error will be happen when the specified width and height are the same as the current width and height of the source bitmap.

    private Bitmap scaleBitmap(Bitmap bitmap) {
                // resize to desired dimensions
                int width = bitmap.getWidth();
                int height = bitmap.getHeight();
                int[] newSize = getScaleSize(width, height);
                Bitmap workBitmap = Bitmap.createScaledBitmap(bitmap, newSize[0], newSize[1], true);
                bitmap.recycle();
                bitmap = workBitmap;
                System.gc();
    
                if (mScaleType == ScaleType.CENTER_CROP) {
                    // Crop it
                    int diffWidth = newSize[0] - mOutputWidth;
                    int diffHeight = newSize[1] - mOutputHeight;
                    workBitmap = Bitmap.createBitmap(bitmap, diffWidth / 2, diffHeight / 2,
                            newSize[0] - diffWidth, newSize[1] - diffHeight);
                    bitmap.recycle();
                    bitmap = workBitmap;
                }
    
                return bitmap;
            }
    

    Should become this:

    private Bitmap scaleBitmap(Bitmap bitmap) {
                // resize to desired dimensions
                int width = bitmap.getWidth();
                int height = bitmap.getHeight();
                int[] newSize = getScaleSize(width, height);
                Bitmap workBitmap = Bitmap.createScaledBitmap(bitmap, newSize[0],
                        newSize[1], true);
                if (workBitmap != bitmap) {
                    bitmap.recycle();
                    bitmap = workBitmap;
                }
                System.gc();
    
                if (mScaleType == ScaleType.CENTER_CROP) {
                    // Crop it
                    int diffWidth = newSize[0] - mOutputWidth;
                    int diffHeight = newSize[1] - mOutputHeight;
                    workBitmap = Bitmap.createBitmap(bitmap, diffWidth / 2,
                            diffHeight / 2, newSize[0] - diffWidth, newSize[1]
                                    - diffHeight);
                    if (workBitmap != bitmap) {
                        bitmap.recycle();
                        bitmap = workBitmap;
                    }
                }
    
                return bitmap;
            }
    
    opened by rockerhieu 4
  • Build gpuimage library error, help me!

    Build gpuimage library error, help me!

    [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were encountered while building the effective model for jp.co.cyberagent.android.gpuimage:gpuimage-library:apklib:1.0.3 [WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin com.jayway.maven.plugins.android.generation2:android-maven-plugin @ line 56, column 21 [WARNING] [WARNING] Some problems were encountered while building the effective model for jp.co.cyberagent.android.gpuimage:gpuimage-sample:apk:1.0.3 [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-javadoc-plugin is missing. @ line 44, column 15 [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [WARNING] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Build Order: [INFO] [INFO] GPUImage for Android [INFO] GPUImage for Android Library [INFO] GPUImage Sample [INFO]
    [INFO] ------------------------------------------------------------------------ [INFO] Building GPUImage for Android 1.0.3 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ gpuimage-parent --- [INFO] [INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ gpuimage-parent --- [INFO] [INFO] --- maven-install-plugin:2.3.1:install (default-install) @ gpuimage-parent --- [INFO] Installing C:\Program Files\android-gpuimage-master\pom.xml to C:\Users\yang_shuai.CCWLAB.m2\repository\jp\co\cyberagent\android\gpuimage\gpuimage-parent\1.0.3\gpuimage-parent-1.0.3.pom [INFO]
    [INFO] ------------------------------------------------------------------------ [INFO] Building GPUImage for Android Library 1.0.3 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ gpuimage-library --- [INFO] Deleting C:\Program Files\android-gpuimage-master\library\target [INFO] [INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ gpuimage-library --- [INFO] [INFO] --- android-maven-plugin:3.2.0:generate-sources (default-generate-sources) @ gpuimage-library --- [INFO] ANDROID-904-002: Found aidl files: Count = 0 [INFO] ANDROID-904-002: Found aidl files: Count = 0 [INFO] C:\Program Files\adt-bundle-windows-x86\sdk\platform-tools\aapt.exe [package, -m, -J, C:\Program Files\android-gpuimage-master\library\target\generated-sources\r, -M, C:\Program Files\android-gpuimage-master\library\AndroidManifest.xml, -S, C:\Program Files\android-gpuimage-master\library\res, --auto-add-overlay, -I, C:\Program Files\adt-bundle-windows-x86\sdk\platforms\android-17\android.jar] [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ gpuimage-library --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory C:\Program Files\android-gpuimage-master\library\src\main\resources [INFO] skip non existing resourceDirectory C:\Program Files\android-gpuimage-master\library\target\generated-sources\extracted-dependencies\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ gpuimage-library --- [INFO] Compiling 20 source files to C:\Program Files\android-gpuimage-master\library\target\classes [INFO] [INFO] --- android-maven-plugin:3.2.0:ndk-build (default) @ gpuimage-library --- [INFO] C:\android-ndk-r8d\ndk-build [-C, C:\Program Files\android-gpuimage-master\library, gpuimage-library] make: Entering directory C:/Program Files/android-gpuimage-master/library' [INFO] C:/android-ndk-r8d/build/core/add-application.mk:128: Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml make: Nothing to be done forgpuimage-library'. make: Leaving directory `C:/Program Files/android-gpuimage-master/library' [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] GPUImage for Android .............................. SUCCESS [0.796s] [INFO] GPUImage for Android Library ...................... FAILURE [3.561s] [INFO] GPUImage Sample ................................... SKIPPED [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.357s [INFO] Finished at: Wed Dec 26 14:14:53 CST 2012 [INFO] Final Memory: 11M/21M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.2.0:ndk-build (default) on project gpuimage-library: ANDROID-040-001: Could not execute: Command = cmd.exe /X /C "C:\android-ndk-r8d\ndk-build -C "C:\Program Files\android-gpuimage-master\library" gpuimage-library", Result = 0 -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException [ERROR] [ERROR] After correcting the problems, you can resume the build with the command [ERROR] mvn -rf :gpuimage-library

    opened by dotyso 4
  • Missing argument checks in native code

    Missing argument checks in native code

    Bug Reporting

    Hi,

    I found that the implementations of YUVtoRBGA and YUVtoARBG in native code do not check the sizes of the input and output arrays. See here: https://github.com/cats-oss/android-gpuimage/blob/master/library/src/main/cpp/yuv-decoder.c#L28 https://github.com/cats-oss/android-gpuimage/blob/master/library/src/main/cpp/yuv-decoder.c#L87

    When a user provides incorrect width or height arguments, this can lead to an OOB array access, which may terminate the app with a SIGSEGV.

    I'm working on a fix and will open a pull request once finished.

    Steps to Reproduce

    Call GPUImageNativeLibrary.YUVtoARBG(yuv, width, height, output) with buffers that are smaller than width*height.

    Actual Results

    The app crashes with SIGSEGV

    Expected Results

    No crash

    OS details

    • Device: Redroid on Arm64
    • OS: Android 11
    opened by fab1ano 0
  • capture

    capture

    Future Task

    What is the motivation?

    What kind of solution can be considered?

    What do you want to discuss?

    Please add relevant labels


    Bug Reporting

    Steps to Reproduce

    Actual Results (include screenshots)

    Expected Results (include screenshots)

    URL

    OS details

    • Device:
    • OS:

    Please add relevant labels

    opened by happysir 0
  • GPUImageSharpenFilter is different compare to CISharpenLuminance from iOS

    GPUImageSharpenFilter is different compare to CISharpenLuminance from iOS

    Hello I am trying to achieve a filter effect similar to iOS SharpenLuminescence:

    extension SharpenLuminescence {
      func filter(_ image: CIImage) -> CIImage {
        image.applyingFilter(
          "CISharpenLuminance",
          parameters: [
            kCIInputSharpnessKey: sharpness,
            kCIInputRadiusKey: radius,
          ]
        )
      }
    }
    

    Using GPUImageSharpenFilter I am getting different results, any idea why and how to achieve a similar effect to iOS?

    The left side photo is from ios, radius 20 sharpen 2, the right site is an image with GPUImageSharpenFilter applied.

    Screenshot 2022-04-20 at 20 25 39
    opened by 8kt8 0
  • Why does GLTextureView's render thread  is not constructed on handler thread

    Why does GLTextureView's render thread is not constructed on handler thread

    Future Task

    Why does GLTextureView's render thread is not constructed on handler thread

    What is the motivation?

    I'm trying use GLTextureView to render some custom shader. There is some 'shaking' effect when it render continuously. It seem's that the sync signal between GLTextureView and Android's vsync and renderthread do not work properly.

    What kind of solution can be considered?

    Could this be solved by add choreographer to GLTextureView's render thread, and sync every frame by choreographer's callback? Why does GLTextureView use thread directly other than handler thread in the first time ?

    Please add relevant labels GLTextureView RenderThread HandlerThread

    opened by Neilcc 0
  • crash while switching camera on huawei mate30(android 10)

    crash while switching camera on huawei mate30(android 10)

    2022-01-06 16:18:24 32072-32072/? A/DEBUG: backtrace: 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #00 pc 00000000003e7294 /apex/com.android.runtime/lib64/libart.so (art::JNI::GetPrimitiveArrayCritical(_JNIEnv*, _jarray*, unsigned char*)+612) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #01 pc 0000000000000944 /data/app/com.sdfwq.videoeffects-Ykn3zRtlfNRtABX6QOBalA==/lib/arm64/libyuv-decoder.so (Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoRBGA+88) (BuildId: f7739d3957210f5c0d34829e8ddf12f08dfbdbd8) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #02 pc 000000000014d350 /apex/com.android.runtime/lib64/libart.so (art_quick_generic_jni_trampoline+144) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #03 pc 00000000001445b8 /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_static_stub+568) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #04 pc 00000000001531c4 /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+284) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #05 pc 00000000002eed0c /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #06 pc 00000000002e9fdc /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+912) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #07 pc 00000000005bdc94 /apex/com.android.runtime/lib64/libart.so (MterpInvokeStatic+368) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #08 pc 000000000013e994 /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_static+20) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #09 pc 000000000055ef2c anonymous:78f6438000 (㒘.Ⱍ.Ⱍ.Ⱍ.Ⱍ.䀔$Ⱍ.run+32) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #10 pc 00000000005bcbec /apex/com.android.runtime/lib64/libart.so (MterpInvokeInterface+1752) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #11 pc 000000000013ea14 /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_interface+20) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #12 pc 000000000055f31a anonymous:78f6438000 (㒘.Ⱍ.Ⱍ.Ⱍ.Ⱍ.䀔.ҵ+26) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #13 pc 00000000002bf948 /apex/com.android.runtime/lib64/libart.so (_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_6JValueEbb.llvm.4040658722762997890+240) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #14 pc 00000000005a62c8 /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1012) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #15 pc 000000000014d468 /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #16 pc 000000000200d0e0 /memfd:/jit-cache (deleted) (㒘.Ⱍ.Ⱍ.Ⱍ.Ⱍ.䀔.onDrawFrame+80) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #17 pc 0000000000144334 /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #18 pc 00000000001531a4 /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+252) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #19 pc 00000000002eed0c /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #20 pc 00000000002e9fdc /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+912) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #21 pc 00000000005bc888 /apex/com.android.runtime/lib64/libart.so (MterpInvokeInterface+884) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #22 pc 000000000013ea14 /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_interface+20) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #23 pc 00000000002fc55a /system/framework/framework.jar (android.opengl.GLSurfaceView$GLThread.guardedRun+1086) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #24 pc 00000000005bd788 /apex/com.android.runtime/lib64/libart.so (MterpInvokeDirect+1168) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #25 pc 000000000013e914 /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_direct+20) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #26 pc 00000000002fcb54 /system/framework/framework.jar (android.opengl.GLSurfaceView$GLThread.run+48) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #27 pc 00000000002bf948 /apex/com.android.runtime/lib64/libart.so (_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_6JValueEbb.llvm.4040658722762997890+240) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #28 pc 00000000005a62c8 /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1012) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #29 pc 000000000014d468 /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #30 pc 0000000000144334 /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #31 pc 00000000001531a4 /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+252) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #32 pc 00000000004c6d18 /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #33 pc 00000000004c7dac /apex/com.android.runtime/lib64/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue const*)+416) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #34 pc 0000000000507d7c /apex/com.android.runtime/lib64/libart.so (art::Thread::CreateCallback(void*)+1176) (BuildId: 5507e0405072e431616851bd75037326) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #35 pc 00000000000ce1b0 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) (BuildId: 95e03d8a9f101c0f1d3d9458688aa085) 2022-01-06 16:18:24 32072-32072/? A/DEBUG: #36 pc 0000000000070ba8 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 95e03d8a9f101c0f1d3d9458688aa085)

    opened by ivorita 0
Owner
CATS Open Source Softwares
OSS from CATS ( CyberAgent Advanced Technology Studio ).
CATS Open Source Softwares
A library for Android provides blurred drop shadows to ImageView similar to iOS image backdrop shadows

A library for Android provides blurred drop shadows to ImageView similar to iOS image backdrop shadows.Provides fast canvas draw as no renderscript needed .The similar shadow blurred effects can also be seen in iOS Music App.

Vivek Verma 163 Dec 31, 2022
DMIV aims to provide a flexible and customizable instrument for automated images moving on display. It provides scroll, gyroscope or time based moving. But you can create your own evaluator.

DexMovingImageView DMIV aims to provide a flexible and customizable instrument for automated images moving on display. It provides scroll, gyroscope o

Diego Grancini 310 Feb 7, 2022
Custom ImageView for android with polygon shape (Android)

PolygonImageView Create a custom ImageView with polygonal forms. Usage To use PolygonImageView, add the module into your project and start to build xm

Albert Grobas 531 Dec 25, 2022
Android library to generate image avatar from the first letter of a username. Letter avatar like Gmail Android best practice

AvatarImageGenerator Generate first letter avatar Image like gmail's contact avatar. It generates an drawable that can be be set to an ImageView. Inst

Korir Amos 61 Sep 25, 2022
Implementation of ImageView for Android that supports zooming, by various touch gestures.

PhotoView PhotoView aims to help produce an easily usable implementation of a zooming Android ImageView. [ Dependency Add this in your root build.grad

Baseflow 18.4k Dec 30, 2022
A circular ImageView for Android

CircleImageView A fast circular ImageView perfect for profile images. This is based on RoundedImageView from Vince Mi which itself is based on techniq

Henning Dodenhof 13.8k Mar 29, 2021
Android library (AAR). Highly configurable, easily extendable deep zoom view for displaying huge images without loss of detail. Perfect for photo galleries, maps, building plans etc.

Subsampling Scale Image View A custom image view for Android, designed for photo galleries and displaying huge images (e.g. maps and building plans) w

null 7.4k Jan 8, 2023
Android library project for cropping images

I guess people are just cropping out all the sadness An Android library project that provides a simple image cropping Activity, based on code from AOS

Jamie McDonald 4.5k Dec 29, 2022
Android widget for cropping and rotating an image.

Cropper The Cropper is an image cropping tool. It provides a way to set an image in XML and programmatically, and displays a resizable crop window on

Edmodo 2.9k Nov 14, 2022
Adds touch functionality to Android ImageView.

TouchImageView for Android Capabilities TouchImageView extends ImageView and supports all of ImageView’s functionality. In addition, TouchImageView ad

Michael Ortiz 2.4k Mar 28, 2021
Custom shaped android imageview components

Shape Image View Provides a set of custom shaped android imageview components, and a framework to define more shapes. Implements both shader and bitma

Siyamed SINIR 2.6k Mar 29, 2021
Android ImageView widget with zoom and pan capabilities

ImageViewTouch for Android ImageViewTouch is an android ImageView widget with zoom and pan capabilities. This is an implementation of the ImageView wi

Alessandro Crugnola 1.9k Jan 4, 2023
Android ImageView replacement which allows image loading from URLs or contact address book, with caching

Smart Image View for Android SmartImageView is a drop-in replacement for Android’s standard ImageView which additionally allows images to be loaded fr

James Smith 1.3k Dec 24, 2022
Implements pinch-zoom, rotate, pan as an ImageView for Android 2.1+

GestureImageView This is a simple Android View class which provides basic pinch and zoom capability for images. Can be used as a replacement for a sta

Jason 1.1k Nov 10, 2022
Custom view for circular images in Android while maintaining the best draw performance

CircularImageView Custom view for circular images in Android while maintaining the best draw performance Usage To make a circular ImageView, add this

Pkmmte Xeleon 1.2k Dec 28, 2022
Android ImageView that handles animated GIF images

GifImageView Android ImageView that handles Animated GIF images Usage In your build.gradle file: dependencies { compile 'com.felipecsl:gifimageview:

Felipe Lima 1.1k Mar 9, 2021
Android ImageView that supports different radii on each corner.

SelectableRoundedImageView Note that this project is no longer maintained. Android ImageView that supports different radii on each corner. It also sup

Joonho Kim 1.1k Mar 17, 2021
ImageView with a tag on android

SimpleTagImageView ImageView with a tag in android. So it's a ImageView. Demo ####Warning:When you set the round radius,the simpletagimageview scale t

null 944 Nov 10, 2022
Replacement for deprecated official Android crop image function

The MIT License (MIT) Copyright (c) 2012 Jan Muller Permission is hereby granted, free of charge, to any person obtaining a copy of this software and

Jan Muller 561 Nov 25, 2022