MolotovCherry / kmagick

Kotlin ImageMagick bindings to the MagickWand API
MIT License
40 stars 5 forks source link

App crashes on invoking 'wand.getImagePixelColor(...)' #3

Closed RollingPanda1 closed 2 years ago

RollingPanda1 commented 2 years ago

I can import the package but when i start using its methods app just crashes.

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.1'
    }
}

android {
    compileSdkVersion 31
    buildToolsVersion "30.0.1"

    defaultConfig {
        minSdkVersion 23
        targetSdkVersion 31
        versionCode 1
        versionName "1.0"
    }
    lintOptions {
        abortOnError false
    }
    sourceSets {
        main {
                jniLibs.srcDirs = ['libs']
            }
        }
}

repositories {
    mavenCentral()
    jcenter()
    mavenLocal()

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    compile 'com.facebook.react:react-native:+'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    implementation 'com.orhanobut:hawk:2.0.1'

    implementation 'com.github.bumptech.glide:glide:4.13.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'

}
import com.cherryleafroad.kmagick.*

fun doTheMagick() {
    // close resources when finished
    Magick.initialize().use {
        val wand = MagickWand()

        val pw = PixelWand()
        pw.color = "#ff0000"
        wand.newImage(500, 500, pw)

        wand.getImagePixelColor(100, 100)?.let {
            //srgb(255,0,0)
            Log.d(TAG,it.color)
        }

        val dwand = DrawingWand()
        dwand.fontSize = 40.0
        dwand.font = "Times New Roman"

        val colorWand = PixelWand()
        colorWand.color = "black"
        dwand.fillColor = colorWand
        wand.annotateImage(dwand, 0.0,50.0, 0.0, "Some text")

        // get bytes of image, then read it back in
        val blob = wand.writeImageBlob("png")
        wand.readImageBlob(blob)

       // ALWAYS make sure to handle your exceptions! Something may always go wrong
        try {
            // this will obviously fail
            wand.readImage("oops!")
        } catch (e: MagickWandException) {
            // handle it here
            val exc = wand.getException()
            Lod.d(TAG,"Got a MagickWandException: ${e.message}")
            Log.d(TAG,"Extra exception details: ${exc.exceptionType}: ${exc.message}")
        }

        // But what if the library itself panics? (this is what we call a crash)
        // then a RuntimeException will be thrown instead
        // A RuntimeException can theoretically occur on ANY library function call
        // however the chances of that actually happening are very low
        // try {
            // pretend that the following fn exists and causes a panic, so throws a RuntimeException
            // wand.panic()
        // } catch (e: RuntimeException) {
            // Log.d(TAG,"Something bad happened: ${e.message}")
        // }

        wand.writeImage("D:/out.png")
    }
}

image

MolotovCherry commented 2 years ago

What's your error message? I need more details about what exactly happened.

If you can, can you give logcat of the error? I need to see the exception you program ended with and possibly the line number it failed at

RollingPanda1 commented 2 years ago

Ok I just checked each method one by one and found that wand.getImagePixelColor() causing the crash. The app just crash without errors or exceptions

            ...
            Log.d(TAG, "initialized...")
            val wand = MagickWand()

            val pw = PixelWand()
            pw.color = "#ff0000"
            wand.newImage(500, 500, pw)

            Log.d(TAG, "getting image pixel color...")
            wand.getImagePixelColor(100, 100)?.let {  // Culprit
                Log.d(TAG," got the pxl clrs ")
            }
           ...

Meanwhile this works

wand.getImageWidth()?.let {
       Log.d(TAG,"Width: ${it}")  // output is "Width: 500"
}
MolotovCherry commented 2 years ago

Most likely you're missing a required library. I must've forgotten to put this in the instructions.

You can add this line to your build.gradle:
implementation 'org.objenesis:objenesis:3.2'

As per your error, errors are always displayed if you check the logcat, regardless of crashing. It'll tell me exactly what the issue is when you provide it. (That is, after all, how I found out what the error above was)

(Your next error will probably come up on AnnotateImage because the font isn't available, You can catch that exception as normal and check it)

Thanks for your report. After you confirm it works, we can close this.

RollingPanda1 commented 2 years ago

Most likely you're missing a required library. I must've forgotten to put this in the instructions.

You can add this line to your build.gradle: implementation 'org.objenesis:objenesis:3.2'

As per your error, errors are always displayed if you check the logcat, regardless of crashing. It'll tell me exactly what the issue is when you provide it. (That is, after all, how I found out what the error above was)

(Your next error will probably come up on AnnotateImage because the font isn't available, You can catch that exception as normal and check it)

Thanks for your report. After you confirm it works, we can close this.

Thanks it solved.

RollingPanda1 commented 2 years ago

Most likely you're missing a required library. I must've forgotten to put this in the instructions.

You can add this line to your build.gradle: implementation 'org.objenesis:objenesis:3.2'

As per your error, errors are always displayed if you check the logcat, regardless of crashing. It'll tell me exactly what the issue is when you provide it. (That is, after all, how I found out what the error above was)

(Your next error will probably come up on AnnotateImage because the font isn't available, You can catch that exception as normal and check it)

Thanks for your report. After you confirm it works, we can close this.

Well I am not running it on Android Studio. Its CLI and VS Code only. Although I use one console for adb logcat and It did not show anything when app crashes. I read the AnnotateImage on #1 but iI was not sure about it's usage and I skipped this method as other useful methods are working.

MolotovCherry commented 2 years ago

Well I am not running it on Android Studio. Its CLI and VS Code only. Although I use one console for adb logcat and It did not show anything when app crashes. I read the AnnotateImage on #1 but iI was not sure about it's usage and I skipped this method as other useful methods are working.

I updated the README and also made a new example Android setup folder. Obviously you have yours setup properly, but there's a fix in there for getting the sources.jar to actually show properly (in case yours wasn't), so you can see the documentation.

Anyways, yeah, logcat will always show you the errors for your app, so you can check this if you need to know any issues. Sometimes you have to fish around for it as there's a lot of output.

And AnnotateImage on #1.. Yeah, that was just a regular ordinary exception due to improper usage (which you can see why by handling the exception and checking the message; details on the main page for how to do that).

For the most part, you can look at the regular C magickwand imagemagick documentation as this is the same (in case the doc on the methods isn't enough)

RollingPanda1 commented 2 years ago

Your work is effortless. You are doing great job. Appreciated.

Btw I tried to resize some static images and it worked like charm! But got weird output if input is gif image. Like incorrect colors and single frame image rather animating. Do i have to use specific methods to manipulate gif files ?

MolotovCherry commented 2 years ago

Your work is effortless. You are doing great job. Appreciated.

Btw I tried to resize some static images and it worked like charm! But got weird output if input is gif image. Do i have to use specific methods to manipulate gif files ?

I'm afraid that's imagemagick specific. However it works internally is not really up to me. But I don't think imagemagick requires any special handling for gif images.

What code did you use? Also, if you're having a problem, you may want to ask/file a bug report with imagemagick

RollingPanda1 commented 2 years ago
// getting image
wand.readImage(src) 

// resizing image
wand.resizeImage(512,512,FilterType.UndefinedFilter)  

// Saving image
wand.writeImage(dst)

input: giphy

Output: giphy_new

It is correctly resized but became static. ( It seems the last frame )

MolotovCherry commented 2 years ago

Gifs are able to save the difference between frames to save space. That's probably what's happening here. (Anyways, I'd recommend asking questions about image editing operations to imagemagick themselves; the API is basically the same, and the behavior is theirs)

RollingPanda1 commented 2 years ago

I did not create issue on ImageMagick as those are command lines and command line works fine for me when I used to resize the gifs and animated webp and conversion between gif and webp. MagickWand is low level so I did not read that in detail for now due to time issue.

MolotovCherry commented 2 years ago

I think There is no direct single method for resize the gifs.

Not 100% of the imagemagick API is covered. If there are some API methods you need, please make a feature request on the magick-rust repo, which is what I am using for the bindings. (If I hooked directly into C myself to implement it, I'd be bypassing the dependency and creating problems later on)

(You could also tell me, maybe if I have time I'll send them a PR containing the changes)

In your project what is wand ?

It is the C wand provided by imagemagick (through direct bindings)

is it the python binding of IM or any other ?

Direct bindings to C (we call the C functions directly at the low level)

I did not create issue on ImageMagick as those are command lines and command line works fine for me when I used to resize the gifs and animated webp and conversion between gif and webp.

Probably the command line is setting things up a certain way. If you can find out which API it's calling, that can be replicated here (provided the functions are exported. You may need to do a feature request to the repo I listed above to get them accessible)

MagickWand is low level so I did not read that in detail for now due to time issue.

Yes, it's much more recommended to read that, since I have no idea what the Python bindings may do to it. But ours is a direct binding to C, so if you read those docs, it will be the exact same behavior.