Weird bug in processing or linux?

For some time now I have been using Processing for linux on a Chromebook, with linux running in a virtual machine/container. I start a terminal and change directory to processing-3.5.3 and then ./processing and up pops the IDE and off I go. The problem is it is beta and just when I’m happy they update something and break something that I need. This time, I submitted to the latest update and all seemed fine until… I started up linux switched to processing directory and started the IDE and then chose to run an old sketch that put Red lines of lat and lon on a sphere. Now the lines of lat and lon are Blue. There is also a ControlP5 button that changed from Red to Blue.

I checked the code by using Find and searching for (0,0,255), that’s blue and it’s nowhere in the code. I figured I’d check some more recent sketches for weirdness and found some.

The second sketch displays an .obj of an airplane with Red livery scheme. Red has changed to Blue.

Any ideas?

So, I’ve been thinking about how this happened. The IDE uses java, maybe they got in that way while I was online playing with processing. Arduino IDE also uses java, maybe they got in while I was programming a board or using data from a board over serial. Maybe there is a vulnerability opened while using USB serial on linux chromebook. I don’t know the how of it.

All my processing programs that use the color Red(255,0,0) are affected. If I go in and change (255,0,0) to (0,0,255), it is now red. Isnt that cute? Someone has changed the definition of colors. I didn’t realize using processing or chromebook required some political affiliation.

1 Like

do you have a simple piece of code that demonstrate the issue?

May be a little endian / big endian challenge? (although the alpha channel would be inverted too)

Hit F12 to open the browser’s console and paste the test below there:
new Uint8Array(Uint32Array.of(0x12345678).buffer)[0] === 0x78

It must return true on the device it’s run if it’s little-endian.

Which it is so for almost all devices in the market.

For further details about endianness go to this forum thread:

I can’t test anything or post an example right now. I will revisit after work…

Here’s a screenshot of a reduced code version illustrating how stroke(255,0,0) produces blue instead of red.

Here is the reduced code:

PGraphics texture;
PImage texmap;
float[] cx, cz, sphereX, sphereY, sphereZ;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5f;
float globeRadius = 597; //597;
float pushBack = -100;
int sDetail = 64; //128;  // Sphere detail setting

int SINCOS_LENGTH = PApplet.parseInt(360.0f / SINCOS_PRECISION);

public void setup() {
  
     hint(DISABLE_DEPTH_TEST);
      size(1275, 750, P3D);
      blendMode(SCREEN); 
      texmap = loadImage("alphatest.png");
      texture = createGraphics(texmap.width, texmap.height);                   
      initStars();
      addDiagonalLine();
  
}

public void initStars() {
  texture.beginDraw();
  texture.image(texmap,0,0);
  texture.endDraw();
}


