# 3d scanner with Arduino and laser pointer

**URL:** <https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360>\
**Category:** Project Guidance\
**Created:** [May 29, 2021, 5:51pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360 "2021-05-29T17:51:33Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2021, 12:00pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/21 "2021-06-02T12:00:16Z")

</div>

here:

I made something for you.

As I described above the steps.

- ArrayList listOfFrames holds the steps of your scans.
- Each frame / scan holds several points. Here you have to implement your scan.
- in state 0 you can loop through the points (space bar)
- Press return now
- in state 1 the points are connected to the 3D form using a circle form (aka cylinder). This is the core idea. That’s how you can go from 2D (points) to 3D points deforming/making a cylinder.
- Look at it with peasyCam

Chrisir

```auto
import peasy.*;

final int show2D=0;
final int show3D=1;
int state=show2D; 

PeasyCam camera;

ArrayList<Frame> listOfFrames = new ArrayList();
ArrayList<OneQuad> listOneQuad = new ArrayList(); 

// Tool classes 
ToolsPVector toolsPVector = new ToolsPVector();

// float a3=0; 

int i_key=0; 

// ---------------------------------------------------------------

void setup() {
  size(1300, 990, P3D);

  camera = new PeasyCam(this, width/2, height/2, 0, 900);

  createArrayList();
  make3DShape();
} //func setup()

void draw() {

  switch(state) {

  case show2D:
    background(0); // black
    camera(); 

    Frame cf=listOfFrames.get(i_key); // for (Frame cf : listOfFrames) {
    cf.display(300);
    fill(255);
    text("Space Bar to show next frame; ENTER to go to 3D mode; showing frame "
      + i_key 
      +" of "
      +listOfFrames.size()
      +".", 
      19, 19); 
    break; 

  case show3D:
    background(111); // gray 

    avoidClipping(); 
    ambientLight(128, 128, 128) ;
    directionalLight(128, 128, 128, 
      0, 0, 1);
    directionalLight(128, 128, 128, 
      0, 0, -1);
    lightFalloff(1, 0, 0);
    lightSpecular(0, 0, 0);

    // --------

    CheckeredFloor(); 

    for ( OneQuad current : listOneQuad ) {
      current.display();
    }
    break; 

  default : 
    println("Error in draw()"); 
    exit(); 
    break;
  }//switch
  //
} // func draw()

// ---------------------------------------------------------------------------------------------------------------------
// Inputs 

void keyPressed() {

  if (key==' ') {
    i_key++; 
    if (i_key>=listOfFrames.size()) {
      //i_key=listOfFrames.size()-1;
      i_key=0;
    }
  } else if (key==RETURN || key==ENTER) {
    state = show3D;
    i_key=0;
  }
  //
}//func

// ---------------------------------------------------------------------------------------------------------------------
// creating Data

void createArrayList() {
  // create frames 
  ArrayList<Frame> listOfFramesHelper = new ArrayList(); 

  Frame newF = new Frame(); 
  newF.listOfCells.add(new Cell(width/2, 100)); 
  newF.listOfCells.add(new Cell(width/2-210, 200)); 
  newF.listOfCells.add(new Cell(width/2-300, 300)); 
  newF.listOfCells.add(new Cell(width/2-20, 400)); 
  listOfFramesHelper.add(newF); 

  newF = new Frame(); 
  newF.listOfCells.add(new Cell(width/2, 100)); 
  newF.listOfCells.add(new Cell(width/2-110, 200)); 
  newF.listOfCells.add(new Cell(width/2-400, 300)); 
  newF.listOfCells.add(new Cell(width/2-40, 400)); 
  listOfFramesHelper.add(newF); 

  newF = new Frame(); 
  newF.listOfCells.add(new Cell(width/2, 100)); 
  newF.listOfCells.add(new Cell(width/2-130, 200)); 
  newF.listOfCells.add(new Cell(width/2-400, 300)); 
  newF.listOfCells.add(new Cell(width/2-330, 400)); 
  listOfFramesHelper.add(newF); 

  // ------------------------------------------------

  // interpolate ---

  for (int i=0; i<listOfFramesHelper.size()-1; i++) {

    Frame f1=listOfFramesHelper.get(i); 
    Frame f2=listOfFramesHelper.get(i+1); 

    for (int i2=0; i2<10; i2++) { // 10 is the resolution

      newF = new Frame(); 

      for (int i3=0; i3<f1.listOfCells.size(); i3++) {

        Cell c1=f1.listOfCells.get(i3); 
        Cell c2=f2.listOfCells.get(i3); 

        float x1 = lerp( c1.x, c2.x, i2 / 10.0 ); 
        float y1 = lerp( c1.y, c2.y, i2 / 10.0 ); 

        newF.listOfCells.add(new Cell(x1, y1));
      }//for
      listOfFrames.add(newF);
    }//for
  }//for

  // interpolate between last and first ---

  Frame f1=listOfFramesHelper.get(listOfFramesHelper.size()-1); 
  Frame f2=listOfFramesHelper.get(0); 

  for (int i2=0; i2<10; i2++) { // 10 is the resolution

    newF = new Frame(); 

    for (int i3=0; i3<f1.listOfCells.size(); i3++) {

      Cell c1=f1.listOfCells.get(i3); 
      Cell c2=f2.listOfCells.get(i3); 

      float x1 = lerp( c1.x, c2.x, i2 / 10.0 ); 
      float y1 = lerp( c1.y, c2.y, i2 / 10.0 ); 

      newF.listOfCells.add(new Cell(x1, y1));
    }//for
    listOfFrames.add(newF);
  }//for
  println(listOfFrames.size());
}//func 

// -- -- -- -- -- -- 

void make3DShape() {

  // The Core Function 

  for (int i=0; i<listOfFrames.size()-1; i++) {

    float angle = map (i, 0, listOfFrames.size(), 0, TWO_PI);  
    float angle2 = map (i+1, 0, listOfFrames.size(), 0, TWO_PI);  

    Frame f1=listOfFrames.get(i);   
    Frame f2=listOfFrames.get(i+1); 

    for (int i3=0; i3<f1.listOfCells.size()-1; i3++) {

      Cell c1=f1.listOfCells.get(i3); // upper left corner 
      Cell c2=f2.listOfCells.get(i3); // upper right 

      Cell c3=f1.listOfCells.get(i3+1); // lower left 
      Cell c4=f2.listOfCells.get(i3+1); // lower right 

      //---
      float x1 = cos(angle) * (width/2-c1.x); // same corners as above 
      float y1 = c1.y; 
      float z1 = sin(angle) * (width/2-c1.x) +0; 

      float x2 = cos(angle2) * (width/2-c2.x); 
      float y2 = c2.y; 
      float z2 = sin(angle2) * (width/2-c2.x) +0;

      float x3 = cos(angle) * (width/2-c3.x); 
      float y3 = c3.y; 
      float z3 = sin(angle) * (width/2-c3.x) +0; 

      float x4 = cos(angle2) * (width/2-c4.x); 
      float y4 = c4.y; 
      float z4 = sin(angle2) * (width/2-c4.x) +0;

      OneQuad newOneQuad = new OneQuad ( 
        new PVector ( x1, y1, z1 ), 
        new PVector ( x2, y2, z2 ), 
        new PVector ( x4, y4, z4 ), // changed order here 
        new PVector ( x3, y3, z3 )
        );  

      listOneQuad.add(newOneQuad);
    }//for
    //
  }//for

  //---------------------------------------
  // close shape

  float angle = map (listOfFrames.size()-1, 0, listOfFrames.size(), 0, TWO_PI);  
  float angle2 = map (0, 0, listOfFrames.size(), 0, TWO_PI);  

  Frame f1=listOfFrames.get(listOfFrames.size()-1);   
  Frame f2=listOfFrames.get(0); 

  for (int i3=0; i3<f1.listOfCells.size()-1; i3++) {

    Cell c1=f1.listOfCells.get(i3); // upper left corner 
    Cell c2=f2.listOfCells.get(i3); // upper right 

    Cell c3=f1.listOfCells.get(i3+1); // lower left 
    Cell c4=f2.listOfCells.get(i3+1); // lower right 

    //---
    float x1 = cos(angle) * (width/2-c1.x); // same corners as above 
    float y1 = c1.y; 
    float z1 = sin(angle) * (width/2-c1.x) +0; 

    float x2 = cos(angle2) * (width/2-c2.x); 
    float y2 = c2.y; 
    float z2 = sin(angle2) * (width/2-c2.x) +0;

    float x3 = cos(angle) * (width/2-c3.x); 
    float y3 = c3.y; 
    float z3 = sin(angle) * (width/2-c3.x) +0; 

    float x4 = cos(angle2) * (width/2-c4.x); 
    float y4 = c4.y; 
    float z4 = sin(angle2) * (width/2-c4.x) +0;

    OneQuad newOneQuad = new OneQuad ( 
      new PVector ( x1, y1, z1 ), 
      new PVector ( x2, y2, z2 ), 
      new PVector ( x4, y4, z4 ), // changed order here 
      new PVector ( x3, y3, z3 )
      );  

    listOneQuad.add(newOneQuad);
  }//for

  // -------------------------

  println( listOneQuad.size());
}//func 

//-----------------------------------------------------------------------------
// floor

void CheckeredFloor() {
  //floor

  noStroke(); 

  for (int i = -40; i < 40; i++) {
    for (int j = -40; j < 40; j++) {

      // get color
      // % is modulo, meaning rest of division 
      if (i%2 == 0) { 
        if (j%2 == 0) { 
          fill (255, 0, 0);
        } else 
        {
          fill ( 103 );
        }
      } else {
        if (j%2 == 0) { 
          fill ( 103 );
        } else 
        {
          fill (255, 0, 0);
        }
      } // if

      pushMatrix(); 
      translate ( 80*i, height/2+210+30+3.5, 80*j ); 
      box ( 80, 7, 80); // one cell / tile 
      popMatrix();
    } // for
  } // for
} // function 

//-----------------------------------------------------------------------------------------------
// Tools 

void avoidClipping() {
  // avoid clipping (at camera): 
  // https : // 
  // forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
  perspective(PI/3.0, (float) width/height, 1, 1000000);
}//func 

// ==============================================================================================

class Frame {
  // 2D

  // one frame holds a list of points from the image scan

  ArrayList<Cell> listOfCells = new ArrayList(); 

  void display(float xpos) {
    stroke(255); 
    for (Cell c1 : listOfCells) {
      fill(i_key*49+60, 0, 0); 
      ellipse(c1.x+xpos, c1.y, 
        6, 6);
    }
  }
}//class

// ==============================================================================================

class OneQuad {
  // 3D surface (rect)
  PVector pv0, pv1, pv2, pv3; 

  // constr
  OneQuad (PVector pv0_, PVector pv1_, PVector pv2_, PVector pv3_) {
    pv0=pv0_.copy();
    pv1=pv1_.copy();
    pv2=pv2_.copy();
    pv3=pv3_.copy();
  }// constr

  void display() {

    fill(255, 0, 0);

    beginShape(QUAD); // //class 

    fill(255, 0, 0); 
    vertex(pv0.x, pv0.y, pv0.z);
    vertex(pv1.x, pv1.y, pv1.z);
    vertex(pv2.x, pv2.y, pv2.z);
    vertex(pv3.x, pv3.y, pv3.z);

    endShape(CLOSE); // CLOSE
  }
}//class

// ==============================================================================================

class Cell {

  float x, y; // pos
  int sclx=1, scly=1; // size 

  // int i, j; // pos in grid (col/row)

  boolean state=false; // ON / OFF

  // Two colors 
  color colorForOff= color(random(255), random(255), random(255)); // color(0); // 
  color colorForON=color((255), 0, 0); 

  String strImgName = ""; 
  PImage imgCell = null; 

  //constr 
  Cell(float x_, float y_) {
    x = x_; 
    y = y_;
  } //constr 

  void display() {
    fill( colorForOff ); 
    stroke(111); 

    rect(x, y, 
      sclx, scly);
  }//func 

  String toString() {
    return str(x)
      +","+
      str(y);
  }
  //
}//class

//===================================================================================

class ToolsPVector {

  // not a class for an object like a car but a class that collects Tools - FOR 3D -----------!!!! 

  void linePV ( PVector pv1, PVector pv2) {
    line(pv1.x, pv1.y, pv1.z, 
      pv2.x, pv2.y, pv2.z);
  }//func

  void pointPV ( PVector pv) {
    point(pv.x, pv.y, pv.z);
  }//func

  void spherePV ( PVector pv) {
    pushMatrix(); 
    translate(pv.x, pv.y, pv.z); 
    noStroke(); 
    fill(255, 0, 0); 
    sphere(17); 
    popMatrix();
  }//func

  void spherePVCol ( PVector pv, color c1) {
    pushMatrix(); 
    translate(pv.x, pv.y, pv.z); 
    noStroke(); 
    fill(c1); 
    sphere(17); 
    popMatrix();
  }//func

  void vertexPV(color col_, PVector pv_) {
    fill(col_); 
    vertex(pv_.x, pv_.y, pv_.z);
  }
  //
}//class
//

```

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 2, 2021, 6:20pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/22 "2021-06-02T18:20:53Z")

