Package Filters

Source Code of Filters.Filter

package Filters;



import java.awt.Color;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

import javax.swing.ProgressMonitor;
import javax.swing.SwingWorker;

import DrawingTools.DrawingTool;
import Makelangelo.MachineConfiguration;


/**
* base class for image filtering
* @author Dan
*/
public class Filter {
  // image properties
  int image_width, image_height;
  float w2,h2,scale;
  DrawingTool tool;
 
  int color_channel=0;
 
  // text properties
  protected float kerning=5.0f;
  protected float letter_width=10.0f;
  protected float letter_height=20.0f;
  protected float line_spacing=5.0f;
  protected float padding=5.0f;
  static final String alphabetFolder = new String("ALPHABET/");
  protected int chars_per_line=25;
  protected boolean draw_bounding_box=false;
 
  // text position and alignment
  public enum VAlign { TOP, MIDDLE, BOTTOM };
  public enum Align { LEFT, CENTER, RIGHT };
  protected VAlign align_vertical = VAlign.MIDDLE;
  protected Align  align_horizontal = Align.CENTER;
  protected float posx=0;
  protected float posy=0;

  // file properties
  String dest;
  // pen position optimizing
  boolean lastup;
  float previous_x,previous_y;
  // threading
  ProgressMonitor pm;
  SwingWorker<Void,Void> parent;

 
  public void SetParent(SwingWorker<Void,Void> p) {
    parent=p;
  }
  public void SetProgressMonitor(ProgressMonitor p) {
    pm=p;
  }
  public void SetDestinationFile(String _dest) {
    dest=_dest;
  }
 
  /**
   * Called by filters that create GCODE from a bufferedImage.
   */
  public void Generate() {}

  /**
   * Replace this with your generator/converter name.
   */
  public String GetName() {  return "Unnamed"}
 
  /**
   * process should be called by filters that modify a bufferedimage.  Think photoshop filters.
   * @param img
   * @return the altered image
   */
  public BufferedImage Process(BufferedImage img) {
    return img;
  }

  // convert should be called by filters that modify a bufferedImage.
  public void Convert(BufferedImage img) throws IOException {}
 
 
  protected int decode(int pixel) {
    int r = ((pixel>>16)&0xff);
    int g = ((pixel>> 8)&0xff);
    int b = ((pixel    )&0xff);
    return (r+g+b)/3;
  }
 
  protected int decode(Color c) {
    int r = c.getRed();
    int g = c.getGreen();
    int b = c.getBlue();
    return (r+g+b)/3;
  }
 
 
  protected int encode(int i) {
    return (0xff<<24) | (i<<16) | (i<< 8) | i;
  }
 

  protected void liftPen(OutputStreamWriter out) throws IOException {
    tool.WriteOff(out);
    lastup=true;
  }
 
 
  protected void lowerPen(OutputStreamWriter out) throws IOException {
    tool.WriteOn(out);
    lastup=false;
  }

 
  protected void ImageStart(BufferedImage img,OutputStreamWriter out) throws IOException {
    MachineConfiguration mc = MachineConfiguration.getSingleton();
    tool = mc.GetCurrentTool();

    ImageSetupTransform(img);
   
    out.write(mc.GetConfigLine()+";\n");
    out.write(mc.GetBobbinLine()+";\n");

    previous_x=0;
    previous_y=0;
   
    SetAbsoluteMode(out);
  }
 
  protected void SetAbsoluteMode(OutputStreamWriter out) throws IOException {
    out.write("G00 G90;\n");
  }
 
  protected void SetRelativeMode(OutputStreamWriter out) throws IOException {
    out.write("G00 G91;\n");
  }
 
  /**
   * setup transform from source image dimensions to destination paper dimensions.
   * @param img source dimensions
   */
  protected void ImageSetupTransform(BufferedImage img) {
    SetupTransform( img.getWidth(), img.getHeight() );
  }
 
  /**
   * setup transform when there is no image to convert from.  Essentially a 1:1 transform.
   */
  protected void SetupTransform() {
    MachineConfiguration mc = MachineConfiguration.getSingleton();
    // TODO I don't remember why these * 20 are needed here.  Find out and comment the code.
    SetupTransform( (int)mc.GetPaperWidth()*20, (int)mc.GetPaperHeight()*20 );
  }
 