public void addDiagonalLine() {


   texture.beginDraw(); 
   texture.stroke(255,0,0);
   texture.strokeWeight(2);
   texture.line(0,0,0, texture.height);
   texture.line(texture.width/12, 0,texture.width/12,texture.height);
   texture.line(texture.width/12*2, 0,texture.width/12*2,texture.height);
   texture.line(texture.width/12*3, 0,texture.width/12*3,texture.height);     
   texture.line(texture.width/12*4, 0,texture.width/12*4,texture.height);
   texture.line(texture.width/12*5, 0,texture.width/12*5,texture.height);
   texture.line(texture.width/12*6, 0,texture.width/12*6,texture.height);
   texture.line(texture.width/12*7, 0,texture.width/12*7,texture.height);
   texture.line(texture.width/12*8, 0,texture.width/12*8,texture.height);
   texture.line(texture.width/12*9, 0,texture.width/12*9,texture.height);
   texture.line(texture.width/12*10, 0,texture.width/12*10,texture.height);
   texture.line(texture.width/12*11, 0,texture.width/12*11,texture.height);
/////  texture.line(texture.width/12 * 11 -texture.width/12/3, 0,texture.width/12 * 11 -texture.width/12/3,texture.height);
 

  texture.line(texture.width/12 -texture.width/12/2, 0,texture.width/12 -texture.width/12/2,texture.height);
  texture.line(texture.width/12+texture.width/12/2, 0,texture.width/12+texture.width/12/2,texture.height);
  texture.line(texture.width/12/2+texture.width/12/2, 0,texture.width/12/2+texture.width/12/2,texture.height);
  texture.line(texture.width/12 * 2+texture.width/12/2, 0,texture.width/12 * 2+texture.width/12/2,texture.height);
 
  texture.line((texture.width/12 * 3)+texture.width/12/2, 0,(texture.width/12 * 3)+texture.width/12/2,texture.height);
  texture.line((texture.width/12 * 4)+texture.width/12/2, 0,(texture.width/12 * 4)+texture.width/12/2,texture.height);
  texture.line((texture.width/12 * 5)+texture.width/12/2, 0,(texture.width/12 * 5)+texture.width/12/2,texture.height);
  texture.line((texture.width/12 * 6)+texture.width/12/2, 0,(texture.width/12 * 6)+texture.width/12/2,texture.height);
  texture.line((texture.width/12 * 7)+texture.width/12/2, 0,(texture.width/12 * 7)+texture.width/12/2,texture.height);
  texture.line((texture.width/12 * 8)+texture.width/12/2, 0,(texture.width/12 * 8)+texture.width/12/2,texture.height);//////////////
  texture.line((texture.width/12 * 9)+texture.width/12/2, 0,(texture.width/12 * 9)+texture.width/12/2,texture.height);
  texture.line((texture.width/12 * 10)+texture.width/12/2, 0,(texture.width/12 * 10)+texture.width/12/2,texture.height);
  texture.line((texture.width/12 * 11)+texture.width/12/2, 0,(texture.width/12 * 11)+texture.width/12/2,texture.height);
  
//latitude lines
//texture
  texture.stroke(255,255,255);
  texture.line(0, texture.height/2,texture.width,texture.height/2); // +15 degrees
  texture.stroke(255,0,0);
  texture.line(0, texture.height/2/3,texture.width,texture.height/2/3); // +60 degrees
  texture.line(0, texture.height/2/3 * 2,texture.width,texture.height/2/3 * 2); // +30 degrees
  texture.line(0, texture.height/2/6,texture.width,texture.height/2/6 ); // +75 degrees
  texture.line(0, texture.height/2/3 + texture.height/2/6,texture.width,texture.height/2/3 + texture.height/2/6); // +45 degrees
  //   texture.stroke(255,255,255);
  texture.line(0, texture.height/2/3 * 2 + texture.height/2/6 ,texture.width,texture.height/2/3 * 2 + texture.height/2/6); // equator 0 degrees
  //   texture.stroke(255,255,255);
  texture.line(0, texture.height/2 + texture.height/2/3/2 ,texture.width,texture.height/2 + texture.height/2/3/2); // -15 degrees
   //   texture.stroke(255,255,255);
  //  texture.line(0, texture.height/2 -texture.height/2/3 ,texture.width,texture.height/2 -texture.height/2/3);  //redundant
  //   texture.stroke(255,255,255);
  texture.line(0, texture.height - texture.height/2/3 * 2,texture.width,texture.height -texture.height/2/3 * 2); // -30 degrees
  texture.line(0, texture.height -texture.height/2/3,texture.width,texture.height -texture.height/2/3); // -60 degrees
  texture.line(0, texture.height - texture.height/2/3 * 2 + texture.height/2/6,texture.width,texture.height -texture.height/2/3 * 2 + texture.height/2/6); // -45 degrees
  texture.line(0, texture.height -texture.height/2/3 + texture.height/2/6,texture.width,texture.height -texture.height/2/3 + texture.height/2/6); // -75 degrees
  texture.endDraw();
   
}

public void renderGlobe() {

  pushMatrix();
  translate(width/2, height/2, pushBack);
  pushMatrix();
  noFill();
  stroke(255,200);
  strokeWeight(2);
  smooth();
  popMatrix();
  lights();
  pushMatrix();
  rotateX(radians(90));
  fill(200);
  noStroke();
  textureMode(IMAGE);
  // texturedSphere(globeRadius, texture);
  texturedSphere(globeRadius, texture);
  popMatrix();
  popMatrix();

  }
  
  
    
public void initializeSphere(int res)
{
  sinLUT = new float[SINCOS_LENGTH];
  cosLUT = new float[SINCOS_LENGTH];

  for (int i = 0; i < SINCOS_LENGTH; i++) {
    sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
    cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
  }

  float delta = (float)SINCOS_LENGTH/res;
  float[] cx = new float[res];
  float[] cz = new float[res];

  // Calc unit circle in XZ plane
  for (int i = 0; i < res; i++) {
    cx[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
    cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
  }

  // Computing vertexlist vertexlist starts at south pole
  int vertCount = res * (res-1) + 2;
  int currVert = 0;

  // Re-init arrays to store vertices
  sphereX = new float[vertCount];
  sphereY = new float[vertCount];
  sphereZ = new float[vertCount];
  float angle_step = (SINCOS_LENGTH*0.5f)/res;
  float angle = angle_step;

  // Step along Y axis
  for (int i = 1; i < res; i++) {
    float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
    float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
    for (int j = 0; j < res; j++) {
      sphereX[currVert] = cx[j] * curradius;
      sphereY[currVert] = currY;
      sphereZ[currVert++] = cz[j] * curradius;
    }
    angle += angle_step;
  }
  sDetail = res;
}

// Generic routine to draw textured sphere
public void texturedSphere(float r, PGraphics t) {
  int v1,v11,v2;
  r = (r + 240 ) * 0.33f;
  beginShape(TRIANGLE_STRIP);
  texture(t);
  float iu=(float)(t.width-1)/(sDetail);
  float iv=(float)(t.height-1)/(sDetail);
  float u=0,v=iv;
  for (int i = 0; i < sDetail; i++) {
    vertex(0, -r, 0,u,0);
    vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
    u+=iu;
  }
  vertex(0, -r, 0,u,0);
  vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
  endShape();

  // Middle rings
  int voff = 0;
  for(int i = 2; i < sDetail; i++) {
    v1=v11=voff;
    voff += sDetail;
    v2=voff;
    u=0;
    beginShape(TRIANGLE_STRIP);
    texture(t);
    for (int j = 0; j < sDetail; j++) {
      vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
      vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
      u+=iu;
    }

    // Close each ring
    v1=v11;
    v2=voff;
    vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
    vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
    endShape();
    v+=iv;
  }
  u=0;

  // Add the northern cap
  beginShape(TRIANGLE_STRIP);
  texture(t);
  for (int i = 0; i < sDetail; i++) {
    v2 = voff + i;
    vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
    vertex(0, r, 0,u,v+iv);
    u+=iu;
  }
  vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
  endShape();

}

public void draw() {
  background(0);
  initStars();
  addDiagonalLine();
  initializeSphere(sDetail);
  renderGlobe();
      
}

Here is the blank image “alphatest.png” that should go in a directory called data.

What’s the purpose of this? Have you tried without?..

the doc states

Blends the pixels in the display window according to a defined mode. There is a choice of the following modes to blend the source pixels (A) with the ones of pixels already in the display window (B). Each pixel’s final color is the result of applying one of the blend modes with each channel of (A) and (B) independently. The red channel is compared with red, green with green, and blue with blue.

SCREEN - opposite multiply, uses inverse values of the colors.

You may try out this workaround below: :hammer_and_wrench:

import java.nio.ByteOrder;
static final ByteOrder ENDIANNESS = ByteOrder.nativeOrder();

{
  println(ENDIANNESS);
}

static final color c(final color c) {
  return ENDIANNESS == ByteOrder.LITTLE_ENDIAN? c : Integer.reverseBytes(c);
}

Just replace statements like texture.stroke(255, 0, 0); w/ this model:
texture.stroke(c(color(255, 0, 0)));

Another example: stroke(255, 200); - - > stroke(c(color(255, 200)));

If your issue is about endianness the trick above should hopefully work. :crossed_fingers:

I’m pretty much convinced this is actually because of blendMode()

Well, blendMode() doesn’t make red to become blue color in my laptop here. :man_shrugging:

Anyways, I’ve already given 2 ways to check endianness. 1 in JS and the other in Java. :smiley_cat:

Yes thanks for the endianness thingy

I’m on my mobile so could not check but have you tried with OP’s alphatest.png background image. Overlay on white

Yes I have dragged it to Processing’s IDE and could run it. :relieved:

Ok, I appreciate GoToLoop’s suggestions and have some time to test…soon.

As for why blendMode()? I found that if I used that, then I could make an image transparent when overlayed on another. Actually, both images become transparent. The larger code this originated from has two spheres very close in size and one image is of all the stars. The transparent effect works well for that.

Here’s the Endianness.

OK - my bad, it appears blendMode() is not the culprit at least on my Mac

I tried with your exact same code and your image stored in the data sub-directory of the sketch and I get this:

so red is actually red…

Note that I get the exact same image without the blendMode() though

this is weird. Have you tried out without it?

Could you also check outside your VM; that is, if your Chromebook itself is also little-endian?

Open a browser and run this statement below which must evaluate as true for little-endian:

is your Chromebook Intel based or ARM based ?

I opened a browser window and couldn’t figure out how to run the code, so I poked around and found developer tools(I aint, but I seen it done once :wink: and how about that, there is console with the little >

I get “true” for little-endian.

dmesg reports that I have an intel processor.

As to why blendMode() doesn’t seem to make any difference, you will need to add another sphere inside the other by adjusting the size by 1 or 2 and put an image on it just like is done for alphatest.png . Both images probably need to be the same dimensions. I seem to remember getting screwy results until I used equal image sizes. You will also need to add some code to rotateX, rotateY with the mouse if you want to see different views, etc. The code I posted above is still rather large when it is best to post minimal code to illustrate a problem.

I’m using that trick, but I actually have to use

texture.stroke(c(color(0,0,255)));

to produce red. Your code tests for LITTLE_ENDIAN and then reverses, if I am reading it correctly.

Yes! It should reverse only for LITTLE_ENDIAN: :+1:

But for some mysterious reasons your system is behaving as BIG_ENDIAN for Processing’s color! :astonished: