Wired Pixel Thing on Android Mode

I was writing an android watch face but when I run it, this happened.

FATAL EXCEPTION: main
Process: processing.test.star, PID: 27171
java.lang.RuntimeException: The pixels array is not available in this renderer withouth a backing bitmap
at processing.a2d.PGraphicsAndroid2D.loadPixels(PGraphicsAndroid2D.java:2006)
at processing.core.PImage.filter(PImage.java:830)
at processing.core.PApplet.filter(PApplet.java:12494)
at processing.test.star.STAR.draw(STAR.java:50)
at processing.core.PApplet.handleDraw(PApplet.java:1852)
at processing.android.PWatchFaceCanvas$CanvasEngine.onDraw(PWatchFaceCanvas.java:255)
at android.support.wearable.watchface.CanvasWatchFaceService$Engine.draw(CanvasWatchFaceService.java:169)
at android.support.wearable.watchface.CanvasWatchFaceService$Engine.access$200(CanvasWatchFaceService.java:39)
at android.support.wearable.watchface.CanvasWatchFaceService$Engine$1.doFrame(CanvasWatchFaceService.java:56)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:909)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:655)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

I’m sure that’s because the “filter(BLUR, 6);” thing that went wrong in my code.
And I even wrote my own blur function, but neither of them work, they both return the same error.

So I was wondering how to fix this also why this is happening.

Thanks!

Hi @RyanUnicoen
What renderer are you using?
If you leave out the blur filter, does it still happen?
Without seeing the code it’s difficult to test.
Does the code run well on a phone?
Are you using APDE?
Have you written pg.beginDraw() before loadPixels();
Are you calling updatePixels() in a function on a PGraphics element that hasn’t been drawn yet?

Thanks for the reply, here’s the code that I think is important and some answer.

What renderer are you using?

not quite sure but I guess P2D?

If you leave out the blur filter, does it still happen?

nope.

Does the code run well on a phone?

haven’t tried, but it works well on java mode though.

Are you using APDE?

No, I’m on windows.

Have you written pg.beginDraw() before loadPixels();
Are you calling updatePixels() in a function on a PGraphics element that hasn’t been drawn yet?

I’m not using a PGraphics though.

And here’s the code:

final color bgc = color(0);
final color mc = color(255);
final float scs = 18;
final float bcs = 23;
final float lg = 20;
final float hgr = 56;
final float blt = 8;
final float slt = 6;
LineWorker lw;

void setup(){
size(400, 400);
ellipseMode(CENTER);
lw = new LineWorker();
}

void draw(){
background(bgc);

lw.connectLines();
lw.drawAllLines();
filter(BLUR, 6);
lw.drawAllLines();
}

Thanks!

Where is the LineWorker class?

The rest of the code is not that important I think and also very long and quite messy, but still:

final color bgc = color(0);
final color mc = color(255);
final float scs = 18;
final float bcs = 23;
final float lg = 20;
final float hgr = 56;
final float blt = 8;
final float slt = 6;
LineWorker lw;

void setup(){
size(400, 400);
ellipseMode(CENTER);
lw = new LineWorker();
}

void draw(){
background(bgc);

lw.connectLines();
lw.drawAllLines();
filter(BLUR, 6);
lw.drawAllLines();
}

class LineWorker {
  ArrayList<Line> Lines;
  int mCounter;
  byte mFlags = 0;

  LineWorker() {
    Lines = new ArrayList<Line>();
  }

  void drawAllLines() {
    for (Line l : Lines) {
      PVector s, e;
      s = Coor2XY((int)l.s.x, (int)l.s.y);
      e = Coor2XY((int)l.e.x, (int)l.e.y);
      noStroke();
      fill(mc);
      ellipse(s.x, s.y, l.s.x==2?bcs:scs, l.s.x==2?bcs:scs);
      ellipse(e.x, e.y, l.e.x==2?bcs:scs, l.e.x==2?bcs:scs);
      stroke(mc);
      strokeCap(ROUND);
      if ((l.s.x == 1 && l.e.x == 2)||(l.s.x == 2 && l.e.x == 1)||(l.s.x == 2 && l.e.x == 3)||(l.s.x == 3 && l.e.x == 2)) {
        strokeWeight(slt);
        PVector sub = new PVector(s.x, s.y).sub(e);
        PVector t = sub.mult(lg/sub.mag());
        e = e.add(t);
        s = s.add(t.mult(-1));
        line(s.x, s.y, e.x, e.y);
      } else if (l.s.x == 2 && l.e.x == 2) {
        strokeWeight(blt);
        line(s.x, s.y, e.x, e.y);
      } else {
        strokeWeight(slt);
        line(s.x, s.y, e.x, e.y);
      }
    }
  }

