Loading...
Logo
Processing Forum
hi
if i want to save a picture with saveFrame("bild.png") and open it in photoshop, it shows a dpi of 72. is there a possibility to safe pictures with 300 dpi?
thanks for help

Replies(21)

Two ways to do it:

1) Save the image with a higher number of pixels (figure out how many you actually want).  Then, in photoshop, set the DPI to whatever you want, with resampling turned off.  For example, to go from 72 / 300, you would use a width that is 300/72 or 4.166 times what you are using now.  So if my original width/height were set to 800 x 600, I would change the size command from

size(800,600)
to
size(int(800*4.166),int(600*4.166));

Save the image, and then load it in photoshop, and then manually set the DPI to 300.

Note: this only works if your sketch is constructed to pay attention to the active width/height.  If you are using hard-coded coordinates, then you should also add 

scale(300/72.0);

to the front of your draw() function.  Or just use PDF.

2) Export to PDF, and then load the PDF into Photoshop at whatever size you like (this will be better if you need something extremely high resolution).



hi
thank you for that super idea - scaling it up and then make it smaller in photoshop again. the problem is, if i scale it up to the size of 300 dpi - i cannot see the whole display anymore because my cinema-monitor is to small and the mouse is not at the place it should be but about 10 cm more left...
i think i have to change the whole script? or is there a way to scale it up only at the moment the file has to be saved and not before?

If it is still about your drawing application, instead of directly doing line() with previous and current coordinates, you can save the coordinates in an ArrayList<PVector>, then draw.
Thus, when you need to save at high resolution, you can make a big PGraphics and replay the drawing with scaling of the saved coordinates, then save it.
yes it is still about my drawing application and - ups - your advice sounds very complicated
i am not good at all in programming - what is the point of saving the coordinates in an array list pvector? does it drawing it afterwards?will there not be still to many vectors?
and what do you mean with a big PGraphics?

by the way - the big problem with the scaling is, that the mouse does not draw there where it is, but about 13 cm right of it....
oh ! now i understand what you mean ! cool ! but how?
i have no idea how i coud save the coordinates of the mouse in an array list and replay it again that is to complicated for me to program...
This shows the basic idea.

1) All drawing occurs inside myDrawing(), which is based the current drawing context as a PGraphics.

2) In draw, we obtain the current drawing context using this.g

3) When 's' is pressed, we allocate a new graphics object, scale it, and draw into it.  Then save the drawing.

Note: On my machine, hitting 's' uses a lot of memory. Processing issued a message saying I needed to increase my memory in preferences.  I increased it (to 512m) and it worked.


Copy code
  1. // Save at equivalent pixel resolution of 300 when you type 's'

  2. float mySaveScale = 300/72.0;

  3. void setup()
  4. {
  5.   size(800,600);
  6.   smooth();
  7. }

  8. void myDrawing(PGraphics pg)
  9. {
  10.   pg.background(255);
  11.   pg.stroke(0);
  12.   pg.strokeWeight(10);
  13.   pg.triangle( 200, 300, 600, 150, 600, 450);
  14. }

  15. void draw()
  16. {
  17.   myDrawing(this.g);
  18. }

  19. void keyPressed()
  20. {
  21.   if (key == 's') {
  22.     println("SAVING to test.png");
  23.     PGraphics pg = createGraphics(int(width*mySaveScale), int(height*mySaveScale), P2D);
  24.     pg.beginDraw();
  25.     pg.scale(mySaveScale);
  26.     myDrawing(pg);
  27.     pg.save("test.png");
  28.     pg.endDraw();
  29.   }
  30. }


thank you for your script. i tried it and i am impressed! super! an for me as newby still understandable - but - if i work with line(mouxeX, mouseY, pmousex, pmouseY) it doesn't show the drawing after saving. do you know why and how i could change it?

you should maybe checkout the tilsaver. i also posted a code for using pgraphics here though
https://forum.processing.org/topic/high-resolution-image-save


thank you for your tipps an link. unfortunately i need to see the drawing which is made by line(mouseX, mouseY, pmouseX, pmouseY) in the moment i am drawing - realtime...
Sorry, I was busy, no time for a detailed answer until the week-end...

So, let's go slowly.
A PGraphics is a PImage with additional methods (and perhaps fields) to draw upon the image.
You already manipulate a PGraphics without knowing it: when you do line(), you implicitly do g.line() where g is the default PGraphics used by Processing. All drawings go there, and at the end of draw(), it is copied on the screen.
Now, you can do your own PGraphics, of whatever size you want, that are, by default, not displayed. Sometime, you don't even want to display them, you just use them as a scratch pad (eg. finding if mouse is over a shape) or save them directly to disk (that's what we want to do).

ArrayList is relatively simple to use: it is really just an array that can automatically grow if filled up. It just have some specific syntax to add items and get them. I explained some details in Why use ArrayList instead of array with append()? article.

Let's start simple and store the drawing in an array list. I won't use a PGraphics at first.
Copy code
  1. ArrayList<Stroke> strokes = new ArrayList<Stroke>();
  2. boolean bNewLine = true;
  3.  
  4. void setup()
  5. {
  6.   size(360, 480);
  7.   smooth();
  8. }
  9.  
  10. void draw()
  11. {
  12.   background(255);
  13.   if (mousePressed)
  14.   {
  15.     Stroke s = new Stroke(mouseX, mouseY, bNewLine);
  16.     strokes.add(s);
  17.     bNewLine = false;
  18.   }
  19.   else
  20.   {
  21.     bNewLine = true;
  22.   }
  23.  
  24.   Stroke ps = null;
  25.   for (Stroke s : strokes)
  26.   {
  27.     if (!s.bNewLine)
  28.     {
  29.       line(ps.x, ps.y, s.x, s.y);
  30.     }
  31.     // Else, don't draw a line from the previous stroke
  32.    
  33.     // This point is the starting point of the next line
  34.     ps = s;
  35.   }
  36. }
  37.  
  38. class Stroke
  39. {
  40.   int x, y;
  41.   boolean bNewLine;
  42.   Stroke(int _x, int _y, boolean _b)
  43.   {
  44.     x = _x;
  45.     y = _y;
  46.     bNewLine = _b;
  47.   }
  48. }
I used a simple class that's just an easy way to store several related values together.
If you really have memory problems, we can reduce the memory usage even further (by dropping the storage of the boolean), but it is a bit more advanced. Since it is still quite simple, I show it as it is a nice illustration of OO coding:

You can still use the first version if you feel more comfortable with it, they are functionally equivalent.
Copy code
  1. ArrayList<Stroke> strokes = new ArrayList<Stroke>();
  2. boolean bNewLine = true;

  3. void setup()
  4. {
  5.   size(360, 480);
  6.   smooth();
  7. }

  8. void draw()
  9. {
  10.   background(255);
  11.   if (mousePressed)
  12.   {
  13.     Stroke s; // Declare to the interface
  14.     if (bNewLine)
  15.     {
  16.       s = new NewLineStroke(mouseX, mouseY);
  17.     }
  18.     else
  19.     {
  20.       s = new ContinuationStroke(mouseX, mouseY);
  21.     }
  22.     strokes.add(s);
  23.     bNewLine = false;
  24.   }
  25.   else
  26.   {
  27.     bNewLine = true;
  28.   }

  29.   Stroke ps = null;
  30.   for (Stroke s : strokes)
  31.   {
  32.     if (!s.startsNewLine())
  33.     {
  34.       line(ps.getX(), ps.getY(), s.getX(), s.getY());
  35.     }
  36.     // Else, don't draw a line from the previous stroke

  37.     // This point is the starting point of the next line
  38.     ps = s;
  39.   }
  40. }

  41. // The interface defines what methods MUST be implemented by the classes using it
  42. // If we define an array list storing Stroke, we can put in it anything implementing this interface,
  43. // and be confident we can use these methods on these objects.
  44. interface Stroke
  45. {
  46.   /** @return true if we need to start a new, disconnected line from here. */
  47.   boolean startsNewLine();
  48.   // Getters
  49.   int getX();
  50.   int getY();
  51. }

  52. // Implementation common to both concrete classes
  53. // By making it abstract, we cannot instantiate it, cannot be used with 'new'
  54. abstract class BaseStroke implements Stroke
  55. {
  56.   // Protected: sub-classes can access them
  57.   protected int x, y;

  58.   //@Override -- Processing doesn't understand annotations yet
  59.   // The above indicates this method is required by the interface we implement
  60.   int getX() { return x; }
  61.   //@Override
  62.   int getY() { return y; }

  63.   // startsNewLine() isn't here, which is legal because this class is abstract
  64. }

  65. // Here, we inherit BaseStroke, so we can use what it defined
  66. class NewLineStroke extends BaseStroke
  67. {
  68.   public NewLineStroke(int _x, int _y)
  69.   {
  70.     x = _x;
  71.     y = _y;
  72.   }

  73.   //@Override
  74.   public boolean startsNewLine()
  75.   {
  76.     return true; // Specific to this implementation
  77.   }
  78. }

  79. class ContinuationStroke extends BaseStroke
  80. {
  81.   public ContinuationStroke(int _x, int _y)
  82.   {
  83.     x = _x;
  84.     y = _y;
  85.   }

  86.   //@Override
  87.   public boolean startsNewLine()
  88.   {
  89.     return false; // Specific to this implementation
  90.   }
  91. }

Continuing.
There is a nice side-effect of drawing this way: you can easily implement an undo!
For future usage, I also move the drawing to a separate function.
I don't paste again the class definitions (and the start of the sketch), they don't change.
Copy code
  1. void draw()
  2. {
  3.   background(255);
  4.   if (mousePressed)
  5.   {
  6.     Stroke s; // Declare to the interface
  7.     if (bNewLine)
  8.     {
  9.       s = new NewLineStroke(mouseX, mouseY);
  10.     }
  11.     else
  12.     {
  13.       s = new ContinuationStroke(mouseX, mouseY);
  14.     }
  15.     strokes.add(s);
  16.     bNewLine = false;
  17.   }
  18.   else
  19.   {
  20.     bNewLine = true;
  21.   }
  22.   drawOn(g);
  23. }

  24. void drawOn(PGraphics surface)
  25. {
  26.   Stroke ps = null;
  27.   for (Stroke s : strokes)
  28.   {
  29.     if (!s.startsNewLine())
  30.     {
  31.       surface.line(ps.getX(), ps.getY(), s.getX(), s.getY());
  32.     }
  33.     // Else, don't draw a line from the previous stroke

  34.     // This point is the starting point of the next line
  35.     ps = s;
  36.   }
  37. }

  38. void keyPressed()
  39. {
  40.   if (key == 'u') // undo
  41.   {
  42.     for (int i = strokes.size() - 1; i >= 0; i--)
  43.     {
  44.       Stroke s = strokes.get(i);
  45.       strokes.remove(i);
  46.       if (s.startsNewLine())
  47.         break; // Found the start of the current line, we don't delete further
  48.     }
  49.   }
  50. }
Let's make the final step toward saving in high resolution:
Copy code
  1. void keyPressed()
  2. {
  3.   if (key == 's')
  4.   {
  5.     PGraphics drawingSurface = createGraphics(width * scaleFactor, height * scaleFactor, JAVA2D);
  6.     drawingSurface.beginDraw();
  7.     drawingSurface.smooth();
  8.     drawingSurface.background(255);
  9.     drawingSurface.scale(scaleFactor);
  10.     drawOn(drawingSurface);
  11.     drawingSurface.endDraw();
  12.  
  13.     drawingSurface.save("Big.png");
  14.     println("Done saving");
  15.   }
  16.   else if (key == 'u') // undo
  17.   {
  18.     for (int i = strokes.size() - 1; i >= 0; i--)
  19.     {
  20.       Stroke s = strokes.get(i);
  21.       strokes.remove(i);
  22.       if (s.startsNewLine())
  23.         break; // Found the start of the current line, we don't delete further
  24.     }
  25.   }
  26. }
scale() allows also to scale the stroke, so the drawing is fully proportional.
You can have a memory issue if the image is too big.
I think it should be easy to save four (or more) separate images, which can be stitched together later, using Photoshop, Gimp or even ImageMagick.

Note that if you create a PDF PGraphics instead of a bitmap one, you get a PDF file instead of a PNG one, with very little code change.

You can find the full sketch at http://bazaar.launchpad.net/~philho/+junk/Processing/files/head:/_QuickExperiments/_Interactive/DrawingHiRes/
hey wow! you are genious! thank you very much for your detailed help!
for me as a newby - it is quite complicated. i don't really understand the script, but i will try to combine it with mine so that it hopefully will work. i hope i am able to do so and will publish it here a soon as i get there

now my hopefully last question...
i need to draw on a grafictablet which is a horizontal format A4 size(842,595).
but as output i need a vertical format A4.

the easiest way to do so, would be to change size(595,842) but this doesn't fit on the tablet anymore. i can't scale it smaller because i also need the "original and real drawing" with the same size 595,842.
if i have to draw it horizontal, making a composition horizontal which is looked at vertical when it is finished - this is quite confusing (thinking as a painter).

is there a possibility to rotate the output display? not what happens inside the output display - i mean the whole display?
i tried it with rotating the monitor on 90° - but this is extremely confusing when a left mouse moving changes to down moving...
this is definitively to complicated for me - i already have problems with left an right when nothing is rotated


hi
i tried the whole afternoon to bring my script and your script together. it works - but not perfect. my problem is, that the textfields are not on the picture after i save it with key s
below there is the combined script. as you can see i tried to integrate my class wirte.textfield() into drawingSurface. it doesn't work. so i tried to make it like this:
drawingSurface.write.textfield();
but it says:
drawingSurface.write cannot be resolved or is not a field
what does this mean?
can you help me again?

Copy code
  1.   //import processing.pdf.*;
    ArrayList<Stroke> strokes = new ArrayList<Stroke>();
    boolean bNewLine = true;
    final int scaleFactor = 4;

       //klasse textfeld erzeugt objekt schreiben
       textfield write;
       float totalDistance; //zahlenvariable für distanz in pixeln
       float cmDistance;//zahlenvariable für cm-umrechnung
       float sFr;//preis pro cm
       float value = 0;
      
      
     // boolean recording;
     // PGraphicsPDF pdf;
      
       void setup() {
       
         size(566,397);
       //  pdf = (PGraphicsPDF) createGraphics(566, 397, PDF, "zeichnung.pdf");
         background(255);
         smooth();
      
         //erzeugt neues textfeld mit name schreiben
         write = new textfield();
        
       }
     
       void draw() {
         background(255);
         stroke(0);
       
         if (mousePressed) {
         //  line(mouseX, mouseY, pmouseX, pmouseY);
           totalDistance += dist(mouseX, mouseY, pmouseX, pmouseY);
           cmDistance = totalDistance * 0.035277;
           sFr = totalDistance * 0.035277 /100;
           value = totalDistance; 
       
        
       Stroke s; // Declare to the interface
        if (bNewLine)
        {
          s = new NewLineStroke(mouseX, mouseY);
        }
        else
        {
          s = new ContinuationStroke(mouseX, mouseY);
        }
        
        strokes.add(s);
        bNewLine = false;
           
      }
      else
      {
        bNewLine = true;

     }
           drawOn(g);
          
         //ruft funktion texteinfüllen der klasse textfeld auf und schreibt es ins objekt schreiben
         write.textfillin();
        
     
        /* if ((value > 36090 ) && (value < 36095)) {
           saveFrame("zeichnung_value.png");
         }*/
       }
       //---------------------------------
      void drawOn(PGraphics surface)
    {
      Stroke ps = null;
      for (Stroke s : strokes)
      {
        if (!s.startsNewLine())
        {
          surface.line(ps.getX(), ps.getY(), s.getX(), s.getY());
        }
        // Else, don't draw a line from the previous stroke

        // This point is the starting point of the next line
        ps = s;   
      }  
    }

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

    void keyPressed()
     
    {
     
      if (key == 's')
      {

        PGraphics drawingSurface = createGraphics(width * scaleFactor, height * scaleFactor, JAVA2D);

        drawingSurface.beginDraw();

    write.textfillin();

        drawingSurface.smooth();
        drawingSurface.scale(scaleFactor);
        drawOn(drawingSurface);
        drawingSurface.endDraw();
      
        drawingSurface.save("Big.png");
     
      }
      else if (key == 'u') // undo
      {
        for (int i = strokes.size() - 1; i >= 0; i--)
        {
          Stroke s = strokes.get(i);
          strokes.remove(i);
          if (s.startsNewLine())
            break; // Found the start of the current line, we don't delete further
        }
      }
    }
    //-------------------------------------
    // The interface defines what methods MUST be implemented by the classes using it
    // If we define an array list storing Stroke, we can put in it anything implementing this interface,
    // and be confident we can use these methods on these objects.
    interface Stroke
    {
     
     
      /** @return true if we need to start a new, disconnected line from here. */
      boolean startsNewLine();
      // Getters
      int getX();
      int getY();  
    }
    //-------------------------------------
    // Implementation common to both concrete classes
    // By making it abstract, we cannot instantiate it, cannot be used with 'new'
    abstract class BaseStroke implements Stroke
    {
      // Protected: sub-classes can access them
      protected int x, y;

      //@Override -- Processing doesn't understand annotations yet
      // The above indicates this method is required by the interface we implement
      int getX() { return x; }
      //@Override
      int getY() { return y; }
      // startsNewLine() isn't here, which is legal because this class is abstract
     
     
    }
    //-------------------------------------
    // Here, we inherit BaseStroke, so we can use what it defined
    class NewLineStroke extends BaseStroke
    {
      public NewLineStroke(int _x, int _y)
      {
        x = _x;
        y = _y;
       
      }

      //@Override
      public boolean startsNewLine()
      {
        return true; // Specific to this implementation
       
      }
     
    }
    //-------------------------------------
    class ContinuationStroke extends BaseStroke
    {
      public ContinuationStroke(int _x, int _y)
      {
        x = _x;
        y = _y;
       
      }

      //@Override
      public boolean startsNewLine()
     
      {
        return false; // Specific to this implementation
      }
     
    }
     //-------------------------------------
     class textfield{

       void textfillin() {
     
         textSize(8);
         noStroke();  
        
        //position nach drehung
        //translate(525, 350);//rechter bildrand mit rotate(PI/-2.0)
        translate(40, 40);
        //drehen um 90 gradr
        rotate(PI/2.0);
        
     
         //position ohne drehung
     // translate(220, 355);
         
         //distanz in pixel
         fill(255);
         rect(16, 5, 72, 22);//referenzquadrat und texthalter  
         fill(0, 0, 0);//schriftfarbe
         text(" px "+totalDistance, 15, 20);
        // text("px|", 73, 20);
        
         //distanz in cm
         fill(255);
         rect(88, 5, 72, 22);
         fill(0, 0, 0);
         text("cm "+cmDistance, 87, 20);
         //text("cm|", 145, 20);
        
         //datum
         fill(255);
         rect(160, 5, 52, 22);
         fill(0, 0, 0);
         int d = day();    // Values from 1 - 31
         int m = month();  // Values from 1 - 12
         int y = year();   // 2003, 2004, 2005, etc.
        String datum = String.valueOf(d);
        text(datum+".", 160, 20);
        datum = String.valueOf(m);
        text(datum+".", 173, 20);
        datum = String.valueOf(y);
        text(datum +" |", 186, 20);
        
         //uhrzeit
         fill(255);
         rect(212, 5, 72, 22);
         fill(0, 0, 0);
         int h = hour();    // Values from 1 - 31
         int mi = minute();  // Values from 1 - 12
         int se = second();   // 2003, 2004, 2005, etc.
        String z = String.valueOf(h);
        text("time "+z+".", 213, 20);
        z = String.valueOf(mi);
        text(z+".", 245, 20);
        z = String.valueOf(se);
        text(z, 258, 20);
      
         //signatur
         fill(255);
         rect(272, 5, 68, 22);//referenzquadrat und texthalter  
         fill(0, 0, 0);//schriftfarbe
         text("| a o ", 274, 20);  

         
         //nummer
         fill(255);
         //rect(338, 5, 72, 22);//referenzquadrat und texthalter  
         rect(160, 25, 120, 35);
         fill(0, 0, 0);//schriftfarbe
         text("Nr. 3 / 1'273'200", 162, 35);
        
          //distanz in sFr
         fill(255);
         rect(272, 25, 72, 35);
         fill(0, 0, 0);
         text(sFr, 305, 35);
         text("| sFr.", 275, 35);

       }
       
      }


     
There is no point to make a class holding only one method and no fields. Classes are useful (in general) when you make several instances of them, and they distinguish themselves by their values.
See: my drawOn function was not wrapped in a class.

Moreover, if all you want to do is to display the text on the screen, you just have to call the function in draw(), after the drawing. If you want to save it too, you have to do similarly to drawOn(), ie. prefix all the calls with the PGraphics object.

You should read a bit more on PGraphics usage, to really understand what is going on.
And you can ask questions on stuff you didn't understand, there is no problem with that.
it works! you are a great help! thanks!
i made classes of the textfields to keep a better survey and keeping it easier and i thought, that i could do it in the PGraphics drawingSurface with drawingSurface.writing.textfield() because i thought i made a instance of all the textfields - but - depending the place i wrote drawingSurface.writing.textfield(), the result was that it ignored it, or in the other case, it didn't show the line anymore and it ignored the rotation and size - and in both cases, it didn't save it - so - obviously it doesn't work like this and i have to make it double.

now i copied and placed the textfields singularly within the PGraphics and added drawingSurface.xxx - and it works.
the good thing is - that i can have it rotated in the saved picture and dont' need to show it on the display because i had to do it double - that's cool in some way.

the only thing i need yet is, that processing makes a bling or some sound, shortly before i reach whyle drawing the limit of 36090 pixels - any idea how i could do this. the only thing i found was a library with importing sound but nothing with generating sound at a certain situation within processing...

Copy code
  1. void keyPressed()
     
    {
     
      if (key == 's')
      {

        PGraphics drawingSurface = createGraphics(width * scaleFactor, height * scaleFactor, JAVA2D);

        drawingSurface.beginDraw();


    //drawingSurface.write.textfillin();

        drawingSurface.smooth();
        drawingSurface.scale(scaleFactor);
        drawOn(drawingSurface);
    /****************/
    //textfelder müssen hier nochmals geschrieben werden, damit es beim sichern mitkommt
      
        drawingSurface.textSize(8);
        drawingSurface.noStroke();
        //position nach drehung
        //translate(525, 350);//rechter bildrand mit rotate(PI/-2.0)
        drawingSurface.translate(40, 40);
        //drehen um 90 gradr
        drawingSurface.rotate(PI/2.0);
        drawingSurface.fill(0, 0, 0);//schriftfarbe
      
         //distanz in pixel
         drawingSurface.text(" px "+totalDistance, 15, 20);
        
         //distanz in cm
         drawingSurface.text("cm "+cmDistance, 87, 20);

         //datum
         int d = day();    // Values from 1 - 31
         int m = month();  // Values from 1 - 12
         int y = year();   // 2003, 2004, 2005, etc.
        String datum = String.valueOf(d);
        drawingSurface.text(datum+".", 160, 20);
        datum = String.valueOf(m);
        drawingSurface.text(datum+".", 173, 20);
        datum = String.valueOf(y);
        drawingSurface.text(datum +" |", 186, 20);
        
         //uhrzeit
         int h = hour();    // Values from 1 - 31
         int mi = minute();  // Values from 1 - 12
         int se = second();   // 2003, 2004, 2005, etc.
        String z = String.valueOf(h);
        drawingSurface.text("time "+z+".", 213, 20);
        z = String.valueOf(mi);
        drawingSurface.text(z+".", 245, 20);
        z = String.valueOf(se);
        drawingSurface.text(z, 258, 20);
        
         //signatur
         drawingSurface.text("| arlette ochsner ", 274, 20);
        
          //nummer
         drawingSurface.text("Nr. 3 / 1'273'200", 162, 35);
        
          //distanz in sFr
         drawingSurface.text("| sFr. " +sFr, 275, 35);
        
        
     /********************/
        drawingSurface.endDraw();
      
      
        drawingSurface.save("Big.png");
     
      }
      else if (key == 'u') // undo
      {
        for (int i = strokes.size() - 1; i >= 0; i--)
        {
          Stroke s = strokes.get(i);
          strokes.remove(i);
          if (s.startsNewLine())
            break; // Found the start of the current line, we don't delete further
        }
      }
    }
You can generate sounds with the built-in Minim library. See the examples (File > Examples...) under Libraries > Minim Audio. For example, SineWaveSignal generates a sound without loading a file.
thank you for your advice - in the meantime i found the example SineWave and i took the script and integrated it into my script - and i got to run it the way i want! i am really proud, that i could do it without your help for this time

now i have another question - if i write the amount of pixels in my textfield it shows e.g. px 112.345234 - i would like to shorten it to 112.35 - i found examples for float floor(). but it shortens to 112 - i am searching for some way to shorten it as decimal to 2 positions after the point and round it mathematically up or down. i found some advices to use nf() - but i don't understand, what it does, how it works an how i could integrate it into my script. is there a more simple way to do it?
nf() is indeed the simplest way.
Example:
float x = 112.345234;
println(nf(x, 0, 2));
Hard to do simpler...
wow - it is really simple if you explain it!  it works perfect!!!!

now i am almost happy - what i wonder is - is there a possibility to measure the time i need to do the drawing and give it out in minutes or seconds?

and the amount of cm/pixels adding up from one drawing to the next and
subtracting the amount of used cm/pixels from e.g. 100'000 cm/pixels
the amount to go yet comparing with the amount done?
i guess this will be very complicated because it goes from drawing to drawing resp. from file to file, picture to picture...
i think i have to do this by hand - do i?
Yes, you have to do it by hand.
And you can use millis() to measure the time since the start of the sketch. There was a recent question about a chronometer or similar, which shows how to convert this time to minutes and seconds. Although it is just a matter of dividing by the correct amount...
hi
sorry for not answering so long but i was extremely busy this week.
in the meantime i could manage it with the millis() and now the script is exactly doing what i want. i am very happy!
thank you for your extreme help!!! i appreciate it!!!