</div>

> [@Chrisir](#):
>
> I made something for you.
> 
> As I described above the steps.

thanks a lot i am working on your steps

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 2, 2021, 6:34pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/23 "2021-06-02T18:34:25Z")

</div>

@paulgoux hi

i do have this part of code how to replace it using ketai library can ketai works instead of video library?

```auto

import processing.video.*;
import nervoussystem.obj.*;
import processing.serial.*;
Capture cam ;
Serial myPort;

void setup() {
  size(800, 600);
  
 
  
    cam = new Capture(this, 640, 480);
    cam.start();
  }

```

i try to follow this code but could not

[Open Android Camera](https://discourse.processing.org/t/topic/23696/10)

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 2, 2021, 9:59pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/24 "2021-06-02T21:59:39Z")

</div>

Dont forget ketai import.

```auto
import android.os.Environment;
import android.os.Build ;
import android.app.Activity;
import android.content.Context;

boolean k1 = false;
int W = 1440, H = 720;
Permission storage, camera, readStorage;
PGraphics canvas;
PShader edges;
KetaiCamera cam;

//void settings(){
// //size(W,H,P2D);
//};

void setup() {
  fullScreen(P2D);
  orientation(LANDSCAPE);
  cam = new KetaiCamera(this, width, height, 60);
  canvas = createGraphics(width, height, P2D);
  //edges = loadShader("edges.glsl");
  storage = new Permission(this, "WRITE_EXTERNAL_STORAGE");
  readStorage = new Permission(this, "READ_EXTERNAL_STORAGE");
  camera = new Permission(this, "CAMERA");
  //cam.start();
};

void draw() {
  fill(255);
  background(0);
  if (frameCount>10&&!cam.isStarted())cam.start();
  image(cam, 0,0);
  text(frameRate, 50, 100);
};

void mousePressed() {
  //if (cam.isStarted()){
  // cam.stop();
  //}else cam.start();

  if (cam.isFlashEnabled())
    cam.disableFlash();
  else
    cam.enableFlash();
};

void onCameraPreviewEvent() {
  cam.read();
};

```

```auto

public class Permission{
  
  PApplet parent;
  String p;
  
  public boolean requestedPortraitImage = false;

  public Permission(PApplet pParent,String permissionName) {
    parent = pParent;
    p = permissionName;
    parent.requestPermission("android.permission."+permissionName, "onPermissionResult", this);
    println(permissionName);
  };

  public void onPermissionResult(boolean granted) {
    if (!granted) {
      PApplet.println("User did not grant ",p, "permission. Camera is disabled.");
    }
  };

};

```

as a class

```auto
import android.os.Environment;
import android.os.Build ;
import android.app.Activity;
import android.content.Context;

boolean k1 = false;
AndroidCamera cam;

void setup() {
  fullScreen(P2D);
  orientation(LANDSCAPE);
  cam = new AndroidCamera(this, width, height, 60);
};

void draw() {
  fill(255);
  background(0);
  cam.display();
};

void mousePressed() {
  cam.toggleFlash();
};

void onCameraPreviewEvent() {
  cam.read();
};

```

```auto
class AndroidCamera {
  PApplet applet;
  KetaiCamera cam;
  int w, h;
  Permission storage, camera, readStorage, P;
  PGraphics canvas;
  PShader shader;
  
  AndroidCamera(PApplet p, int w, int h, int frate) {
    this.w = w;
    this.h = h;
    applet = p;
    cam = new KetaiCamera(p, w, h, frate);
    P = new Permission(p, "WRITE_EXTERNAL_STORAGE");
    P = new Permission(p, "READ_EXTERNAL_STORAGE");
    P = new Permission(p, "CAMERA");
    canvas = p.createGraphics(w, h, P2D);
  };

  void display() {
    start();
    canvas.beginDraw();

    //mult = BMS.Sliders.get(0).value;
    //counter = BMS.Sliders.get(1).value;
    //mult = 1.0;
    //counter = 1.0;
    //edges.set("mult",mult);
    //edges.set("type",counter);
    if (shader!=null)canvas.shader(shader);
    canvas.image(cam, 0, 0);
    canvas.text(frameRate, 50, 100);
    applet.image(canvas, 0, 0);
    //canvas.imageMode(CORNER);
    //canvas.fill(0);
    //canvas.rect(0, 0, width, 20);
    canvas.endDraw();
  };

  void start() {
    if (applet.frameCount>10&&!cam.isStarted())cam.start();
  };

  void toggleFlash() {
    if (cam.isStarted()) {
      if (cam.isFlashEnabled())
        cam.disableFlash();
      else
        cam.enableFlash();
    }
  };

  void read() {
    cam.read();
  };
};

```

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 3, 2021, 11:16pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/25 "2021-06-03T23:16:01Z")

