1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.mediaeditor.field.image;
35
36 import info.magnolia.ui.mediaeditor.action.feature.Scalable;
37 import info.magnolia.ui.mediaeditor.field.MediaField;
38
39 import java.awt.image.BufferedImage;
40 import java.io.ByteArrayInputStream;
41 import java.io.ByteArrayOutputStream;
42 import java.io.IOException;
43 import java.io.InputStream;
44 import java.util.Iterator;
45
46 import javax.imageio.ImageIO;
47
48 import org.apache.commons.io.IOUtils;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import com.vaadin.server.StreamResource;
53 import com.vaadin.server.StreamResource.StreamSource;
54 import com.vaadin.ui.Alignment;
55 import com.vaadin.ui.Component;
56 import com.vaadin.ui.CustomField;
57 import com.vaadin.ui.HasComponents;
58 import com.vaadin.ui.Image;
59 import com.vaadin.ui.VerticalLayout;
60
61
62
63
64 public abstract class ImageMediaField extends CustomField<byte[]> implements MediaField, Scalable {
65 private static final Logger log = LoggerFactory.getLogger(ImageMediaField.class);
66
67 protected final static String DEFAULT_FORMAT = "png";
68
69 protected final static String TEMP_FILE_NAME_BASE = "image_media_editor";
70
71 private Component fieldComponent;
72 private byte[] value;
73
74 @Override
75 protected Component initContent() {
76 addStyleName("image-media-field");
77 setSizeFull();
78 VerticalLayout mediaContentWrapper = new VerticalLayout();
79 mediaContentWrapper.addStyleName("media-wrapper");
80 mediaContentWrapper.setSizeFull();
81 fieldComponent = createImage();
82 mediaContentWrapper.addComponent(fieldComponent);
83 mediaContentWrapper.setComponentAlignment(fieldComponent, Alignment.MIDDLE_CENTER);
84 return mediaContentWrapper;
85 }
86
87 protected abstract Component createImage();
88
89 @Override
90 protected void doSetValue(byte[] value) {
91 this.value = value;
92 if (value != null) {
93 refreshImageSource();
94 }
95 }
96
97 @Override
98 public byte[] getValue() {
99 return value;
100 }
101
102 @Override
103 public void scaleToActualSize() {
104 doScaleToActual(this);
105 }
106
107 private void doScaleToActual(HasComponents hc) {
108 Iterator<Component> it = hc.iterator();
109 while (it.hasNext()) {
110 Component c = it.next();
111 if (c instanceof Image) {
112 c.removeStyleName("scale-to-fit");
113 } else if (c instanceof HasComponents) {
114 doScaleToActual((HasComponents)c);
115 }
116 }
117 }
118
119 @Override
120 public void scaleToFit() {
121 doScaleToFit(this);
122 }
123
124 private void doScaleToFit(HasComponents hc) {
125 Iterator<Component> it = hc.iterator();
126 while (it.hasNext()) {
127 Component c = it.next();
128 if (c instanceof Image) {
129 c.addStyleName("scale-to-fit");
130 } else if (c instanceof HasComponents) {
131 doScaleToFit((HasComponents)c);
132 }
133 }
134 }
135
136 @Override
137 public void applyChanges() {
138 }
139
140 @Override
141 public void revertChanges() {
142 }
143
144 public void execute() {
145 InputStream stream = null;
146 try {
147 BufferedImage result = executeImageModification();
148 stream = createStreamSource(result, DEFAULT_FORMAT);
149 if (result != null) {
150 setValue(IOUtils.toByteArray(stream));
151 refreshImageSource();
152 }
153 } catch (IOException e) {
154 log.error("Error occurred while converting operation result into stream: " + e.getMessage(), e);
155 revertChanges();
156 } finally {
157 IOUtils.closeQuietly(stream);
158 }
159 }
160
161 protected BufferedImage executeImageModification() throws IOException {
162 return null;
163 }
164
165 public abstract void refreshImageSource();
166
167 protected String generateTempFileName() {
168 return TEMP_FILE_NAME_BASE + System.currentTimeMillis();
169 }
170
171 protected StreamResource createResourceFromValue() {
172 StreamSource streamSource = () -> new ByteArrayInputStream(getValue());
173 StreamResource streamResource = new StreamResource(streamSource, generateTempFileName());
174 streamResource.setMIMEType(String.join("/", "image", DEFAULT_FORMAT));
175
176 return streamResource;
177 }
178
179 protected InputStream createStreamSource(final BufferedImage img, final String formatName) throws IOException {
180 ByteArrayOutputStream os = null;
181 try {
182 if (img == null) {
183 return null;
184 }
185 os = new ByteArrayOutputStream();
186 ImageIO.write(img, formatName, os);
187 return new ByteArrayInputStream(os.toByteArray());
188 } finally {
189 IOUtils.closeQuietly(os);
190 }
191 }
192 }