artoolkit5
artoolkit5 copied to clipboard
Android Camera Color Problem
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

Taken with ARMovie

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.
Comment by lya1234
Wednesday Apr 20, 2016 at 08:39 GMT
i try to run armovie too.. but it stop responding.
Comment by ThorstenBux
Friday Apr 22, 2016 at 02:41 GMT
@philip-lamb: The red channel is also missing in nftSimple and nftBook
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.
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.
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.