</div>

@jafal

did this work for you?

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 4, 2021, 11:39pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/26 "2021-06-04T23:39:54Z")

</div>

@paulgoux hi

i was working with hardware of the scanner it is need more calibration to get more reasonable result and reliability

next stage i am going to move to android mode i want to replace the video library with ketai camera

this is some scanned stuff

 ![snapshot01](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/e/e90ab64a31bf39692deb1a88634c28b66537283a.png)  
 ![snapshot03](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/a/ab56be149487654b92bd1eb192855276d4f93e21.png)  
 ![snapshot04](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/3/3894888658be17c32f26527ecf1a8c555567132b.png)

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 4, 2021, 11:52pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/27 "2021-06-04T23:52:15Z")

</div>

Ok… doesnt answer the question…

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 12:02am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/28 "2021-06-05T00:02:48Z")

</div>

@paulgoux

it is fine so far i did not implement the whole code i just used part of it but its useful and thanks for you

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 12:13am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/29 "2021-06-05T00:13:10Z")

</div>

> [@paulgoux](#):
>
> ```auto
> cam = new KetaiCamera(p, w, h, frate);
> P = new Permission(p, "WRITE_EXTERNAL_STORAGE");
> P = new Permission(p, "READ_EXTERNAL_STORAGE");
> P = new Permission(p, "CAMERA");
> 
> ```

how to chose the saving folder destination after compiling i mean making the application afford you choice where to save … how to do it ?

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 5, 2021, 12:26am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/30 "2021-06-05T00:26:01Z")

