I have a problem with executing wbesciptr in alfresco. I don't know what is going on, but every time i run my webscript written in java I got 401 error code. I have simmilar webscript in javascript and it runs ok.
Address:
http://localhost:8080/proxy/alfresco/api/repository/person/my-captcha?type=validate&token=MILUR1445505693188&word=EWGVNB
Error log:
2015-10-23 09:32:35,030 INFO [web.site.EditionInterceptor] [http-bio-8080-exec-7] Unable to retrieve License information from Alfresco: 401
My bean in xml:
<bean id="webscript.pl.[...].ca.guest.my-captcha.get"
class="pl.[...].repo.web.scripts.ca.MyCaptcha"
parent="webscript">
</bean>
Properties in xml:
<webscript>
<shortname>My captcha</shortname>
<description>Get captcha</description>
<url>/api/ca/guest/my-captcha</url>
<format default="json"/>
<family>[...]</family>
<authentication runas="admin">none</authentication>
</webscript>
FTL:
{
"token": <#if token?exists>"${token}"<#else>null</#if>,
"response": <#if response?exists>"${response}"<#else>null</#if>,
"image": <#if image?exists>"${image}"<#else>null</#if>
}
and JAVA class:
public class MyCaptcha extends DeclarativeWebScript {
private static final Logger LOGGER = Logger.getLogger(MyCaptcha.class);
private static final String CAPTCHA_VALIDATE = "validate";
private static final String CAPTCHA_CREATE = "create";
private static final String PARAMETER_TYPE = "type";
private static final String PARAMETER_TOKEN = "token";
private static final String PARAMETER_WORD = "word";
private static final String PARAMETER_IMAGE = "image";
private static final String PARAMETER_RESPONSE = "response";
private static Map<String, String> TOKENCACHE = new HashMap<>();
#Override
protected Map<String, Object> executeImpl(WebScriptRequest req,
Status status, Cache cache) {
Map<String, Object> result;
String request = req.getParameter(PARAMETER_TYPE);
if (request != null && request.equals(CAPTCHA_CREATE)) {
result = createCaptcha();
return result;
} else if (request != null && request.equals(CAPTCHA_VALIDATE)) {
String token = req.getParameter(PARAMETER_TOKEN);
String word = req.getParameter(PARAMETER_WORD);
result = new HashMap<>();
result.put(PARAMETER_RESPONSE, token != null && word != null
&& TOKENCACHE.get(token).equalsIgnoreCase(word)
? "true"
: "false");
return result;
} else {
result = new HashMap<>();
result.put(PARAMETER_RESPONSE, "false");
return result;
}
}
public Map<String, Object> createCaptcha() {
int width = 150;
int height = 50;
BufferedImage bufferedImage = new BufferedImage(150, 50,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setFont(new Font("Georgia", Font.BOLD, 18));
RenderingHints renderingHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
renderingHints.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHints(renderingHints);
// drawing gradient
GradientPaint gp = new GradientPaint(0, 0, Color.lightGray, 0,
height / 1, Color.white, true);
g2d.setPaint(gp);
g2d.fillRect(0, 0, width, height);
// setting font's color
g2d.setColor(new Color(0, 0, 0));
// creating chain of random letters
char captchaWord[] = new char[6];
String captcha = "";
Random r = new Random();
for (int i = 0; i < 6; i++) {
captchaWord[i] = (char) (65 + Math.abs(r.nextInt()) % 24);
captcha += captchaWord[i];
}
// drawing chain of random letters on image
int x = 0;
for (int i = 0; i < captchaWord.length; i++) {
x += 10 + (Math.abs(r.nextInt()) % 15);
g2d.drawChars(captchaWord, i, 1, x + 5,
20 + Math.abs(r.nextInt()) % 20);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// OutputStream b64 = new Base64.OutputStream(baos);
Map<String, Object> result = new HashMap<>();
try {
ImageIO.write(bufferedImage, "png", baos);
byte[] bytes = baos.toByteArray();
String base64bytes = Base64.encodeBytes(bytes);
String src = "data:image/png;base64," + base64bytes;
String token = createToken(captcha);
result.put(PARAMETER_IMAGE, src); // b64.toString("UTF-8"));
result.put(PARAMETER_TOKEN, token);
TOKENCACHE.put(token, captcha);
return result;
} catch (IOException e) {
LOGGER.error("Exception : can't write image into base64 ::", e);
// ? e.printStackTrace();
result.put("error", "can't write image into base64");
return result;
}
}
// this function creates unique (hope so) token to recognize captcha
public String createToken(String captcha) {
StringBuffer token = new StringBuffer();
Date date = new Date();
Random r = new Random();
token.append((char) (65 + Math.abs(r.nextInt()) % 24))
.append((char) (65 + Math.abs(r.nextInt()) % 24))
.append((char) (65 + Math.abs(r.nextInt()) % 24))
.append((char) (65 + Math.abs(r.nextInt()) % 24))
.append((char) (65 + Math.abs(r.nextInt()) % 24))
.append(date.getTime());
return token.toString();
}
}
I solved it (fortunately). There was a problem with address. I were calling my webscript using proxy instead of direct connecting to one/service/.../my-captcha
Related
I have a tensorflow lite model which use,
input is {1,320,320,3}
output array dataType is {FLOAT32,FLOAT32,INT32}.
Interpreter#runForMultipleInputsOutputs crashed when resized the input to {1,224,320,3}.
My tensorflow lite version:
implementation('org.tensorflow:tensorflow-lite:0.0.0-nightly') { changing = true }
implementation('org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly') { changing = true }
implementation('org.tensorflow:tensorflow-lite-support:0.0.0-nightly') { changing = true }
Create the input tensor. Prepare the output tensor:
inputImageBuffer = new TensorImage(imageDataType);
outputArr = new TensorBuffer[tflite.getOutputTensorCount()];
resizeOutputArr = new TensorBuffer[tflite.getOutputTensorCount()];
for (int i = 0, count = tflite.getOutputTensorCount(); i < count; i++) {
DataType pDataType = tflite.getOutputTensor(i).dataType();
if (pDataType == DataType.INT32) pDataType = DataType.FLOAT32;
outputArr[i] = TensorBuffer.createFixedSize(i == 0 ? new int[]{imageSizeY, imageSizeX} : new int[]{imageSizeX}, pDataType);
resizeOutputArr[i] = TensorBuffer.createDynamic(pDataType);
}
Resize the input imagebuffer
// Loads bitmap into a TensorImage.
inputImageBuffer.load(bitmap);
float sc = bitmap.getWidth() / 320.0f;
int scaleWid = Math.round(bitmap.getWidth() / sc);
int scaleHei = Math.round(bitmap.getHeight() / sc);
imageSizeY = scaleHei / 32 * 32;
// Creates processor for the TensorImage.
int numRotation = sensorOrientation / 90;
this.processor =
new ImageProcessor.Builder()
.add(new ResizeOp(scaleHei, scaleWid, ResizeOp.ResizeMethod.NEAREST_NEIGHBOR))
.add(new ResizeWithCropOrPadOp(imageSizeY, imageSizeX))
.add(new Rot90Op(numRotation))
.add(new GrayOp(imageSizeY, imageSizeX))
.add(getPreprocessNormalizeOp())
.build();
processor.process(inputImageBuffer);
Run:
int imageTensorIndex = 0;
int[] imageShape = tflite.getInputTensor(imageTensorIndex).shape(); // {1, height, width, 3}
if (imageSizeY != imageShape[1] || imageShape[1] == 0) { // imageSizeY changed
tflite.resizeInput(imageTensorIndex, new int[]{1, imageSizeY, imageSizeX, 3}); //resize inputTensor
for (int i = 0, count = tflite.getOutputTensorCount(); i < count; i++) { //recreate outputTensor
DataType pDataType = tflite.getOutputTensor(i).dataType();
if (pDataType == DataType.INT32) pDataType = DataType.FLOAT32;
outputArr[i] = TensorBuffer.createFixedSize(i == 0 ? new int[]{imageSizeY, imageSizeX} : new int[]{imageSizeX}, pDataType);
}
}
Map<Integer, Object> outputMap = new HashMap<>();
for (int i = 0, cnt = outputArr.length; i < cnt; i++) { //rewind outputBuffer
outputMap.put(i, outputArr[i].getBuffer().rewind());
resizeOutputArr[i].getBuffer().rewind();
}
try {
tflite.runForMultipleInputsOutputs(new Object[]{inputImageBuffer.getBuffer()}, outputMap);
} catch (IllegalArgumentException e) {
e.printStackTrace();
return null;
}
for (int i = 0, count = tflite.getOutputTensorCount(); i < count; i++) { //resize outputArr with new shape
int[] shape = tflite.getOutputTensor(i).shape();
outputArr[i].getBuffer().limit(computeFlatSize(shape) * DataType.FLOAT32.byteSize());
resizeOutputArr[i].loadBuffer(outputArr[i].getBuffer(), shape);
outputArr[i].getBuffer().clear();
if (i == count - 1 && shape != null && shape[0] <= 0) return null;
}
return resizeOutputArr;
protected static int computeFlatSize(#NonNull int[] shape) {
SupportPreconditions.checkNotNull(shape, "Shape cannot be null.");
int prod = 1;
for (int i = 0; i < shape.length; ++i) {
prod *= shape[i];
}
return prod;
}
I got blew Exception when there is no recognized object in the Bitmap:
W: java.lang.IllegalArgumentException: Internal error: Tensor hasn't been allocated.
W: at org.tensorflow.lite.Tensor.buffer(Native Method)
W: at org.tensorflow.lite.Tensor.buffer(Tensor.java:493)
W: at org.tensorflow.lite.Tensor.copyTo(Tensor.java:264)
W: at org.tensorflow.lite.Tensor.copyTo(Tensor.java:254)
W: at org.tensorflow.lite.NativeInterpreterWrapper.run(NativeInterpreterWrapper.java:170)
W: at org.tensorflow.lite.Interpreter.runForMultipleInputsOutputs(Interpreter.java:343)
W: at com.fotric.irdetector.qf.tflite.Classifier.recognizeImage(Classifier.java:283)
This exception reduces the recognition performance, Someone help me, thanks!!!
This is the code for this issue for you to check if there is any problem in the code.
Now the problem is when I limit the rows to 45 (this number fits in one page) every row will print in one page.
But, If I don't limit the rows and the row size (approximately 100-200), every row goes to new page in the PDF. The PDF page number goes to approximately equal to row numbers.
I have opened this issue in Boxable's git but it's not active so I came for help here.
Following are the files generated in both conditions:
LimitTemp.pdf
noLimitTemp.pdf
public class CSVtoPDF {
private float marginBetweenYElements = 10;
private float titleFontSize = 18;
private float fontSize = 8;
private float headerFontSize = 12;
private float header1FontSize = 14;
private float header2FontSize = 12;
private float headerCellHeight = 19;
private float dataCellHeight = 12;
private PDFont font = PDType1Font.HELVETICA;
private PDFont headerFont = PDType1Font.TIMES_BOLD;
List filteredData = new ArrayList();
ReportSettings rs = new ReportSettings();
String filePath, destPath, header1, header2, filename;
public CSVtoPDF(List data, Audit audit) throws IOException {
this.filteredData = data;
Date liveDate = new Date();
SimpleDateFormat format= new SimpleDateFormat("YYYY-MM-DD HH:mm:ss");
liveDate = Calendar.getInstance().getTime();
float headerCellHeight = 18;
PDDocument doc = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
//page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(),
// PDRectangle.A4.getWidth()));
PDPageContentStream cos = new PDPageContentStream(doc, page);
/* Add page to PDDocument */
doc.addPage(page);
System.out.println("Inside Main csvtopdf");
//Draw Header
Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
try {
String[] keys = prefs.keys();
//destPath = prefs.get("destpath", rs.getDestPath());
//filename = prefs.get("file_name", rs.getFileName());
//header1 = prefs.get("header1", rs.getHeader1());
//header2 = prefs.get("header2", rs.getHeader2());
} catch (BackingStoreException ex) {
System.err.println(ex);
}
header1= "Header 1";
header2= "Header 2";
cos.beginText();
cos.moveTextPositionByAmount(220, 810);
cos.setFont(headerFont, header1FontSize);
cos.drawString(header1);
cos.endText();
cos.beginText();
cos.moveTextPositionByAmount(220, 800);
cos.setFont(headerFont, header2FontSize);
cos.drawString(header2);
cos.endText();
cos.beginText();
cos.moveTextPositionByAmount(220, 790);
cos.setFont(headerFont, headerFontSize);
cos.drawString("Report: Filtered Audit Report");
cos.endText();
//cos.beginText();
// cos.moveTo(200, 30);
//cos.setFont(headerFont, headerFontSize);
// cos.drawString(header2);
//cos.endText();
/* Initialize DataTable */
float margin = 20;
float tableWidth = page.getMediaBox().getWidth() - (2 * margin);
float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin);
float yStart = yStartNewPage;
float bottomMargin = -800;
BaseTable table = new BaseTable(yStart, yStartNewPage,
bottomMargin, tableWidth, margin, doc, page, true, true);
Row<PDPage> dataRow = table.createRow(dataCellHeight);
for (int i = 0; i < data.size() - 1; i++) {
System.out.println(data.get(i));
}
drawTableData(table, dataCellHeight, 20, data, 1,doc,page);
table.draw();
File result;
if (Objects.isNull(destPath)) {
cos.close();
result = new File("temp.pdf");
} else {
result = new File(destPath);
}
System.out.println("befor save result");
doc.save(result);
System.out.println("after save result");
}
public void drawTableData(BaseTable table, float dataCellHeight, float
cellWidth, List<Audit> data, int style,PDDocument doc,PDPage page) {
String s;
Cell<PDPage> cell;
// for (int k = 0; k < data.size(); k++) {
System.out.println("inside drawtable for ");
for (int i = 0; i < data.size(); i++) { // add row
System.out.println("inside drawtable for " + i);
Audit atmp = data.get(i);
//if (i==35) {
// doc.addPage(page);
//}
Row<PDPage> sTableRow = table.createRow(dataCellHeight);
for (int j = 0; j <= 2; j++) { //add cell in the rows
if (j == 0) { // normal cells on right
s = atmp.getTimeStamp();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
setStyle(style, cell);
//k++;
} else if (j == 1) { //big cells on left
s = atmp.getDiscription();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth + 50, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
setStyle(style, cell);
// k++;
} else if (j == 2) { //top blank cell
//System.out.println("In j null and 0 " + j);
s = atmp.getUserID();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth - 10, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
//cell.setBottomBorderStyle(null);
setStyle(style, cell);
//k++;
}
}
table.addHeaderRow(sTableRow);
System.out.println(" row added ");
}
//}
}
public void setStyle(int type, Cell cell) {
// type : 0 as header, 1 as table body
if (type == 0) {
cell.setFont(headerFont);
//cell.setHeight(headerCellHeight);
cell.setFontSize(headerFontSize);
cell.setBottomPadding(3);
} else if (type == 1) {
cell.setTopPadding(1);
cell.setFont(font);
cell.setAlign(HorizontalAlignment.LEFT);
//cell.setHeight(dataCellHeight);
cell.setFontSize(fontSize);
cell.setBottomPadding(1);
}
}
I found a silly problem in my code. I am telling this so that someone else must not repeat this.
I treated every row of the data table as header row. So it went to new page.
To be specific. In the function drawTableData I removed table.addHeaderRow(sTableRow)
I'm using Apache's PDFBox version 2.0.4 and am having a problem using lineTo and curveTo. My function takes parameters of radians, starting degrees and ending degrees and then uses lineTo and curveTo to generate a slice of a pie chart.
mContents.setNonStrokingColor(color);
mContents.moveTo(0, 0);
List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(endDeg));
mContents.lineTo(smallArc.get(0), smallArc.get(1));
mContents.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4), smallArc.get(5), smallArc.get(6), smallArc.get(7));
mContents.closePath();
mContents.fill();
The pie chart generates and appears to be fine. My app adds a footer which contains a logo that it reads from a file as follows:
try {
pdImage = PDImageXObject.createFromFile(mFullImagePath, mDoc);
}catch(IOException ie){System.out.println("Error opening image file - "+ie.getMessage());}
try {
mContents.drawImage(pdImage,250,5,pdImage.getWidth()/2,pdImage.getHeight()/2);
}catch(IOException e){System.out.println("Error adding image file - "+ e.getMessage());}
When the pi chart is included in the pdf generated, the footer and image are not in the pdf. Stubbing the code to generate the pie chart and the footer shows up with the image included.
Currently have to add the pie chart specifying specific coordinates after the page has been generated otherwise the additional lines below the pie chart do not appear.
Could the curveTo and lineTo generated output be bigger than what is displayed causing these issues?
EDIT - adding the image in the footer before drawing the graph and the image, graph and text all appear.
Appreciate any pointers
Complete code:
import com.google.code.geocoder.Geocoder;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.util.Matrix;
import org.apache.tomcat.jni.Address;
import org.slf4j.Logger;
import java.awt.*;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
/** * Created by tim on 7/6/2017. */
public class ReportDataPDFBox {
private PDDocument mDoc = null;
private PDPage mPage = null;
private PDImageXObject pdImage = null;
private PDFont mHeaderFont = PDType1Font.HELVETICA_BOLD;
private final int FONT_SIZE_HDR1 = 16;
private final int FONT_SIZE_HDR2 = 14;
private final int FONT_SIZE_REG = 12;
private final int HDR_INDENT = 30;
private final int BODY_INDENT_1 = 55;
private final int BODY_INDENT_2 = 65;
private final int BODY_INDENT_3 = 75;
private PDFont mRegFont = PDType1Font.HELVETICA;
PDPageContentStream mContents = null;
private String mReportName = null;
private String mFullImagePath = null;
private String mMonth = null;
private boolean mReportDone = true;
private int mHorizonVal = 700;
private int mHorizonGrph = 0;
private long[] mDayPercent;
private Calendar mCurrentCalendar = null;
ProcessFrequencyData pfd = null;
ProcessWeatherData pwd = null;
ProcessPerformanceData ppd = null;
Logger log = null;
Color[] mColor = {Color.PINK,Color.YELLOW,Color.CYAN, Color.BLUE,Color.RED,Color.GREEN,Color.ORANGE,Color.LIGHT_GRAY};
public ReportDataPDFBox(Logger logger, ProcessFrequencyData pfd, ProcessWeatherData pwd, ProcessPerformanceData ppd){
this.log = logger;
this.pfd = pfd;
this.pwd = pwd;
this.ppd = ppd;
initializeDoc();
}
public void initializeDoc(){
mDoc = new PDDocument();
mPage = new PDPage();
mDoc.addPage(mPage);
mFullImagePath = "logo.png";
mCurrentCalendar = Calendar.getInstance();
mMonth = mCurrentCalendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
mReportName = mMonth + ".pdf";
try{
mContents = new PDPageContentStream(mDoc, mPage);
}catch(IOException e){System.out.println("Error setting content stream - "+e.getLocalizedMessage());}
}
public boolean writeTheReport(){
addHeader();
addFooter();
generateReportContent();
// addFooter();
cleanUpALlDone();
return mReportDone;
}
private void addHeader(){
try {
mContents.beginText();
mContents.setFont(mHeaderFont,FONT_SIZE_HDR1);
mContents.newLineAtOffset(200, 740);
mContents.showText(mMonth + " - ActoTracker Report - " + mCurrentCalendar.get(Calendar.YEAR));
mContents.endText();
}catch (IOException io){System.out.println("Error with text content screen");}
}
private void generateReportContent(){
addNumberRunInfo();
addLocationRunInfo();
addWeekDayInfo();
addWeekInfo();
addFrequencyData();
pukeMeAChart();
// generateDailyChart();
}
private void addNumberRunInfo(){
int daysActive = Utility.getDaysBetweenDates(Utility.getOldestDate(pfd.getFirstDate(),
pwd.getFirstDate()), Calendar.getInstance().getTimeInMillis());
writeLine(mHeaderFont, FONT_SIZE_HDR2,HDR_INDENT, "Frequency Information");
long percentActiveIdle = (pfd.getTotalDaysRun()*100/daysActive);
String line = "Number of Runs - " + pfd.getTotalDaysRun() + " Number of days ActoTracker active - " + daysActive + " Percent run =
"+percentActiveIdle;
writeLine(mRegFont, FONT_SIZE_REG, BODY_INDENT_1, line);
}
private void addLocationRunInfo(){
String line = "Number of locations run = " + pfd.getLocationRun();
writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
for (int i=1; i<=pfd.getLocationRun();i++){
String[] locationInfo = pfd.getLocationInfo(i);
long percent = pfd.getRunsByLocation(i)*100/pfd.getTotalDaysRun();
String line2= new String( locationInfo[0] + " - " + locationInfo[1] +" , "+locationInfo[2]+ " Number of runs = " +
pfd.getRunsByLocation(i) + " Percent of runs = " +percent );
writeLine(mRegFont, FONT_SIZE_REG,BODY_INDENT_2,line2);
}
}
private void addWeekDayInfo(){
int totDaysRunning = pfd.getTotalRunDay();
int leastCnt = 0;
int mostCnt = 0;
mHorizonGrph = mHorizonVal - 90;
mDayPercent = new long[8];
String mostDay = " most common day";
String leastDay = " least common day";
DayFrequencyResults frequency = pfd.getDayDistribution();
int[] leastDays = frequency.getLessDays();
int[] mostDays = frequency.getMostDays();
StringBuilder leastString = new StringBuilder();
StringBuilder mostString = new StringBuilder();
for (int i=0; i< leastDays.length;i++){
if (leastDays[i] != 0) {
leastString.append(Utility.getDayName(leastDays[i])).append(" ");
leastCnt++;
}
}
for (int j=0; j< mostDays.length;j++){
if (mostDays[j] != 0) {
mostString.append(Utility.getDayName(j+1)).append(" ");
mostCnt++;
}
}
if (leastCnt > 1){leastDay += "s";}
if (mostCnt > 1) {mostDay +="s";}
String line = mostString.toString()+mostDay+ " to run"+ " "+leastString.toString()+leastDay+" to run";
writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
for (int i=1;i<8;i++){
String day = new String(Utility.getDayName(i)+" " + pfd.getRweekDayCount(i) + " runs "+"
"+pfd.getRweekDayCount(i)*100/totDaysRunning)+ "%";
writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_2,day);
double x = pfd.getRweekDayCount(i) / (double)pfd.getTotalDaysRun();
mDayPercent[i] = Math.round(360*x);
}
System.out.println("BreakPoint");
}
private void addWeekInfo(){
String line;
Integer[] largestWeekTotals = {0,0,0,0,0,0,0};
double largestDistance = 0D;
double firstHalfDist = 0D;
double secondHalfDist = 0D;
DecimalFormat df = new DecimalFormat("####.##");
int[] distFreq = pfd.getMonthlySummaryInfo();
if (distFreq[0] > distFreq[1]){
line = "Ran more in first half of months run. "+ distFreq[0] + " times versus "+ distFreq[1]+" times";
}else{
line = "Ran more in second half of months run. " + distFreq[1] + " times versus " + distFreq[0]+" times";
}
writeLine(mRegFont,FONT_SIZE_REG, BODY_INDENT_1, line);
for (int i = 1; i<7;i++){
if (i<4){
firstHalfDist += Utility.getMileage(pfd.fa.getWeekDistanceTotal(i),false);
}else{
secondHalfDist += Utility.getMileage(pfd.fa.getWeekDistanceTotal(i),false);
}
}
if (firstHalfDist > secondHalfDist){
line = new String ("Ran further in the first half of the month " + df.format(firstHalfDist) + " miles versus " +
df.format(secondHalfDist) + " miles");
}else{
line = new String ("Ran further in the second half of the month " + df.format(secondHalfDist) + " miles versus " +
df.format(firstHalfDist)+ " miles");
}
writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1, line);
}
private void addFrequencyData(){
int greatestFreq = 0;
int leastDiff = 0;
int greatestDiff = 0;
int leastFreq = 0;
for (int i=0; i<30; i++){
int cnt = ppd.getRunsByFrequentcy(i);
if (cnt > greatestFreq){
greatestFreq = cnt;
greatestDiff = i;
}
else{
if (cnt > 0 && i>leastDiff){
leastDiff = i;
leastFreq = cnt;
}
}
log.info("Frequency?? = " + cnt + " index = "+i);
}
String line = greatestDiff + " days is the most common frequency between runs "+greatestFreq+" times";
writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
String line2 = leastDiff + " days longest time between runs " + leastFreq + " times";
writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line2);
}
private void writeLine(PDFont font, int fontSize, int indent, String text){
mHorizonVal -= 20;
try {
mContents.beginText();
mContents.setFont(font, fontSize);
mContents.newLineAtOffset(indent,mHorizonVal);
mContents.showText(text);
mContents.endText();
}catch(IOException e){}
}
private void addFooter(){
log.info("IN addFooter");
mPage = new PDPage();
mDoc.addPage(mPage);
try {
pdImage = PDImageXObject.createFromFile(mFullImagePath, mDoc);
}catch(IOException ie){System.out.println("Error opening image file - "+ie.getMessage());}
try {
mContents.drawImage(pdImage,250,5,pdImage.getWidth()/2,pdImage.getHeight()/2);
}catch(IOException e){log.error("Error adding image file - "+ e.getLocalizedMessage());}
}
private void cleanUpALlDone(){
try {
mContents.close();
mDoc.save(mReportName);
mDoc.close();
}catch (IOException ie){System.out.println("Error closing PDF document - " + ie.getMessage());}
}
private void generateDailyChart(){
int totalVal = 0;
try {
mContents.transform(Matrix.getTranslateInstance(375, 525));
}catch(IOException e){}
for (int i=1; i< 8;i++){
totalVal += mDayPercent[i];
writeTheChart(mDayPercent[i-1], totalVal,mColor[i]);
log.info("Color selected = " +mColor[i] +"Index = "+i);
}
}
private void writeTheChart(long beg, long end, Color color){
try {
log.info("Color received = " + color);
drawSlice(color, 60,beg, end);
}catch(IOException e){}
}
private void pukeMeAChart(){
try {
mContents.transform(Matrix.getTranslateInstance(375,525));
drawSlice(Color.YELLOW, 60, 0, 69);
mContents.fill();
drawSlice(Color.BLUE, 60, 69, 117);
drawSlice(Color.RED, 60, 117, 181);
mContents.fill();
drawSlice(Color.WHITE, 60, 181, 208);
mContents.fill();
drawSlice(Color.GREEN, 60, 208, 272);
mContents.fill();
drawSlice(Color.YELLOW, 60, 272, 336);
drawSlice(Color.BLUE, 60, 336, 360);
mContents.fill();
} catch(IOException e ){}
}
private void drawSlice(Color color, float rad, float startDeg, float endDeg) throws IOException
{
mContents.setNonStrokingColor(color);
mContents.moveTo(0, 0);
List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(endDeg));
mContents.lineTo(smallArc.get(0), smallArc.get(1));
mContents.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4), smallArc.get(5), smallArc.get(6), smallArc.get(7));
mContents.closePath();
mContents.fill();
}
private List<Float> createSmallArc(double r, double a1, double a2)
{
// Compute all four points for an arc that subtends the same total angle
// but is centered on the X-axis
double a = (a2 - a1) / 2;
double x4 = r * Math.cos(a);
double y4 = r * Math.sin(a);
double x1 = x4;
double y1 = -y4;
double q1 = x1*x1 + y1*y1;
double q2 = q1 + x1*x4 + y1*y4;
double k2 = 4/3d * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
double x2 = x1 - k2 * y1;
double y2 = y1 + k2 * x1;
double x3 = x2;
double y3 = -y2;
// Find the arc points' actual locations by computing x1,y1 and x4,y4
// and rotating the control points by a + a1
double ar = a + a1;
double cos_ar = Math.cos(ar);
double sin_ar = Math.sin(ar);
List<Float> list = new ArrayList<Float>();
list.add((float) (r * Math.cos(a1)));
list.add((float) (r * Math.sin(a1)));
list.add((float) (x2 * cos_ar - y2 * sin_ar));
list.add((float) (x2 * sin_ar + y2 * cos_ar));
list.add((float) (x3 * cos_ar - y3 * sin_ar));
list.add((float) (x3 * sin_ar + y3 * cos_ar));
list.add((float) (r * Math.cos(a2)));
list.add((float) (r * Math.sin(a2)));
return list;
}
}
In contrast to your assumption, you are not having a problem using lineTo and curveTo, i.e. your method drawSlice. You are having problems in the code using that method, i.e. here:
private void pukeMeAChart(){
try {
mContents.transform(Matrix.getTranslateInstance(375,525));
drawSlice(Color.YELLOW, 60, 0, 69);
mContents.fill();
drawSlice(Color.BLUE, 60, 69, 117);
drawSlice(Color.RED, 60, 117, 181);
mContents.fill();
drawSlice(Color.WHITE, 60, 181, 208);
mContents.fill();
drawSlice(Color.GREEN, 60, 208, 272);
mContents.fill();
drawSlice(Color.YELLOW, 60, 272, 336);
drawSlice(Color.BLUE, 60, 336, 360);
mContents.fill();
} catch(IOException e ){}
}
This method starts by translating the coordinate system
mContents.transform(Matrix.getTranslateInstance(375,525));
and does not undo that translation when it is finished. Thus, the footer and image are in the pdf, merely not where you would expect them but instead translated, probably outside the crop box.
To undo the translation (and other changes, too, like the fill color), simply store the graphics state at the start of pukeMeAChart and restore it at the end of it.
Furthermore, drawSlice fills the slice itself, so there is no path to fill in pukeMeAChart anymore. Thus, the fill calls there are invalid.
All changes applied:
private void pukeMeAChart(){
try {
mContents.saveGraphicsState();
mContents.transform(Matrix.getTranslateInstance(375,525));
drawSlice(Color.YELLOW, 60, 0, 69);
drawSlice(Color.BLUE, 60, 69, 117);
drawSlice(Color.RED, 60, 117, 181);
drawSlice(Color.WHITE, 60, 181, 208);
drawSlice(Color.GREEN, 60, 208, 272);
drawSlice(Color.YELLOW, 60, 272, 336);
drawSlice(Color.BLUE, 60, 336, 360);
mContents.restoreGraphicsState();
} catch(IOException e ){}
}
generateDailyChart(), another method (indirectly) using the drawSlice method, also has the graphics state issue and has to be fixed similarly:
private void generateDailyChart(){
mContents.saveGraphicsState();
int totalVal = 0;
try {
mContents.transform(Matrix.getTranslateInstance(375, 525));
}catch(IOException e){}
for (int i=1; i< 8;i++){
totalVal += mDayPercent[i];
writeTheChart(mDayPercent[i-1], totalVal,mColor[i]);
log.info("Color selected = " +mColor[i] +"Index = "+i);
}
mContents.restoreGraphicsState();
}
As it currently is commented out and, therefore, not used, this problem does not show yet, though.
I am trying to create an image with a given text and style. eg;
" textStyle(Offer ends 25/12/2016. Exclusions Apply., disclaimer) textStyle(See Details,underline) "
In above line i am splitting and creating a map that stores the first parameter of textStyle block as key and second parameter as value where second param defines the style to be applied on first param. Hence an entry of map will look like .
Now when i iterate over this map to write the text to image i check if the text is overflowing the width. If yes then it breaks the text and adds it to next line in the horizontal center. So for example lets say i am trying to write "Offer ends 25/12/2016. Exclusions Apply." with Arial and font size 12. While writing i find that i can write till "Offer ends 23/12/2016. " only and "Exclusions apply" has to go in next line. But it writes the text in horizontal center neglecting that as there is space left horizontally i can write "See Details" too in the same line.
Please help. Below is the code what i have tried. I have also tried creating a JTextPane and then converting it to image but this cannot be an option as it first creates the frame, makes it visible, writes it and then disposes it. And most of the times i was getting Nullpointer exception on SwingUtilities.invokeAndWait.
Actual : http://imgur.com/7aIlcEQ
Expected http://imgur.com/038zQTZ
public static BufferedImage getTextImage(String textWithoutStyle, Map<String, String> textToThemeMap, Properties prop, int height, int width) {
BufferedImage img = new BufferedImage(width,height,BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2d = img.createGraphics();
g2d.setPaint(Color.WHITE);
FontMetrics fm = g2d.getFontMetrics();
Map<String, Font> textToFontMap = new LinkedHashMap<String, Font>();
for(Map.Entry<String, String> entry : textToThemeMap.entrySet()) {
if(StringUtils.isNotBlank(entry.getKey()) && StringUtils.isNotBlank(entry.getValue())) {
Font font = getFont(prop, entry.getValue().trim());
g2d.setFont(font);
fm = g2d.getFontMetrics();
String string = entry.getKey();
char[] chars = null;
int i = 0, pixelWidth = 0;
List<String> newTextList = new ArrayList<String>();
if(fm.stringWidth(string) > (width - 10)) {
chars = string.toCharArray();
for (i = 0; i < chars.length; i++) {
pixelWidth = pixelWidth + fm.charWidth(chars[i]);
if(pixelWidth >= (width - 10)) {
break;
}
}
String newString = WordUtils.wrap(string, i, "\n",false);
String[] splitString = newString.split("\n");
for(String str : splitString) {
newTextList.add(str);
textToFontMap.put(string, font);
}
} else {
newTextList.add(string);
textToFontMap.put(string, font);
}
}
}
Font font = new Font("Arial", Font.BOLD, 14);
int spaceOfLineHeight = (textToFontMap.size() - 1) * 7;
int spaceOfText = textToFontMap.size() * font.getSize();
int totalSpace = spaceOfLineHeight + spaceOfText ;
int marginRemaining = height - totalSpace;
int tempHt = marginRemaining / 2 + 10;
String txt = null;
for(Map.Entry<String, Font> entry : textToFontMap.entrySet()) {
txt = entry.getKey();
font = entry.getValue();
g2d.setFont(font);
fm = g2d.getFontMetrics();
int x = (width - fm.stringWidth(txt)) / 2;
int y = tempHt;
g2d.drawString(txt, x, y);
tempHt = tempHt + fm.getHeight();
}
// g2d.drawString(text.getIterator(), 0, (int)lm.getAscent() + lm.getHeight());
// g2d.dispose();
return img;
}
// Code with JTextPane ------------------------------------------
public static BufferedImage getTextImage(final Map < String, String > textToThemeMap, final Properties prop, final int height, final int width) throws Exception {
JFrame f = new JFrame();
f.setSize(width, height);
final StyleContext sc = new StyleContext();
DefaultStyledDocument doc = new DefaultStyledDocument(sc);
final JTextPane pane = new JTextPane(doc);
pane.setSize(width, height);
// Build the styles
final Paragraph[] content = new Paragraph[1];
Run[] runArray = new Run[textToThemeMap.size()];
int i = 0;
for (Map.Entry < String, String > entry: textToThemeMap.entrySet()) {
if (StringUtils.isNotBlank(entry.getValue().trim()) && StringUtils.isNotBlank(entry.getKey().trim())) {
Run run = new Run(entry.getValue().trim(), entry.getKey());
runArray[i++] = run;
}
}
content[0] = new Paragraph(null, runArray);
/*createDocumentStyles(sc, prop,textToThemeMap.values());
addText(pane, sc, sc.getStyle("default"), content);
pane.setEditable(false);*/
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
createDocumentStyles(sc, prop, textToThemeMap.values());
} catch (MalformedURLException e) {
//e.printStackTrace();
}
addText(pane, sc, sc.getStyle("default"), content);
pane.setEditable(false);
}
});
} catch (Exception e) {
System.out.println("Exception when constructing document: " + e);
}
f.getContentPane().add(pane);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D gd = img.createGraphics();
f.paint(gd);
f.dispose();
/*ImageIO.write(img, "png", new File("C:\\Users\\spande0\\Desktop\\a.png"));
System.out.println("done");*/
return img;
}
I suspect the issue is in your 'Y' computation.
int spaceOfLineHeight = (newTextList.size() - 1) * 7;
int spaceOfText = newTextList.size() * font.getSize();
int totalSpace = spaceOfLineHeight + spaceOfText;
int marginRemaining = height - totalSpace;
int tempHt = marginRemaining / 2 + 10;
You have to keep the height occupied by the previous lines, and add it to the current 'Y'.
At the moment, for all the lines, the 'Y' values is same.
Declare prevHeight outside the for loop. and then do the following.
int tempHt = marginRemaining / 2 + 10;
tempHT += prevHeight;
prevHeight = tempHeight
Based on the comments, I will suggest you to break down your function into two smaller functions.
// Loop through the strings and find out how lines are split and calculate the X, Y
// This function will give the expected lines
splitLinesAndComputeResult
// Just render the lines
renderLines
I'm trying to print the same that I have in my applet GUI.
The things it's that when I print it it's not exactly the same... the size of each component changes in a disproportionately way.
The GUI:
Printed:
The margins are not a problem, I can fix them easily... but as you can see the barcode and the vertical text has not the proper size.
Main class:
public class Impresion extends Applet{
PrinterJob job = PrinterJob.getPrinterJob();
Panel test;
Label test2;
Label test3;
String copyParam = null;
String dialogParam = null;
String codeParam = null;
String descParam = null;
public void init(){
copyParam = this.getParameter("copias");
dialogParam = this.getParameter("ventanita");
codeParam = this.getParameter("codigo");
descParam = this.getParameter("descripcion");
copyParam = "1";
dialogParam = "1";
codeParam = "002/113";
descParam = "asd";
if (copyParam == null || dialogParam == null || codeParam == null || descParam == null){
System.out.println("Faltan parametros. - "+copyParam+" - "+dialogParam+" - "+codeParam+" - "+descParam);
} else {
job.setPrintable(new Dibujar(codeParam, descParam));
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
float leftMargin = (float) 0.1;
float topMargin = (float) 0.1;
float rightMargin = (float) 0.1;
float bottomMargin = (float) 0.1;
float mediaWidth = (float) 60.0;
float mediaHeight = (float) 50.0;
aset.add(new MediaPrintableArea(leftMargin, topMargin, (mediaWidth - leftMargin - rightMargin), (mediaHeight - topMargin - bottomMargin), Size2DSyntax.MM));
int copias = Integer.parseInt(copyParam);
aset.add(new Copies(copias));
boolean imprimir = true;
if (dialogParam.indexOf('1') != -1){
imprimir = job.printDialog(aset);
}
if (imprimir){
try {
job.print(aset);
} catch (PrinterException e) {
e.printStackTrace();
}
}
}
}
}
Printable class:
public class Dibujar implements Printable{
String codeParam = null;
String descParam = null;
public Dibujar(String code, String desc) {
codeParam = code;
descParam = desc;
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException{
if (pageIndex > 0){
return NO_SUCH_PAGE;
}
Barcode b = null;
try {
b = BarcodeFactory.createCodabar(codeParam);
b.setDrawingText(false);
b.setBarWidth(1);
b.draw((Graphics2D) g, 30, 8);
} catch (BarcodeException | OutputException e1) {
e1.printStackTrace();
}
g.setFont(new Font("Arial", Font.BOLD, 9));
String description = descParam;
g.drawString(description, 16, 70);
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(90),16,8);
Graphics2D g2 = (Graphics2D) g;
g2.transform(at);
g.setFont(new Font("Arial", Font.BOLD, 14));
g2.drawString(codeParam.replace("/", ""),16,8);
g2.transform(new AffineTransform());
return PAGE_EXISTS;
}
}
Adjust the parameters in this:
aset.add(new MediaPrintableArea(leftMargin, topMargin, (mediaWidth - leftMargin - rightMargin), (mediaHeight - topMargin - bottomMargin), Size2DSyntax.MM));
Or adjust the parameters in these two:
b.draw((Graphics2D) g, 30, 8);
//....
g2.drawString(codeParam.replace("/", ""),16,8);