  protected void SetupTransform(int width,int height) {
    image_height = height;
    image_width = width;
    h2=image_height/2;
    w2=image_width/2;
   
    MachineConfiguration mc = MachineConfiguration.getSingleton();
   
    scale=10f;

    int new_width = image_width;
    int new_height = image_height;
   
    if(image_width>mc.GetPaperWidth()) {
      float resize = (float)mc.GetPaperWidth()/(float)image_width;
      scale *= resize;
      new_height *= resize;
    }
    if(new_height>mc.GetPaperHeight()) {
      float resize = (float)mc.GetPaperHeight()/(float)new_height;
      scale *= resize;
      new_width *= resize;
    }
    scale *= mc.paper_margin;
    new_width *= mc.paper_margin;
    new_height *= mc.paper_margin;
   
    TextFindCharsPerLine(new_width);
   
    posx = w2;
    posy = h2;
  }
 
 
  protected int pointSample(BufferedImage img,int x,int y) {
    Color c = new Color(img.getRGB(x, y));
    switch(color_channel) {
    case 1: return c.getRed();
    case 2: return c.getGreen();
    case 3: return c.getBlue();
    default: return decode(c);
    }
  }

 
  protected int TakeImageSample(BufferedImage img,int x,int y) {
    // point sampling

    // 3x3 sampling
    int c=0;
    int values[]=new int[9];
    int weights[]=new int[9];
    if(y>0) {
      if(x>0) {
        values[c]=pointSample(img,x-1, y-1);
        weights[c]=1;
        c++;
      }
      values[c]=pointSample(img,x, y-1);
      weights[c]=2;
      c++;

      if(x<image_width-1) {
        values[c]=pointSample(img,x+1, y-1);
        weights[c]=1;
        c++;
      }
    }

    if(x>0) {
      values[c]=pointSample(img,x-1, y);
      weights[c]=2;
      c++;
    }
    values[c]=pointSample(img,x, y);
    weights[c]=4;
    c++;
    if(x<image_width-1) {
      values[c]=pointSample(img,x+1, y);
      weights[c]=2;
      c++;
    }

    if(y<image_height-1) {
      if(x>0) {
        values[c]=pointSample(img,x-1, y+1);
        weights[c]=1;
        c++;
      }
      values[c]=pointSample(img,x, y+1);
      weights[c]=2;
      c++;
 
      if(x<image_width-1) {
        values[c]=pointSample(img,x+1, y+1);
        weights[c]=1;
        c++;
      }
    }
   
    int value=0,j;
    int sum=0;
    for(j=0;j<c;++j) {
      value+=values[j]*weights[j];
      sum+=weights[j];
    }
   
    return value/sum;
  }

 
  protected float SX(float x) {
    return x*scale;
  }
  protected float SY(float y) {
    return y*scale;
  }
  protected float PX(float x) {
    return x-w2;
  }
  protected float PY(float y) {
    return h2-y;
  }
  protected float TX(float x) {
    return SX(PX(x));
  }
  protected float TY(float y) {
    return SY(PY(y));
  }
 
 
  protected void MoveTo(OutputStreamWriter out,float x,float y,boolean up) throws IOException {
    float x2 = TX(x);
    float y2 = TY(y);
   
    if(up==lastup) {
      previous_x=x2;
      previous_y=y2;
    } else {
      tool.WriteMoveTo(out,previous_x,previous_y);
      tool.WriteMoveTo(out,x2,y2);
      if(up) liftPen(out);
      else   lowerPen(out);
    }
  }
 
 
  protected double RoundOff(double value) {
    return Math.floor(value * 100.0) / 100.0;
  }

 
  public void TextSetPosition(float x,float y) {
    posx=x;
    posy=y;
  }
 
  public void TextSetAlign(Align x) {
    align_horizontal = x;
  }
 
  public void TextSetVAlign(VAlign x) {
    align_vertical = x;
  }
 
 
  public void TextSetCharsPerLine(int numChars) {
    chars_per_line = numChars;
    //System.out.println("MAX="+numChars);
  }
 
 
  public void TextFindCharsPerLine(float width) {
    chars_per_line=(int)Math.floor( (float)(width - padding*2.0f) / (float)(letter_width+kerning) );
    //System.out.println("MAX="+chars_per_line);
  }
 

