Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

jsf - How to convert p:signature value to an image (or other serialised form)

I'm going to use the signature tag of PrimeFaces in my site, but I don't know how can I store in a form of an image in my database or if possible any other type.

I just want to display it later in a data table so the admin can manage and verify the authenticity of those signatures.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Just check the PrimeFaces showcase for p:signature. Signature values are bound to a string, so you can simply store a signature as a string in your database. Later you can simply show the signature using the stored string in combination with the readonly attribute set to true. This is exactly what is demonstrated in the showcase.

Your signature string value will look something like:

{"lines":[[[81,75],[81,78],[81,80],[81,84],[83,87],...]]}

If you really want to store it as an image instead of a string, you have a few options.

SVG

As the string basically is an JSON object with a "lines" array, which per line has the coordinates, you can simply transform it to a SVG. All you need to do is create some paths. A rough implementation:

public String toSvg(String signature, int width, int height) {
  List<String> paths = new ArrayList<>();
  try (JsonReader jsonReader = Json.createReader(new StringReader(signature))) {
    JsonObject jsonObject = jsonReader.readObject();
    JsonArray jsonArray = jsonObject.getJsonArray("lines");
    jsonArray.forEach(line -> paths.add(toSvgPath((JsonArray) line)));
  }
  StringBuilder sb = new StringBuilder();
  sb.append(String.format("<svg width="%d" height="%d" xmlns="http://www.w3.org/2000/svg">
", width, height));
  paths.forEach(sb::append);
  sb.append("</svg>");
  return sb.toString();
}


private String toSvgPath(JsonArray line) {
  StringBuilder sb = new StringBuilder("<path d="");
  for (int i = 0; i < line.size(); i++) {
    JsonArray coords = (JsonArray) line.getJsonArray(i);
    sb.append(String.format("%s%d %d ", (i == 0 ? "M" : "L"), coords.getInt(0), coords.getInt(1)));
  }
  sb.append("" stroke="black" fill="transparent"/>
");
  return sb.toString();
}

But, as the SVG can easily be created from the JSON object, you might just want to store the JSON object and create the SVG when you need to render the signature.

See also:

PNG

p:signature has a base64Value attribute which writes a PNG image as base64 encoded data to the provided property:

<p:signature id="signature"
             base64Value="#{myBean.signature}">

This will give you a URL which will look like:

data:image/png;base64,iVBORw0KGgoAAAANSU...

In your bean it's just a matter of getting the data from the URL:

private static final String URL_DATA_PNG_BASE64_PREFIX = "data:image/png;base64,";

..

String encoded = signatureUrl.substring(URL_DATA_PNG_BASE64_PREFIX.length());
byte[] decoded = Base64.getDecoder().decode(encoded);

You could optionally save it as a file:

Path path = Paths.get("path/to/your/image.png");
Files.write(path, decoded);

See also:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...