Skip to content

Commit 797d3b7

Browse files
committed
Compositing Post card working
1 parent 0cf521f commit 797d3b7

File tree

10 files changed

+374
-245
lines changed

10 files changed

+374
-245
lines changed

tweetprint/src/main/java/org/riskfirst/tweetprint/TweetPrintConfig.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
import org.kite9.diagram.logging.Kite9Log;
66
import org.kite9.diagram.logging.Kite9LogImpl;
77
import org.riskfirst.tweetprint.auth.UserPreferencesService;
8+
import org.riskfirst.tweetprint.image.ADLTweetBuilder;
9+
import org.riskfirst.tweetprint.image.EmojiToMarkupParser;
10+
import org.riskfirst.tweetprint.image.ImageBuilder;
11+
import org.riskfirst.tweetprint.image.Kite9ImageBuilder;
812
import org.riskfirst.tweetprint.rewardful.RewardfulService;
913
import org.springframework.beans.factory.InitializingBean;
1014
import org.springframework.beans.factory.annotation.Value;
@@ -51,4 +55,17 @@ public TwitterClient tweetPrintClient(
5155
.apiSecretKey(consumerSecret).build());
5256
}
5357

58+
@Bean
59+
public ADLTweetBuilder adlTweetBuilder() {
60+
return new ADLTweetBuilder();
61+
}
62+
63+
@Bean
64+
public ImageBuilder imageBuilder(
65+
TwitterClient tc,
66+
ADLTweetBuilder tb,
67+
@Value("${tweetprint.base-url}") String baseUrl) {
68+
return new Kite9ImageBuilder(tc, tb, baseUrl);
69+
70+
}
5471
}
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
package org.riskfirst.tweetprint.builder;
22

