artoolkit5 icon indicating copy to clipboard operation
artoolkit5 copied to clipboard

Android Camera Color Problem

Open ThorstenBux opened this issue 7 years ago • 7 comments

Issue by felangga Thursday Sep 24, 2015 at 03:12 GMT Originally opened as https://github.com/artoolkit/artoolkit5/issues/11


I've tested the ARToolkit examples (ARMovie, ARSimple, etc) and found out the camera has a problem with color. You can see the problem in attachment image, the color seems to be green-ish. Tested on Nexus 5, Lolipop 5.1.1

Taken with default Android Camera 14653

Taken with ARMovie 14648

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux

Comment by ghost Tuesday Mar 08, 2016 at 03:49 GMT


I got the same issue too, can someone fix it?

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux

Comment by philip-lamb Tuesday Mar 08, 2016 at 03:51 GMT


Interesting. Looks like the red channel is not being converted correctly. We will try to reproduce.

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux

Comment by lya1234 Wednesday Apr 20, 2016 at 08:39 GMT


i try to run armovie too.. but it stop responding.

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux

Comment by ThorstenBux Friday Apr 22, 2016 at 02:41 GMT


@philip-lamb: The red channel is also missing in nftSimple and nftBook

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux

Comment by Aljaksandr Thursday Feb 09, 2017 at 09:28 GMT


I've investigated the problem. It seems that I understand what is the reason of the problem. During colorization of greayscale texture (lines 810-844 of code in /lib/SRC/Gl/gsub_es.c) adding additive texture contextSettings->texture1 has no effect. It seems that subtracting texture contextSettings->texture2 operates with grayscale texture contextSettings->texture0, because GL_PREVIOUS points to it. I don't know how to fix it because I don't know OpenGL programming.

My solution is slightly different.

At first, I've made HAVE_ARM_NEON undefined because I don't want to write program using assembler language ))

At second, I've rewritten arglCrCbToRGBA function:

unsigned char constrain_0_255(const int value)
{
	if (value < 0)	return 0;
	else if (value > 255)	return 255;
	else	return value;
}

static void arglCrCbToRGBA(uint8_t * __restrict destRGBAAdd, uint8_t * __restrict destRGBASubtract, uint8_t * __restrict srcCrCb, int numPixels)
{
    int i;
    float Cb, Cr;
    int R, G, B;
    ARUint8 *pCrCb, *pRGBAAdd, *pRGBASubtract;

    pCrCb = srcCrCb;
    pRGBAAdd = destRGBAAdd;
    pRGBASubtract = destRGBASubtract;

    for (i = 0; i < numPixels; i++) {
        Cr = (float)(*(pCrCb++) - 128);
        Cb = (float)(*(pCrCb++) - 128);
        
        R = (int)((             1.402f*Cr)/1.5);
        G = (int)((-0.344f*Cb - 0.714f*Cr)/1.5);
        B = (int)(( 1.772f*Cb)/1.5);
          
        *(pRGBAAdd++) = constrain_0_255(128 + R);
        *(pRGBASubtract++) = 0;
        
        *(pRGBAAdd++) = constrain_0_255(128 + G);
        *(pRGBASubtract++) = 0;
        
        *(pRGBAAdd++) = constrain_0_255(128 + B);
        *(pRGBASubtract++) = 0;

        *(pRGBAAdd++) = 0;
        *(pRGBASubtract++) = 0;
    }
}

At third, I changed the code in arglDispImageStateful function:

void arglDispImageStateful(ARGL_CONTEXT_SETTINGS_REF contextSettings)
{
    int        i;

    if (!contextSettings) return;
    if (!contextSettings->textureObjectsHaveBeenSetup) return;
    if (!contextSettings->textureGeometryHasBeenSetup) return;
    if (!contextSettings->textureDataReady) return;

    glStateCacheActiveTexture(GL_TEXTURE0);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);

    glStateCacheBindTexture2D(contextSettings->texture0);
    glStateCacheTexEnvMode(GL_REPLACE);
    glStateCacheEnableTex2D();

    glStateCacheClientActiveTexture(GL_TEXTURE0);
    glBindBuffer(GL_ARRAY_BUFFER, contextSettings->t2bo);
    glTexCoordPointer(2, GL_FLOAT, 0, NULL);
    glStateCacheEnableClientStateTexCoordArray();

    if (contextSettings->useTextureYCbCrBiPlanar) {
	glStateCacheActiveTexture(GL_TEXTURE1);

        glMatrixMode(GL_TEXTURE);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);

	glBindTexture(GL_TEXTURE_2D, contextSettings->texture1);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED);
	glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);

	glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
	glEnable(GL_TEXTURE_2D);

        glStateCacheClientActiveTexture(GL_TEXTURE1);
        glBindBuffer(GL_ARRAY_BUFFER, contextSettings->t2bo);
        glTexCoordPointer(2, GL_FLOAT, 0, NULL);
        
        glStateCacheEnableClientStateTexCoordArray();
    }

    glBindBuffer(GL_ARRAY_BUFFER, contextSettings->v2bo);
    glVertexPointer(2, GL_FLOAT, 0, NULL);
    glStateCacheEnableClientStateVertexArray();
    glStateCacheDisableClientStateNormalArray();

    if (contextSettings->disableDistortionCompensation) {
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    } else {
        for (i = 0; i < 20; i++) {
            glDrawArrays(GL_TRIANGLE_STRIP, i * 42, 42);
        }
    }

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    if (contextSettings->useTextureYCbCrBiPlanar) {
        // Turn multitexturing off before handing back control, as the caller is unlikely to expect it to be on.
        glStateCacheActiveTexture(GL_TEXTURE2);
        glStateCacheTexEnvMode(GL_MODULATE);
        glStateCacheDisableTex2D();
        glStateCacheActiveTexture(GL_TEXTURE1);
        glStateCacheTexEnvMode(GL_MODULATE);
        glStateCacheDisableTex2D();
        glStateCacheActiveTexture(GL_TEXTURE0);
        glStateCacheClientActiveTexture(GL_TEXTURE0);
    }
}

Because of GL_ADD_SIGNED combining mode OpenGL operates now only with two textures.

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux

Comment by SanjayAndroidDev Tuesday May 30, 2017 at 10:48 GMT


@Aljaksandr How to made HAVE_ARM_NEON undefined?. I changed both function in .c file. But can't able to undefined HAVE_ARM_NEON. In my phone camera issues still happening.

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux

Comment by Aljaksandr Wednesday May 31, 2017 at 13:56 GMT


The most simple way to do it (but not the best) is to write: #undef HAVE_ARM_NEON in the top of file.

ThorstenBux avatar Jan 28 '18 09:01 ThorstenBux