here is the whole script
Copy code
  1.  import ddf.minim.*;
    import ddf.minim.signals.*;

    Minim minim;
    AudioOutput out;
    SineWave sine;
     

    ArrayList<Stroke> strokes = new ArrayList<Stroke>();
    boolean bNewLine = true;
    final int scaleFactor = 4;

       //klasse textfeld erzeugt objekt schreiben
       textfield write;
       float totalDistance; //zahlenvariable für distanz in pixeln
       float cmDistance;//zahlenvariable für cm-umrechnung
       float sFr;//preis pro cm
       float value = 0;
     
     //timer
      int accumTime;   // total time accumulated in previous intervals
    int startTime;   // time when this interval started
    boolean running = false;
    int displayTime;   // value to display on the clock face

      int dHours, dMins, dSecs, dDecimal;
      
     
      
       void setup() {
       
         size(566,397);
         background(255);
         smooth();
      
         //erzeugt neues textfeld mit name schreiben
         write = new textfield();
        
     //sound
         minim = new Minim(this);
     
      // get a line out from Minim, default sample rate is 44100, default bit depth is 16
      out = minim.getLineOut(Minim.STEREO, 2048);
     
      // create a sine wave Oscillator, set to 440 Hz, at 0.5 amplitude, sample rate 44100 to match the line out
      sine = new SineWave(440, 0.5, out.sampleRate());
           
       }
     
       void draw() {
         background(255);
         stroke(0);
          
         if (mousePressed) {
           totalDistance += dist(mouseX, mouseY, pmouseX, pmouseY);
           cmDistance = totalDistance * 0.035277;
           sFr = totalDistance * 0.035277 /100;
           value = totalDistance; 
        
       //alarmsignal kurz vor 36090 pixel
         if ((value > 35000) && (value < 36080))
         {
           out.addSignal(sine);
         }
       
        if (value > 36090) {
             out.close();
             minim.stop();   
         } 
        
         //timer
         // start timing (but only if running == false)
            if (running == false) {
                startTime = millis();
                running = true;
           
            }
            if (running == true) {
              displayTime = accumTime + millis() - startTime;
            }
           
         dSecs = (displayTime / 1000) % 60;
         dMins = (displayTime / 1000 / 60) % 60;
         dHours = (displayTime / 1000 / 60/ 60); 
        
       Stroke s; // Declare to the interface
        if (bNewLine)
        {
          s = new NewLineStroke(mouseX, mouseY);
        }
        else
        {
          s = new ContinuationStroke(mouseX, mouseY);
        }
        
        strokes.add(s);
        bNewLine = false;
           
      }
      else
      {
        bNewLine = true;

     }
           drawOn(g);
          
         //ruft funktion texteinfüllen der klasse textfeld auf und schreibt es ins objekt schreiben
        
         write.textfillin();
       
       }
       //---------------------------------
      void drawOn(PGraphics surface)
    {
     
      Stroke ps = null;
     
      for (Stroke s : strokes)
      {
        if (!s.startsNewLine())
        {
          surface.line(ps.getX(), ps.getY(), s.getX(), s.getY());
        }
        // Else, don't draw a line from the previous stroke

        // This point is the starting point of the next line
        ps = s;   
        
      }

    }

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

    void keyPressed()
     
    {
     
      if (key == 's')
      {

        PGraphics drawingSurface = createGraphics(width * scaleFactor, height * scaleFactor, JAVA2D);

        drawingSurface.beginDraw();


    //drawingSurface.write.textfillin();

        drawingSurface.smooth();
        drawingSurface.scale(scaleFactor);
        drawOn(drawingSurface);
    /****************/
    //textfelder müssen hier nochmals geschrieben werden, damit es beim sichern mitkommt
      
        drawingSurface.textSize(8);
        drawingSurface.noStroke();
        //position nach drehung
        //translate(525, 350);//rechter bildrand mit rotate(PI/-2.0)
        drawingSurface.translate(40, 40);
        //drehen um 90 gradr
        drawingSurface.rotate(PI/2.0);
        drawingSurface.fill(0, 0, 0);//schriftfarbe
      
         //distanz in pixel
         drawingSurface.text("px "+nf(totalDistance,0,2), 15, 20);
        
         //distanz in cm
         drawingSurface.text("cm "+nf(cmDistance,0,2), 87, 20);

         //datum
         int d = day();    // Values from 1 - 31
         int m = month();  // Values from 1 - 12
         int y = year();   // 2003, 2004, 2005, etc.
        String datum = String.valueOf(d);
        drawingSurface.text(datum+".", 160, 20);
        datum = String.valueOf(m);
        drawingSurface.text(datum+".", 173, 20);
        datum = String.valueOf(y);
        drawingSurface.text(datum +" |", 186, 20);
        
         //uhrzeit
         int h = hour();    // Values from 1 - 31
         int mi = minute();  // Values from 1 - 12
         int se = second();   // 2003, 2004, 2005, etc.
        String z = String.valueOf(h);
        drawingSurface.text("time "+z+".", 213, 20);
        z = String.valueOf(mi);
        drawingSurface.text(z+".", 245, 20);
        z = String.valueOf(se);
        drawingSurface.text(z, 258, 20);
        
         //signatur
         drawingSurface.text("| arlette ochsner ", 274, 20);
       
        //timer
        
        drawingSurface.text("drawingtime: " + nf(dHours,2) + ":" + nf(dMins, 2) + ":" + nf(dSecs, 2),15, 35);
        
          //nummer
         drawingSurface.text("Nr. 3 / 1'273'200", 162, 35);
        
          //distanz in sFr
         drawingSurface.text("| sFr. " +nf(sFr,0,2), 275, 35);
        
        
     /********************/
        drawingSurface.endDraw();
      
        if ((value > 36090 ) && (value < 36095)) {
           drawingSurface.save("zeichnung_value.png");
         }
      
        drawingSurface.save("Big.png");
     
      }
      else if (key == 'u') // undo
      {
        for (int i = strokes.size() - 1; i >= 0; i--)
        {
          Stroke s = strokes.get(i);
          strokes.remove(i);
          if (s.startsNewLine())
            break; // Found the start of the current line, we don't delete further
        }
      }
    }
    //-------------------------------------
    // The interface defines what methods MUST be implemented by the classes using it
    // If we define an array list storing Stroke, we can put in it anything implementing this interface,
    // and be confident we can use these methods on these objects.
    interface Stroke
    {
        
      /** @return true if we need to start a new, disconnected line from here. */
      boolean startsNewLine();
      // Getters
      int getX();
      int getY();  
    }
    //-------------------------------------
    // Implementation common to both concrete classes
    // By making it abstract, we cannot instantiate it, cannot be used with 'new'
    abstract class BaseStroke implements Stroke
    {
      // Protected: sub-classes can access them
      protected int x, y;

      //@Override -- Processing doesn't understand annotations yet
      // The above indicates this method is required by the interface we implement
      int getX() { return x; }
      //@Override
      int getY() { return y; }
      // startsNewLine() isn't here, which is legal because this class is abstract
     
     
    }
    //-------------------------------------
    // Here, we inherit BaseStroke, so we can use what it defined
    class NewLineStroke extends BaseStroke
    {
      public NewLineStroke(int _x, int _y)
      {
        x = _x;
        y = _y;
       
      }

      //@Override
      public boolean startsNewLine()
      {
        return true; // Specific to this implementation
       
      }
     
    }
    //-------------------------------------
    class ContinuationStroke extends BaseStroke
    {
      public ContinuationStroke(int _x, int _y)
      {
        x = _x;
        y = _y;
       
      }

      //@Override
      public boolean startsNewLine()
     
      {
        return false; // Specific to this implementation
      }
     
    }
     //-------------------------------------

    //ist nur für die anzeige auf dem bildschirm
    //die gedruckte variante ist im hauptscript unter darwingSurface
      class textfield{
     
       void textfillin() {
     
         textSize(8);
         noStroke();
         fill(0, 0, 0);//schriftfarbe
     
       //nur für lesbare ansicht oben links
       text(" px "+nf(totalDistance,0,2), 0, 10);  
       
        //position nach drehung
        //translate(525, 350);//rechter bildrand mit rotate(PI/-2.0)
        translate(40, 40);
        //drehen um 90 grad
     rotate(PI/2.0);
         
         //position ohne drehung
        //translate(220, 355);
             
         //distanz in pixel
         text("px "+nf(totalDistance, 0, 2), 15, 20);   
        
         //distanz in cm
         text("cm "+nf(cmDistance, 0, 2), 87, 20);
           
         //datum  
         int d = day();    // Values from 1 - 31
         int m = month();  // Values from 1 - 12
         int y = year();   // 2003, 2004, 2005, etc.
        String s = String.valueOf(d);
        text(s+".", 160, 20);
        s = String.valueOf(m);
        text(s+".", 173, 20);
        s = String.valueOf(y);
        text(s +" |", 186, 20);
        
         //uhrzeit
         int h = hour();    // Values from 1 - 31
         int mi = minute();  // Values from 1 - 12
         int se = second();   // 2003, 2004, 2005, etc.
        String z = String.valueOf(h);
        text("time "+z+".", 213, 20);
        z = String.valueOf(mi);
        text(z+".", 245, 20);
        z = String.valueOf(se);
        text(z, 258, 20);
     
         //signatur
         text("| arlette ochsner", 274, 20);  
       
         //timer
      
        text("drawingtime: " + nf(dHours,2) + ":" + nf(dMins, 2) + ":" + nf(dSecs, 2),15, 35);
       
         //nummer
         text("Nr. 3 / 1'273'200", 162, 35);
         
         //distanz in sFr
         text("| sFr. " +nf(sFr, 0, 2), 275, 35);    
       }   
      }