</div>

The filewriter library ive created has that functionality, you initialise it, then tell it what type of file you are saving, inage text etc, default is txt if none is set. Then you set the write location and stipulate wether you want to create the file if the destination folder does not have the desired file. If the file is found you check if you want to overwrite the file or created a new numbered file again the library habndles numbering.

You can then append or overwrite the file deoending on your needs.

Ill also add the option to append the folder later.

If you dont want to use the lib ive left the standalone class in the gallery section.

Also the lib version has dialogue boxes and textboxes. A textbox to set the desired location if you dont know where you want to save at runtime and a dialogue box to get the user overwrite/append choice.

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 12:31am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/31 "2021-06-05T00:31:20Z")

</div>

> [@paulgoux](#):
>
> default is txt if none is set

the sketch i am using deals with image and txt at the same time saving pics to folder and recall them for analyzing then save them a gain

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 5, 2021, 12:33am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/32 "2021-06-05T00:33:29Z")

</div>

Then thats also doable for the library. You could just create two instances of the file output. One to handle the image and the other to handle the text, otherwise you would need to reset all the check bools in between switching types, as the set location function determines what operations to perform

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 12:36am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/33 "2021-06-05T00:36:00Z")

</div>

> [@paulgoux](#):
>
> Then thats also doable for the library.

i am going to try it thank you

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 5, 2021, 12:37am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/34 "2021-06-05T00:37:54Z")

</div>

Note that the github version hasnt been updated with the latest stable version so may have some issues.

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 12:41am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/35 "2021-06-05T00:41:59Z")

</div>

i see

i am now working with replacing video library with ketai then moving afterword for saving stuff

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 5, 2021, 12:53am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/36 "2021-06-05T00:53:12Z")

</div>

heres a simple image save class and sketch

```auto
class imageSaver{
  Permission wstorage,rstorage;
  Activity act;
  PApplet p;
  int counter = -1,maxImageCount;
  boolean imageSaved,mdown;
  String folderName = "MyImageFolder",fileName,ext,absolutePath;
  String imageFile = "MyImage.jpg";
  PImage img;
  File file,file2;
  
  imageSaver(PApplet applet){
    p = applet;
    wstorage = new Permission(p,"WRITE_EXTERNAL_STORAGE");
    act = p.getActivity();
    getExt(imageFile);
  };
  
  imageSaver(PApplet applet,String s1, String s2){
    folderName = s1;
    imageFile = s2;
    p = applet;
    wstorage = new Permission(p,"WRITE_EXTERNAL_STORAGE");
    act = p.getActivity();
    getExt(imageFile);
  };
  
  public void logic() {
    if(mousePressed&&!mdown) {
      img = p.get();
      checkLocation(folderName, imageFile);
      mdown = true;
      counter++;
    }
    if(!mousePressed)mdown = false;
  };

  public void logic(PGraphics canvas) {
    if(true) {
      
      img = canvas.get();
      checkLocation(folderName, imageFile);
      counter++;
    }
  };

  public void checkLocation(String sf, String tf) { 
    boolean k = false;
    try { 
      absolutePath = new String(Environment.getExternalStorageDirectory().getAbsolutePath()); 
      file = new File(absolutePath+"/"+sf); 
      //PApplet.println("checking file1",file,counter);
      if (!file.exists()&&counter==-1) { 
        boolean success = true; 
        success = file.mkdirs();
        img.save(file+"/"+fileName+"."+ext);
        
      } else k = true;
      
      if(counter>-1)k=true;
      boolean k1 = false;
      while(k&&counter<100&&!k1) {
        try { 
          file2 = new File(absolutePath+"/"+folderName+"/"+fileName+counter+"."+ext); 
          PApplet.println("checking file2",file2);
          if (file2.exists()) { 
            counter++;
          } else {
            k = false;
            k1 = true;
            break;
          }
        } 
        catch (Exception e) { 
          PApplet.println("Error while saving file: " + e);
        }
      }
      if(k1){
        //PApplet.println("file",file);
        //PApplet.println("Fname",folderName);
        //PApplet.println("fileName",fileName);
        //PApplet.println("counter",counter);
        //PApplet.println("ext",ext);
        if(counter>-1)img.save(file+"/"+fileName+counter+"."+ext);
        imageSaved = true;
        //PApplet.println("File saved successfully.");
      }
    } 
    catch (Exception e) { 
      PApplet.println("Error while saving file: " + e);
    }
  };
  
  void getExt(String location){

    int count = 0;
    fileName = location.substring(0,location.indexOf("."));
    ext = location.replace(fileName,"");
    ext = ext.replace(".","");
    ext = ext.replace(fileName,"");
  };
  
  public File[] listFiles(String dir) {
    File file = new File(dir);
    if (file.isDirectory()) {
      File[] files = file.listFiles();
      return files;
    } else {
      // If it's not a directory
      return null;
    }
  };

};

```

```auto

import android.os.Environment;
import android.Manifest; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Build.VERSION_CODES; 

import android.app.Activity; 
imageSaver img;

void setup(){
  size(displayWidth, displayHeight);
  background(0, 0, 200); 
  rectMode(CENTER);
  rect(width/2, height/2, width, height/2);
  textAlign(CENTER);
  String str = "Click to save an image.";
  textSize(12);
  float twf = width/textWidth(str);
  textSize(8*twf);
  fill(0);
  text(str, width/2, height/2);
  img = new imageSaver(this);
};

void draw(){
  img.logic();
};

```

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 12:58am UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/37 "2021-06-05T00:58:03Z")

</div>

thank you i was reading this now

# [Filewriter for Android](https://discourse.processing.org/t/filewriter-for-android/28025)

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 9:08pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/38 "2021-06-05T21:08:45Z")

</div>

@paulgoux is there working video library for APDE ?

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [June 5, 2021, 9:10pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/39 "2021-06-05T21:10:32Z")

</div>

Does ketai not work?

---

<div class="post-metadata">

**Author:** ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)\
**Post date:** [June 5, 2021, 9:12pm UTC](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360/40 "2021-06-05T21:12:41Z")

</div>

i am still modify the code did not finished yet but am asking if there is video library for android

[Previous page](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360.md?page=1)

[Next page](https://discourse.processing.org/t/3d-scanner-with-arduino-and-laser-pointer/30360.md?page=3)