  protected Rectangle2D TextCalculateBounds(String text) {
    String [] lines = TextWrapToLength(text);
    int len = TextLongestLine(lines);
   
    int num_lines = lines.length;
    float h = padding*2 + ( letter_height + line_spacing ) * num_lines;//- line_spacing; removed because of letters that hang below the line
    float w = padding*2 + ( letter_width + kerning ) * len - kerning;
    float xmax=0, xmin=0, ymax=0, ymin=0;
   
    switch(align_horizontal) {
    case LEFT:
      xmax=posx + w;
      xmin=posx;
      break;
    case CENTER:
      xmax = posx + w/2;
      xmin = posx - w/2;
      break;
    case RIGHT:
      xmax = posx;
      xmin = posx - w;
      break;
    }
   
    switch(align_vertical) {
    case BOTTOM:
      ymax=posy + h;
      ymin=posy;
      break;
    case MIDDLE:
      ymax = posy + h/2;
      ymin = posy - h/2;
      break;
    case TOP:
      ymax = posy;
      ymin = posy - h;
      break;
    }
    /*
    System.out.println(num_lines + " lines");
    System.out.println("longest "+len+" chars");
    System.out.println("x "+xmin+" to "+xmax);
    System.out.println("y "+ymin+" to "+ymax);
    */
    Rectangle2D r = new Rectangle2D.Float();
    r.setRect(xmin, ymin, xmax - xmin, ymax - ymin);
   
    return r;
  }

 
  protected void TextCreateMessageNow(String text,OutputStreamWriter output) throws IOException {
    if(chars_per_line<=0) return;

    MachineConfiguration mc = MachineConfiguration.getSingleton();
    tool = mc.GetCurrentTool();
   
    // find size of text block
    // TODO count newlines
    Rectangle2D r = TextCalculateBounds(text);

    output.write("G90;\n");
    liftPen(output);
   
    if(draw_bounding_box) {
      // draw bounding box
      output.write("G0 X"+TX((float)r.getMinX())+" Y"+TY((float)r.getMaxY())+";\n");
      lowerPen(output);
      output.write("G0 X"+TX((float)r.getMaxX())+" Y"+TY((float)r.getMaxY())+";\n");
      output.write("G0 X"+TX((float)r.getMaxX())+" Y"+TY((float)r.getMinY())+";\n");
      output.write("G0 X"+TX((float)r.getMinX())+" Y"+TY((float)r.getMinY())+";\n");
      output.write("G0 X"+TX((float)r.getMinX())+" Y"+TY((float)r.getMaxY())+";\n");
      liftPen(output);
    }
   
    // move to first line height
    // assumes we are still G90
    float message_start = TX((float)r.getMinX()) + SX(padding);
    float firstline = TY((float)r.getMinY()) - SY(padding + letter_height);
    float interline = -SY(letter_height + line_spacing);

    output.write("G0 X"+message_start+" Y"+firstline+";\n");
    output.write("G91;\n");

    // draw line of text
    String [] lines = TextWrapToLength(text);
    for(int i=0; i<lines.length; i++) {
      if(i>0) {
        // newline
        output.write("G0 Y"+interline+";\n");

        // carriage return
        output.write("G90;\n");
        output.write("G0 X"+message_start+";\n");
        output.write("G91;\n");
      }
     
      TextDrawLine(lines[i],output);
    }

    output.write("G90;\n");
    liftPen(output);
  }

 
  protected String [] TextWrapToLength(String src) {
    String [] test_lines = src.split("\n");
    int i,j;
   
    int num_lines = 0;
    for(i=0;i<test_lines.length;++i) {
      if( test_lines[i].length() > chars_per_line ) {
        int x = (int)Math.ceil( (double)test_lines[i].length() / (double)chars_per_line );
        num_lines += x; 
      } else {
        num_lines++;
      }
    }

    String [] lines = new String[num_lines];
    j=0;
    for(i=0;i<test_lines.length;++i) {
      if(test_lines[i].length() <= chars_per_line) {
        lines[j++] = test_lines[i];
      } else {
        String [] temp = test_lines[i].split("(?<=\\G.{"+chars_per_line+"})");
        for(int k=0;k<temp.length;++k) {
          lines[j++] = temp[k];
        }
      }
    }
   
    return lines;
  }
 
  protected int TextLongestLine(String [] lines) {
    int len=0;
    for(int i=0;i<lines.length;++i) {
      if(len < lines[i].length()) len = lines[i].length();
    }
   
    return len;
  }
 
   protected void TextDrawLine(String a1,OutputStreamWriter output) throws IOException {
    String ud = System.getProperty("user.dir") + "/" + alphabetFolder;
   
    //System.out.println(a1+" ("+a1.length()+")");
   
    int i=0;
    for(i=0;i<a1.length();++i) {
      char letter = a1.charAt(i);
     
      if(letter=='\n' || letter=='\r') continue;

      String name;

      // find the file that goes with this character
      // TODO load these from an XML description
      if('a'<= letter && letter <= 'z') {
        name="SMALL_" + Character.toUpperCase(letter);
      } else {
        switch(letter) {
        case ' ':  name="SPACE"break;
        case '!':  name="EXCLAMATION"break;
        case '"':  name="DOUBLEQ"break;
        case '$':  name="DOLLAR"break;
        case '#':  name="POUND"break;
        case '%':  name="PERCENT"break;
        case '&':  name="AMPERSAND"break;       
        case '\'':  name="SINGLEQ"break;
        case '(':  name="B1OPEN"break;
        case ')':  name="B1CLOSE"break;
        case '*':  name="ASTERIX"break;
        case '+':  name="PLUS"break;
        case ',':  name="COMMA"break;
        case '-':  name="HYPHEN"break;
        case '.':  name="PERIOD"break;
        case '/':  name="FSLASH"break;
        case ':':  name="COLON"break;
        case ';':  name="SEMICOLON"break;
        case '<':  name="GREATERTHAN"break;
        case '=':  name="EQUAL"break;
        case '>':  name="LESSTHAN"break;
        case '?':  name="QUESTION"break;
        case '@':  name="AT"break;
        case '[':  name="B2OPEN"break;
        case ']':  name="B2CLOSE"break;
        case '^':  name="CARET"break;
        case '_':  name="UNDERSCORE"break;
        case '`':  name="GRAVE"break;
        case '{':  name="B3OPEN"break;
        case '|':  name="BAR"break;
        case '}':  name="B3CLOSE"break;
        case '~':  name="TILDE"break;
        case '\\':  name="BSLASH"break;
        case '�':  name="SPACE"break;
        default: name=Character.toString(letter)break;
        }
      }
      String fn = ud + name  + ".NGC";
      //System.out.print(fn);
     
     
      if(new File(fn).isFile()) {
        if(i>0 && kerning!=0) {
          output.write("G0 X"+SX(kerning)+";\n");
        }
       
        // file found. copy/paste it into the temp file
        //System.out.println(" OK");
        BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(fn),"UTF-8"));

        String b;
            while ( (b = in.readLine()) != null ) {
              if(b.trim().length()==0) continue;
              if(b.equals("UP")) {
            output.write("G90;\n");
                liftPen(output);
            output.write("G91;\n");
              } else if(b.equals("DOWN")) {
            output.write("G90;\n");
            lowerPen(output);
            output.write("G91;\n");
              } else {
                StringTokenizer st = new StringTokenizer(b);
                String gap="";
                while (st.hasMoreTokens()) {
                  String c=st.nextToken();
                  if(c.startsWith("G")) {
                    output.write(gap+c);
                  } else if(c.startsWith("X")) {
                    // translate coordinates
                    float x = Float.parseFloat(c.substring(1))*10// cm to mm
                    output.write(gap+"X"+SX(x));
                  } else if(c.startsWith("Y")) {
                    // translate coordinates
                    float x = Float.parseFloat(c.substring(1))*10// cm to mm
                    output.write(gap+"Y"+SY(x));
                  } else {
                    output.write(gap+c);
                  }
                  gap=" ";
                }
                output.write(";\n");
              }
            }
      } else {
        // file not found
        System.out.print(fn);
        System.out.println(" NOK");
      }
    }
  }
 
  protected void SignName(OutputStreamWriter out) throws IOException {
    TextSetAlign(Align.RIGHT);
    TextSetVAlign(VAlign.BOTTOM);
    TextSetPosition(image_width, image_height);
    TextCreateMessageNow("Makelangelo #"+Long.toString(MachineConfiguration.getSingleton().GetUID()),out);
    //TextCreateMessageNow("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890<>,?/\"':;[]!@#$%^&*()_+-=\\|~`{}.",out);
  }
}

/**
* This file is part of DrawbotGUI.
*
* DrawbotGUI is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DrawbotGUI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
*/
TOP

Related Classes of Filters.Filter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.