  void connectLines() {
    Lines.clear();
    int h = hour() % 12;
    int m = minute();
    boolean pm = (hour() > 12)? true : false;
    mCounter = m % 5;
    int i = (h-1<0)? 11 : h-1, j = (int(m/5)-1<0)? 11 : int(m/5)-1;
    int hAt;
    if (i%2 == 0) {
      Lines.add(new Line(2, i, 3, (i/2)*3));
      hAt = (i/2)*3;
    } else {
      if (PRN() % 2 == 0) {
        Lines.add(new Line(2, i, 3, (i/2)*3 + 1));
        hAt = (i/2)*3 + 1;
      } else {
        Lines.add(new Line(2, i, 3, (i/2)*3 + 2));
        hAt = (i/2)*3 + 2;
      }
    }
    mFlags = 0x7F;
    if (j%2 == 0) {
      Lines.add(new Line(2, j, 1, int(j/2)));
      int t = (int(j/2) % 6 + 1);
      startNest(-1, t);
    } else {
      if (PRN() % 2 == 0) {
        Lines.add(new Line(2, j, 1, int(j/2)));
        int t = (int(j/2) % 6 + 1);
        startNest(-1, t);
      } else {
        Lines.add(new Line(2, j, 1, int(j/2)+1));
        int t = (int(j/2 + 1) % 6 + 1);
        startNest(-1, t);
      }
    }

    if (pm) {
      if (random(8) % 2 == 0) {
        Lines.add(new Line(3, hAt, 3, (hAt+1 > 17)? 0 : hAt + 1));
      } else {
        Lines.add(new Line(3, hAt, 3, (hAt-1 < 0)? 0 : hAt - 1));
      }
    }

    if (i > j) {
      int t = i;
      i = j;
      j = t;
    }

    for (int t = i; t != j; ) {
      if (abs(i-j) == 6 && PRN()%2 == 0) {
        Lines.add(new Line(2, t, 2, t+1));
        t++;
      } else if (abs(i-j) > 6) {
        Lines.add(new Line(2, t, 2, t-1));
        t--;
      } else {
        Lines.add(new Line(2, t, 2, t+1));
        t++;
      }
      t = t<0? 11 : t%12;
    }
  }

  void startNest(int _f, int _n) {
    if (mCounter == 0) return;
    byte near;
    if (_n == 0) {
      near = 0x7D;
    } else if (_n != 1 && _n != 6) {
      near = byte(0x05 << (_n-1));
    } else {
      near = byte(0x22 << ((_n==1)?1:0));
    }
    near = (_n==0)? near : byte(near|0x1);
    if ((mFlags>>_n & 1) == 0) {
      near = byte(near & mFlags & ((_f == -1)? 0xFF : (0x1 << _f) ^ 0xFF));
    } else {
      mFlags = byte(mFlags ^ (0xFF & mFlags & (1<<_n)));
      near = byte(near & ((_f == -1)? 0xFF : (0x1 << _f) ^ 0xFF));
    }
    IntList nearL = new IntList();
    for (byte t = near, i = 0; i < 7; i++, t = byte(t>>1)) {
      if ((t & 0x1) == 1) {
        nearL.append(i);
      }
    }
    int splitInto = 1;
    if (mCounter > 1 && nearL.size() > 1 && _f == -1) {
      splitInto = 2;
    }
    mCounter -= splitInto;
    for (int i = 0; i < splitInto; i++) {
      int t = nearL.get((PRN() + i + _f) % nearL.size());
      Lines.add(new Line(4, _n, 4, t));
      startNest(_n, t);
    }
  }
}

class Line {
  PVector s, e;
  Line(PVector _s, PVector _e) {
    s = _s;
    e = _e;
  }
  Line(int _sl, int _sn, int _el, int _en) {
    s = new PVector(_sl, _sn);
    e = new PVector(_el, _en);
  }
}

PVector Coor2XY(int _l, int _n) {
  _n = (_l!=0)? _n % (_l*6) : _n;
  while (_n<0) {
    _n += _l * 6;
  }
  PVector r = new PVector();
  if ((_l == 0)||(_l == 4 && _n == 0)) {
    r.x = 200;
    r.y = 200;
    return r;
  } else if (_n % _l == 0 || _l == 4) {
    _n = (_l == 4)? _n-1 : _n;
    _l = (_l == 4)? 1 : _l;
    float deg = -60;
    deg += 60 * _n/_l;
    r.x = _l * hgr * cos(radians(deg));
    r.y = _l * hgr * sin(radians(deg));
    r.x += 200;
    r.y += 200;
    return r;
  } else {
    float deg = -60;
    deg += 60 * int(_n/_l);
    r.x = _l * hgr * cos(radians(deg));
    r.y = _l * hgr * sin(radians(deg));
    r.x += 200;
    r.y += 200;
    deg += 120;
    r.x += (_n % _l) * hgr * cos(radians(deg));
    r.y += (_n % _l) * hgr * sin(radians(deg));
    return r;
  }
}

int PRN() {
  int r = 1987 * (day() + minute() * 11 + hour() * 79);
  return r;
}