3+
import static org.riskfirst.tweetprint.builder.compositing.CompositeFunction.POSTCARD_CF;
4+
5+
import org.riskfirst.tweetprint.builder.compositing.CompositeFunction;
6+
37
public enum CardType {
48

59

6-
POSTCARD("CLASSIC-POST-GLOS-6X4", 6f/4f, "noun-postcard-1130482.svg", "Post Card", 3588 / 2, 1287),
7-
GREETINGSCARD("GLOBAL-GRE-MOH-7X5-DIR", 6f/5f, "noun-greeting-card-4384989.svg", "Greetings Card", 6118, 2161);
10+
POSTCARD("CLASSIC-POST-GLOS-6X4", 6f/4f, "noun-postcard-1130482.svg", "Post Card", 3588 / 2, 1287, POSTCARD_CF),
11+
GREETINGSCARD("GLOBAL-GRE-MOH-7X5-DIR", 7f/5f, "noun-greeting-card-4384989.svg", "Greetings Card", 2161, 6118/4, null);
812

913
public final String sku;
1014
public final float ratio;
1115
public final String image;
1216
public final String text;
1317
public final float width;
1418
public final float height;
19+
public final CompositeFunction cf;
1520

16-
private CardType(String sku, float ratio, String image, String text, float width, float height) {
21+
private CardType(String sku, float ratio, String image, String text, float width, float height, CompositeFunction cf) {
1722
this.sku = sku;
1823
this.ratio = ratio;
1924
this.image = image;
2025
this.text = text;
2126
this.width = width;
2227
this.height = height;
28+
this.cf = cf;
2329
}
30+
31+
32+
2433
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package org.riskfirst.tweetprint.builder.compositing;
2+
3+
import java.awt.Color;
4+
import java.awt.Graphics2D;
5+
import java.awt.geom.AffineTransform;
6+
import java.awt.image.AffineTransformOp;
7+
import java.awt.image.BufferedImage;
8+
import java.awt.image.BufferedImageOp;
9+
import java.awt.image.RenderedImage;
10+
import java.io.ByteArrayInputStream;
11+
12+
import javax.imageio.ImageIO;
13+
14+
import org.riskfirst.tweetprint.builder.Arrangement;
15+
import org.riskfirst.tweetprint.builder.CardType;
16+
import org.riskfirst.tweetprint.builder.OrderDetails;
17+
import org.riskfirst.tweetprint.image.ImageBuilder;
18+
19+
@FunctionalInterface
20+
public interface CompositeFunction {
21+
22+
public RenderedImage performCompositing(OrderDetails od, ImageBuilder ib);
23+
24+
public static CompositeFunction POSTCARD_CF = (od, ib) -> {
25+
try {
26+
float panelWidth = CardType.POSTCARD.width;
27+
float panelHeight = CardType.POSTCARD.height;
28+
29+
BufferedImage out = new BufferedImage((int) (panelWidth * 2), (int) (panelHeight), BufferedImage.TYPE_INT_RGB);
30+
31+
float width , height;
32+
if (od.arrangement == Arrangement.PORTRAIT) {
33+
width = panelHeight;
34+
height = panelWidth;
35+
} else {
36+
width = panelWidth;
37+
height = panelHeight;
38+
}
39+
40+
byte[] tweetImageBytes = ib.produceTweetImage(od, width, height);
41+
byte[] messageImageBytes = ib.produceMessageImage(od, panelWidth, panelHeight);
42+
43+
BufferedImage tweetImage = ImageIO.read(new ByteArrayInputStream(tweetImageBytes));
44+
BufferedImage messageImage = ImageIO.read(new ByteArrayInputStream(messageImageBytes));
45+
46+
Graphics2D g2 = (Graphics2D) out.getGraphics();
47+
g2.setBackground(Color.WHITE);
48+
g2.fillRect(0, 0, out.getWidth(), out.getHeight());
49+
g2.drawImage(messageImage, 0, 0, null);
50+
BufferedImageOp op = getOp(od.arrangement, tweetImage);
51+
g2.drawImage(tweetImage, op, (int) panelWidth, 0);
52+
53+
return out;
54+
55+
} catch (Exception e) {
56+
throw new RuntimeException("Couldn't produce composite image", e);
57+
}
58+
};
59+
60+
public static BufferedImageOp getOp(Arrangement arrangement, BufferedImage originalImage) {
61+
if (arrangement == Arrangement.PORTRAIT) {
62+
AffineTransform tx = new AffineTransform();
63+
64+
// last, width = height and height = width :)
65+
tx.translate(originalImage.getHeight() / 2,originalImage.getWidth() / 2);
66+
tx.rotate(Math.PI / 2);
67+
// first - center image at the origin so rotate works OK
68+
tx.translate(-originalImage.getWidth() / 2,-originalImage.getHeight() / 2);
69+
70+
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
71+
return op;
72+
} else {
73+
return null;
74+
}
75+
}
76+
77+
}

tweetprint/src/main/java/org/riskfirst/tweetprint/image/ADLTweetBuilder.java

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.text.DecimalFormat;
1212
import java.time.LocalDateTime;
1313
import java.time.format.DateTimeFormatter;
14-
import java.util.Iterator;
1514
import java.util.List;
1615
import java.util.stream.IntStream;
1716

@@ -45,45 +44,53 @@ private static double round(double value, int precision) {
4544
return (double) Math.round(value * scale) / scale;
4645
}
4746

48-
public Document convertMessageToAdl(String message, String address, Font f, CardType ct) throws Exception {
49-
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
50-
Document d = db.newDocument();
51-
Element diagram = d.createElementNS(ADL_NAMESPACE, "diagram");
52-
diagram.setAttributeNS(XSL_TEMPLATE_NAMESPACE, "xslt:template", "/public/templates/tweet/tweet-template.xsl");
53-
54-
Element frame = d.createElementNS(ADL_NAMESPACE, ct.name().toLowerCase());
55-
diagram.appendChild(frame);
47+
public Document convertMessageToAdl(String message, String address, Font f, CardType ct) throws RuntimeException {
48+
try {
49+
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
50+
Document d = db.newDocument();
51+
Element diagram = d.createElementNS(ADL_NAMESPACE, "diagram");
52+
diagram.setAttributeNS(XSL_TEMPLATE_NAMESPACE, "xslt:template", "/public/templates/tweet/tweet-template.xsl");
53+
54+
Element frame = d.createElementNS(ADL_NAMESPACE, ct.name().toLowerCase());
55+
diagram.appendChild(frame);
5656

57-
Element messageElement = convertEmojis(frame, "message", message);
58-
messageElement.setAttribute("style","font-family: "+f.text);
59-
60-
if (ct == CardType.POSTCARD) {
61-
convertEmojis(frame, "address", address);
62-
}
63-
64-
d.appendChild(diagram);
57+
Element messageElement = convertEmojis(frame, "message", message);
58+
messageElement.setAttribute("style","font-family: "+f.text);
59+
60+
if (ct == CardType.POSTCARD) {
61+
convertEmojis(frame, "address", address);
62+
}
63+
64+
d.appendChild(diagram);
6565

66-
67-
return d;
66+
67+
return d;
68+
} catch (Exception e) {
69+
throw new RuntimeException("Couldn't create XML Representation of Message", e);
70+
}
6871
}
6972

70-
public Document convertTweetsToAdl(List<Tweet> tweets) throws Exception {
71-
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
72-
Document d = db.newDocument();
73-
Element diagram = d.createElementNS(ADL_NAMESPACE, "diagram");
74-
diagram.setAttributeNS(XSL_TEMPLATE_NAMESPACE, "xslt:template", "/public/templates/tweet/tweet-template.xsl");
75-
diagram.setAttributeNS(Kite9Namespaces.SVG_NAMESPACE, "svg:version", "1.0");
76-
77-
Element frame = d.createElementNS(ADL_NAMESPACE, "frame");
78-
diagram.appendChild(frame);
79-
80-
IntStream.range(0, tweets.size())
81-
.mapToObj(i -> convertTweet(tweets.get(i), i == tweets.size() - 1, d))
82-
.forEach(t -> frame.appendChild(t));
83-
84-
d.appendChild(diagram);
85-
86-
return d;
73+
public Document convertTweetsToAdl(List<Tweet> tweets) throws RuntimeException {
74+
try {
75+
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
76+
Document d = db.newDocument();
77+
Element diagram = d.createElementNS(ADL_NAMESPACE, "diagram");
78+
diagram.setAttributeNS(XSL_TEMPLATE_NAMESPACE, "xslt:template", "/public/templates/tweet/tweet-template.xsl");
79+
diagram.setAttributeNS(Kite9Namespaces.SVG_NAMESPACE, "svg:version", "1.0");
80+
81+
Element frame = d.createElementNS(ADL_NAMESPACE, "frame");
82+
diagram.appendChild(frame);
83+
84+
IntStream.range(0, tweets.size())
85+
.mapToObj(i -> convertTweet(tweets.get(i), i == tweets.size() - 1, d))
86+
.forEach(t -> frame.appendChild(t));
87+
88+
d.appendChild(diagram);
89+
90+
return d;
91+
} catch (Exception e) {
92+
throw new RuntimeException("Couldn't create XML Representation of Tweet", e);
93+
}
8794
}
8895

8996
private Element convertTweet(Tweet status, boolean isLast, Document d) {
@@ -144,7 +151,7 @@ private void removeText(Node n, String key) {
144151
}
145152

146153
private void addEntities(Tweet status, Document d, Element tweet, Element textarea) {
147-
if (status.getEntities() != null) {
154+
if ((status.getEntities() != null) && (status.getEntities().getUrls() != null)) {
148155
for (UrlEntity me : status.getEntities().getUrls()) {
149156
UrlEntityV2 mev2 = (UrlEntityV2) me;
150157

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.riskfirst.tweetprint.image;
2+
3+
import org.riskfirst.tweetprint.builder.OrderDetails;
4+
5+
public interface ImageBuilder {
6+
7+
public byte[] produceTweetImage(OrderDetails od, float widthPx, float heightPx) throws RuntimeException;
8+
9+
public byte[] produceMessageImage(OrderDetails od, float widthPx, float heightPx) throws RuntimeException;
10+
11+
}

0 commit comments

Comments
 (0)