What does "Error on int" mean?

''Syntax error on token “int”, invalid ClassType
‘’
I have a static class C3 and I’m trying to create a color method in it. Here’s the code,

static class C3 {
  int r, g, b;
  /*
  public C3(color c){
    r = c;
    g = c;
    b = c;
  }
  */
  public C3(int r, int g, int b){
    this.r = r;
    this.g = g;
    this.b = b;
  }

  public C3 add(C3 o){
    return new C3(r + o.r, g + o.g, b + o.b);
  }

  public int clamp(int c){
    return Math.max(0, Math.min(255, c));
  }

  public int diff(C3 o){
    int Rdiff = o.r - r;
    int Gdiff = o.g - g;
    int Bdiff = o.b - b;
    int distanceSquared = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff;
    return distanceSquared;
  }

  public C3 mul(double d){
    return new C3((int) (d * r), (int) (d * g), (int) (d * b));
  }

  public C3 sub(C3 o){
    return new C3(r - o.r, g - o.g, b - o.b);
  }

  public color toColor(){
    return new color(clamp(r), clamp(g), clamp(b));
  }

  public int toRGB(){
    return toColor().getRGB();
  }
}

private static C3 findClosestPaletteColor(C3 c, C3[] palette){
  C3 closest = palette[0];

  for (C3 n : palette) {
    if (n.diff(c) < closest.diff(c)) {
      closest = n;
    }
  }

  return closest;
}

The error is in the toColor method.

In Processing, keyword color is alias to Java’s keyword int:

Keywords aren’t classes in Java; and therefore we can’t use operator new on them:

Besides color being a keyword, it’s also a function in Processing:

  public color toColor(){
    return color(clamp(r), clamp(g), clamp(b));
  }
2 Likes

But I put the new there as I cannot make a static reference to the non-static method. Is there any way to implement this?

I didn’t pay attention you had a static class: :see_no_evil:

You can simply get rid of keyword static or request a PApplet parameter from your toColor() method:

  public color toColor(final PApplet p) {
    return p.color(clamp(r), clamp(g), clamp(b));
  }
2 Likes

My previous answer doesn’t work! At least on PDE v3.5.4.

Due to the dual-nature of color, being both a keyword & a method, I can’t invoke it using the dot . operator: p.color(r, g, b);

Maybe on Processing 4 they’ve fixed that; and that’s why you’ve marked my post as the “solution”. :smiley:

Anyways, I’ve crafted a “hack” to directly access method color() by extending class PGraphics and creating a method getColor(), which then invokes color():

static final class PGraph extends PGraphics {
  PGraph() {
    checkSettings();
  }

  color getColor(color r, color g, color b) {
    return color(r, g, b);
  }
}

After that, I’ve refactored your class C3 to rely on subclass PGraph:

static class C3 {
  static final PGraph pg = new PGraph();

  color r, g, b;

  C3(color x, color y, color z) {
    r = x;
    g = y;
    b = z;
  }

  C3 add(final C3 c) {
    return new C3(r + c.r, g + c.g, b + c.b);
  }

  C3 sub(final C3 c) {
    return new C3(r - c.r, g - c.g, b - c.b);
  }

  C3 mul(final int d) {
    return new C3(d * r, d * g, d * b);
  }

  C3 mul(final float d) {
    return new C3((int) (d * r), (int) (d * g), (int) (d * b));
  }

  C3 clamp() {
    r = constrain(r, 0, 255);
    g = constrain(g, 0, 255);
    b = constrain(b, 0, 255);

    return this;
  }

  color toColor() {
    return clamp().pg.getColor(r, g, b);
  }

  int diff(final C3 c) {
    final color
      rDiff = c.r - r, 
      gDiff = c.g - g, 
      bDiff = c.b - b;

    return rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
  }

  static final C3 findClosestPaletteColor(final C3 c, final C3... palette) {
    C3 closest = null;
    int dif = MIN_INT;

    for (final C3 n : palette) if (n.diff(c) < dif) dif = (closest = n).diff(c);

    return closest;
  }

  String toString() {
    return "[ " + r + ", " + g + ", " + b + " ]";
  }
}

I just removed the static keyword. I’m not really a programmer so I do not really understand what they mean. I was trying to make some image processing algorithms. They work now though, and I guess that would do. I’d try implementing your solution though.

Keyword static is for declaring shared members of a class which can be accessed w/o instantiating their class:

I believe you did so b/c you wanted your helper method findClosestPaletteColor() not to belong to a particular instance of C3.

If you prefer, you can create a separate static class only for static members.

Then create a non-static subclass which extends that static class:

static final class PGraph extends PGraphics {
  PGraph() {
    checkSettings();
  }

  color getColor(color r, color g, color b) {
    return color(r, g, b);
  }
}

static abstract class C3Base {
  static final PGraph pg = new PGraph();

  static final C3 findClosestPaletteColor(final C3 c, final C3... palette) {
    C3 closest = null;
    int dif = MAX_INT;

    for (final C3 n : palette) if (n.diff(c) < dif) dif = (closest = n).diff(c);

    return closest;
  }
}

class C3 extends C3Base {
  color r, g, b;

  C3(color x, color y, color z) {
    r = x;
    g = y;
    b = z;
  }

  C3 add(final C3 c) {
    return new C3(r + c.r, g + c.g, b + c.b);
  }

  C3 sub(final C3 c) {
    return new C3(r - c.r, g - c.g, b - c.b);
  }

  C3 mul(final int d) {
    return new C3(d * r, d * g, d * b);
  }

  C3 mul(final float d) {
    return new C3((int) (d * r), (int) (d * g), (int) (d * b));
  }

  C3 clamp() {
    r = constrain(r, 0, 255);
    g = constrain(g, 0, 255);
    b = constrain(b, 0, 255);

    return this;
  }

  color toColor() {
    return clamp().pg.getColor(r, g, b);
  }

  int diff(final C3 c) {
    final color
      rDiff = c.r - r, 
      gDiff = c.g - g, 
      bDiff = c.b - b;

    return rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
  }

  String toString() {
    return "[ " + r + ", " + g + ", " + b + " ]";
  }
}

Now this split class C3 extends C3Base is equivalent to previous unified static class C3.

Edit: Added keyword abstract to static class C3 so folks won’t inadvertently instantiate it instead of C3. :wink:

Edit2: wrong MIN_MAX to correct MAX_INT for variable dif!

1 Like

Thanks. It does work. I made findClosestPaletteColor a C3 method since there’s not point to it not being one. What’s left is making a PImage inheritance for my other class.

Almost any static method can be converted to an instance 1.
It’s a matter of how we prefer to organize the logic of our code.

Your method findClosestPaletteColor() is about iterating all C3 instances; and therefore it doesn’t represent a single C3 instance.

That’s why it fits as a static method. Even though we can just leave it as non-static.

As an instance method findClosestPaletteColor(), you’d need to invoke it as something weird like this:
palette[0].findClosestPaletteColor(palette[5], palette);

While as static it makes more sense:
C3.findClosestPaletteColor(palette[5], palette);

I’ve already left for you the “trick” example post about creating a parent class dedicated for static members, where your regular class w/ instance members can extend from.

Or you can just have a PImage instance field and request it from your class’ constructor.

Here’s the new class:

// These methods are faster to calculate. Explanations are on the Processing website

int r(color c){
  return c >> 16 & 0xFF;
}  

int g(color c){
  return c >> 8 & 0xFF;
}  

int b(color c){
  return c & 0xFF;
}  

static final class PGraph extends PGraphics {
  PGraph() {
    checkSettings();
  }

  color getColor(color r, color g, color b) {
    return color(r, g, b);
  }
}

static abstract class C3Base {
  static final PGraph pg = new PGraph();
}

class C3 extends C3Base {
  color r, g, b;

  C3(color c) {
    r = r(c);
    g = g(c);
    b = b(c);
  }
  
  C3(int r, int g, int b) {
    this.r = r;
    this.g = g;
    this.b = b;
  }

  C3 add(final C3 c) {
    return new C3(r + c.r, g + c.g, b + c.b);
  }

  C3 sub(final C3 c) {
    return new C3(r - c.r, g - c.g, b - c.b);
  }

  C3 mul(final int d) {
    return new C3(d * r, d * g, d * b);
  }

  C3 mul(final float d) {
    return new C3((int) (d * r), (int) (d * g), (int) (d * b));
  }

  C3 clamp() {
    r = constrain(r, 0, 255);
    g = constrain(g, 0, 255);
    b = constrain(b, 0, 255);

    return this;
  }

  color toColor() {
    return clamp().pg.getColor(r, g, b);
  }

  int diff(final C3 c) {
    final color
      rDiff = c.r - r, 
      gDiff = c.g - g, 
      bDiff = c.b - b;

    return rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
  }

  String toString() {
    return "[ " + r + ", " + g + ", " + b + " ]";
  }
  
  C3 findClosestPaletteColor(C3[] palette) {
    C3 closest = palette[0];
    C3 c = new C3(r, g, b);

    for (C3 n : palette) {
      if (n.diff(c) < closest.diff(c)) {
        closest = n;
      }
    }

    return closest;
  }
}

I am trying to add some methods to the PImage class. One way I can try is extending the class, currently the only method I know of. There’s some dithering methods, and a couple of filters.
Do you have any recommendations?

Now I understand why you wanted findClosestPaletteColor() to be a regular instance method: You’ve got rid of its 1st parameter!

Instead the previous parameter became a clone of the current C3 instance.

Just so you know, you can keep both static & non-static versions for findClosestPaletteColor().

And those new r(), g() & b() helper functions can be converted to static inside C3Base:

static abstract class C3Base {
  static final color r(final color c) {
    return c >> 020 & 0xff;
  }

  static final color g(final color c) {
    return c >> 010 & 0xff;
  }

  static final color b(final color c) {
    return c & 0xff;
  }

  static final C3 findClosestPaletteColor(final C3 c, final C3[] palette) {
    C3 closest = null;
    int dif = MAX_INT;

    for (final C3 n : palette) if (n.diff(c) < dif) dif = (closest = n).diff(c);

    return closest;
  }
}

Notice now that I’ve got rid of class PGraph & its corresponding static pg field in C3Base.

In its place I’m using this formula: b | g << 010 | r << 020 | PImage.ALPHA_MASK.

Here’s latest version for class C3 w/ even more cool features: :mage:

class C3 extends C3Base implements Comparable<C3>, Cloneable {
  color r, g, b;

  C3(final color c) {
    r = r(c);
    g = g(c);
    b = b(c);
  }

  C3(final color r, final color g, final color b) {
    set(r, g, b);
  }

  C3 set(final color x, final color y, final color z) {
    r = x;
    g = y;
    b = z;

    return clamp();
  }

  C3 add(final C3 c) {
    return new C3(r + c.r, g + c.g, b + c.b);
  }

  C3 sub(final C3 c) {
    return new C3(r - c.r, g - c.g, b - c.b);
  }

  C3 mul(final int d) {
    return new C3(d * r, d * g, d * b);
  }

  C3 mul(final float d) {
    return new C3((int) (d * r), (int) (d * g), (int) (d * b));
  }

  int diff(final C3 c) {
    final color
      rDiff = c.r - r, 
      gDiff = c.g - g, 
      bDiff = c.b - b;

    return rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
  }

  final C3 findClosestPaletteColor(final C3... palette) {
    return findClosestPaletteColor(this, palette);
  }

  C3 clone() {
    try {
      return (C3) super.clone();
    }
    catch (final CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

  C3 clamp() {
    r = constrain(r, 0, 255);
    g = constrain(g, 0, 255);
    b = constrain(b, 0, 255);

    return this;
  }

  color toColor() {
    return clamp().hashCode();
  }

  int hashCode() {
    return b | g << 010 | r << 020 | PImage.ALPHA_MASK;
  }

  boolean equals(final Object o) {
    return o instanceof C3? o.hashCode() == hashCode() : false;
  }

  int compareTo(final C3 c) {
    return
      (hashCode() & ~PImage.ALPHA_MASK) -
      (c.hashCode() & ~PImage.ALPHA_MASK);
  }

  String toString() {
    return '#' + hex(hashCode(), 6) + ": [ " + r + ", " + g + ", " + b + " ]";
  }
}

Edit 1: changed: return C3.findClosestPaletteColor(clone(), palette);
to just: return C3.findClosestPaletteColor(this, palette);

No need to use clone() for this operation, given neither passed object arguments are mutated in anyway inside static method findClosestPaletteColor().


Edit 2: Created a set() method and changed 2nd constructor to use that:

  C3(final color r, final color g, final color b) {
    set(r, g, b);
  }

  C3 set(final color x, final color y, final color z) {
    r = x;
    g = y;
    b = z;

    return clamp();
  }

Edit 3: No need to prefix w/ C3 at return C3.findClosestPaletteColor(this, palette);:
return findClosestPaletteColor(this, palette);