void drawAllPoints() {
  noStroke();
  fill(mc);
  PVector t;
  t = Coor2XY(0, 0);
  ellipse(t.x, t.y, scs, scs);
  for (int i = 0; i < 6; i++) {
    t = Coor2XY(1, i);
    ellipse(t.x, t.y, scs, scs);
  }
  for (int i = 0; i < 12; i++) {
    t = Coor2XY(2, i);
    ellipse(t.x, t.y, bcs, bcs);
  }
  for (int i = 0; i < 18; i++) {
    t = Coor2XY(3, i);
    ellipse(t.x, t.y, scs, scs);
  }
}

void MBlur(int _r, int _t) {
  for (int i = 0; i < _t; i++) {
    Blur(_r);
  }
}

void Blur(int _r) {
  HBlur(_r);
  VBlur(_r);
}

void HBlur(int _r) {
  color[] B = new color[400];
  int CS, oi, ni, si, ei;
  float div;
  div = 1 / float(_r+_r+1);
  loadPixels();

  for (int j = 0; j < 400; j++) {
    CS = 0;
    loadPixels();

    oi = si = j * 400;
    ei = si + 400 - 1;
    ni = si + _r;
    for (int i = 0; i < _r + 2; i++) {
      CS += pixels[si] & 0xFF;
    }

    for (int i = 0; i < _r + 1; i++) {
      CS += (pixels[ni++] & 0xFF) - (pixels[oi] & 0xFF);
      B[i] = color(CS*div);
    }

    for (int i = _r + 1; i < 400 - _r - 1; i++) {
      CS += (pixels[ni++] & 0xFF) - (pixels[oi++] & 0xFF);
      B[i] = color(CS*div);
    }

    for (int i = 400 - _r - 1; i < 400; i++) {
      CS += (pixels[ei] & 0xFF) - (pixels[oi++] & 0xFF);
      B[i] = color(CS*div);
    }
    for (int i = 0; i < 400; i++) {
      pixels[i+si] = B[i];
    }
    updatePixels();
  }
}

void VBlur(int _r) {
  color[] B = new color[400];
  int CS, oi, ni, si, ei;
  float div;
  div = 1 / float(_r+_r+1);
  loadPixels();

  for (int j = 0; j < 400; j++) {
    CS = 0;
    loadPixels();

    oi = si = j;
    ei = si + (400-1)*400;
    ni = si + _r * 400;
    for (int i = 0; i < _r + 2; i++) {
      CS += pixels[si] & 0xFF;
    }

    for (int i = 0; i < _r + 1; i++) {
      CS += (pixels[ni] & 0xFF) - (pixels[oi] & 0xFF);
      ni+=400;
      B[i] = color(CS*div);
    }

    for (int i = _r + 1; i < 400 - _r - 1; i++) {
      CS += (pixels[ni] & 0xFF) - (pixels[oi] & 0xFF);
      ni+=400;
      oi+=400;
      B[i] = color(CS*div);
    }

    for (int i = 400 - _r - 1; i < 400; i++) {
      CS += (pixels[ei] & 0xFF) - (pixels[oi] & 0xFF);
      oi+=400;
      B[i] = color(CS*div);
    }
    for (int i = 0; i < 400; i++) {
      pixels[400*i+si] = B[i];
    }
    updatePixels();
  }
}

Thanks!

Edit: I’m not using the blur function I wrote, currently I’m using the filter(BLUR) but still get the same error.

I don’t have a watch to test, but tried the code on APDE.
It runs on the phone and doesn’t give any error when trying to send code to watch.
Are you using APDE?

It runs on the phone and doesn’t give any error when trying to send code to watch.

It gets error when I apply the watch face, when I apply it the watch face just shows and fadeout about 2 times and the wear os changes my watch face to the one call “simple”

Are you using APDE?

I’m using the processing PED on windows, specifically Processing 3.5.4, Android Mode 4.1.1

Thanks for the reply!

Maybe you should use get() first to take an PImage of the screen and then use the filter on it.

Anyways I would try it on APDE.
It uses a previous more stable mode, and compiles in seconds.

Thanks, I’ll try that later, I have classes later.

1 Like

You’re right!
I tried it on APDE and it runs flawlessly on the phone, but when I install the wear os version of APDE and send the watchface to it, the applied APDE watchface is just a black screen, not the one I wrote, or maybe it is, but something just went wrong.
This also happened when commenting out the line with blur function.
What should I do now?

Thanks!

Well, I think you have to spend some more time, and repeat writing the code again, piece by piece, and take the advantage of APDE, that testing is really fast. This way you will discover where the code fails.
I personally work on my PC for editing.I use an app called Pigeon which shares the clipboards from PC and phone. So I edit on my PC, and when I want to test my code, I press select/copy all, and then on my phone with APDE already open select/paste all. After that, I press run, and the code is compiled within a few seconds.

Thanks, I’ll try that later, the app you mentioned sounds very useful, appreciate you help :slight_smile: