5

I'm trying to use some Native Code to create Gifs. I draw the images using paint, creating a few strokes, click save and the image drawn gets saved to a JPG format. when I click create Gif it takes all the images and starts creating a gif. This is when I get a Fatal Signal 11 and the app restarts.

I use native code so I have a backtrace of the crash:

I/DEBUG(95): backtrace:
I/DEBUG(95):     #00  pc 00002a04  /lib/libgifflen.so (NeuQuant::learn()+239)
I/DEBUG(95):     #01  pc 00002b9d  /lib/libgifflen.so (NeuQuant::quantise(DIB*, DIB*, int, int, int)+84)
I/DEBUG(95):     #02  pc 00002d41  lib/libgifflen.so (Java_com_stay_gif_GifEncoder_addFrame+208)
I/DEBUG(95):     #03  pc 0001deb0  /system/lib/libdvm.so (dvmPlatformInvoke+112)
I/DEBUG(95):     #04  pc 0004d103  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+394)
I/DEBUG(95):     #05  pc 0004f21f  /system/lib/libdvm.so (dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*)+174)
I/DEBUG(95):     #06  pc 000272e0  /system/lib/libdvm.so
I/DEBUG(95):     #07  pc 0002bbe8  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)
I/DEBUG(95):     #08  pc 0005fb37  /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374)
I/DEBUG(95):     #09  pc 000670e5  /system/lib/libdvm.so
I/DEBUG(95):     #10  pc 000272e0  /system/lib/libdvm.so
I/DEBUG(95):     #11  pc 0002bbe8  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)
I/DEBUG(95):     #12  pc 0005f871  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
I/DEBUG(95):     #13  pc 000496f3  /system/lib/libdvm.so
I/DEBUG(95):     #14  pc 00048581  /system/lib/libandroid_runtime.so
I/DEBUG(95):     #15  pc 00049637  /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+390)
I/DEBUG(95):     #16  pc 00000dcf  /system/bin/app_process

The code where it crashes:

void NeuQuant::learn()
{

    int i,j,b,g,r;
    int radius,rad,alpha,step,delta,samplepixels;
    //unsigned char *p;
    int *p;
    unsigned char *lim;

    alphadec = 30 + ((samplefac-1)/3);
    p = (int*)thepicture;
    lim = thepicture + lengthcount;
    samplepixels = lengthcount/samplefac;
    delta = samplepixels/ncycles;
    alpha = initalpha;
    radius = initradius;

    rad = radius >> radiusbiasshift;
    if (rad <= 1) rad = 0;
    for (i=0; i<rad; i++)
            radpower[i] = alpha*(((rad*rad - i*i)*radbias)/(rad*rad));

    //fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad);
    sprintf(s, "samplepixels = %d, rad = %d, a=%d, ad=%d, d=%d", samplepixels, rad, alpha, alphadec, delta);
    __android_log_write(ANDROID_LOG_VERBOSE, "gifflen",s);

    if ((lengthcount%prime1) != 0) step = prime1;
    else {
            if ((lengthcount%prime2) !=0) step = prime2;
            else {
                    if ((lengthcount%prime3) !=0) step = prime3;
                    else step = prime4;
            }
    }

    i = 0;
    while (i < samplepixels)
        {
    /*      b = p[0] << netbiasshift;
            g = p[1] << netbiasshift;
            r = p[2] << netbiasshift;*/
            b = (((*p)) & 0xff) << netbiasshift;
            g = (((*p) >> 8) & 0xff) << netbiasshift;
            r = (((*p) >> 16) & 0xff) << netbiasshift;
            j = contest(b, g, r);
            altersingle(alpha,j,b,g,r); //these crashes
            if (rad) alterneigh(rad,j,b,g,r);   // alter neighbours

            p += step;
            if (p >= (int *)lim) p -= lengthcount;

            i++;
            if (i%delta == 0)
            {
                alpha -= alpha / alphadec;
                radius -= radius / radiusdec;
                rad = radius >> radiusbiasshift;
                if (rad <= 1) rad = 0;
                for (j=0; j<rad; j++)
                    radpower[j] = alpha*(((rad*rad - j*j)*radbias)/(rad*rad));
            }
        }

        //sprintf(s, "final alpha = %f", ((float)alpha)/initalpha);
    //  __android_log_write(ANDROID_LOG_VERBOSE, "gifflen",s);
}

Thx to the Log I found out that the error happens in NeuQuant::learn(), did some debugs and it crashes on this exact line b = (((*p)) & 0xff) << netbiasshift;.

The Crash doesnt happen always, sometimes I get a gif and everything works, but sometimes it crashes at b = (((*p)) & 0xff) << netbiasshift;.

I did some more debuging and I found out that when it crashes on b = (((*p)) & 0xff) << netbiasshift; it doesnt crash when it enters the first time, it crashes like after the 30 check of b = (((*p)) & 0xff) << netbiasshift;.

Anyone know what might be the problem?

Rafael Skubisz
  • 460
  • 3
  • 9

1 Answers1

4

I changed:

if (p >= (int *)lim)
    p -= lengthcount;

to:

if (p >= (unsigned int *)lim)
    p = (unsigned int*)thepicture;

And it seems to work now.

Rafael Skubisz
  • 460
  • 3
  • 9
  • This approach is not correct. It enlarges size of output GIF on 30%. I find another good solution. I just copy body of method `learn()` from original [NeuQuant algorythm](http://members.ozemail.com.au/~dekker/NEUQUANT.C) and paste in gifflen `NeuQuant::learn()` – danik Sep 27 '13 at 10:04
  • I just did some tests with the code form you and code above. I dont see a difference in GIF size. The smallest GIF is around 1000 KB, the biggest around 2500KB in both situations. Tried to draw the same images for the tests so the size difference was max 10% higher/smaller. – Rafael Skubisz Nov 26 '13 at 15:19
  • You're my savior. THANKS! – Anton Shkurenko Nov 26 '15 at 12:56