ImageCropper can load the image dynamically using StreamedContent.
<div class="card">
<h:form>
<p:growl id="msgs" showDetail="true"/>
<h:panelGrid columns="3">
<h:panelGrid columns="1">
<p:spinner id="iterationSpinner"
value="#{dynamicCropper.numberOfIterations}"
min="5" max="50" stepFactor="5"
styleClass="mb-3">
<p:ajax process="@this" update="cropper"/>
</p:spinner>
<h:panelGrid columns="2" cellpadding="7">
<p:outputPanel id="cropper">
<p:imageCropper
value="#{dynamicCropper.croppedImage}"
id="streamed_cropper" cache="false"
image="#{dynamicCropper.image}"
initialCoords="50,50,150,100"
minSize="50,50" maxSize="350,350"/>
</p:outputPanel>
<p:outputPanel id="cropped">
<p:graphicImage
rendered="#{not empty dynamicCropper.newImageName}"
name="demo/images/crop/#{dynamicCropper.newImageName}"/>
</p:outputPanel>
</h:panelGrid>
<p:commandButton value="Crop"
action="#{dynamicCropper.crop}" styleClass="mt-3"
update="cropped msgs" />
</h:panelGrid>
</h:panelGrid>
</h:form>
</div>
@Named
@SessionScoped
public class DynamicCropper implements Serializable {
private final int width = 500;
private final int height = 350;
private int numberOfIterations;
private CroppedImage croppedImage;
private String newImageName;
@PostConstruct
public void init() {
this.numberOfIterations = 5;
}
public StreamedContent getImage() {
return DefaultStreamedContent.builder()
.contentType("image/png")
.stream(() -> {
try {
BufferedImage image = mandelbrotSet(width, height, numberOfIterations);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "png", outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
}
catch (Exception e) {
e.printStackTrace();
return null;
}
})
.build();
}
public void crop() {
if (this.croppedImage != null) {
String imageName = UUID.randomUUID().toString() + ".png";
setNewImageName(imageName);
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
Path path = Paths.get(externalContext.getRealPath(""), "resources", "demo", "images", "crop", imageName);
FileImageOutputStream imageOutput;
try {
imageOutput = new FileImageOutputStream(path.toFile());
imageOutput.write(croppedImage.getBytes(), 0, croppedImage.getBytes().length);
imageOutput.close();
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success", "Cropping finished."));
}
catch (Exception e) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Cropping failed."));
}
}
}
private BufferedImage mandelbrotSet(int width, int height, int maxIterations) throws IOException {
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
final int[] colorBuffer = new int[maxIterations];
Arrays.setAll(colorBuffer, i -> {
float h = i / 256.0f;
float b = i / (i + 8.0f);
return Color.HSBtoRGB(h, 1, b);
});
final int widthBy2 = width / 2;
final int heightBy2 = height / 2;
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
final double re = (j - widthBy2) * 4.0 / width;
final double im = (i - heightBy2) * 4.0 / width;
double x = .0, y = .0, rsq = .0;
int iteration = 0;
for (; rsq < 4 && iteration < maxIterations; ++iteration) {
double newX = x * x - y * y + re;
y = 2 * x * y + im;
x = newX;
rsq = x * x + y * y;
}
if (iteration < maxIterations) {
result.setRGB(j, i, colorBuffer[iteration]);
}
else {
result.setRGB(j, i, 0);
}
}
}
return result;
}
public int getNumberOfIterations() {
return numberOfIterations;
}
public void setNumberOfIterations(int numberOfIterations) {
this.numberOfIterations = numberOfIterations;
}
public CroppedImage getCroppedImage() {
return croppedImage;
}
public void setCroppedImage(CroppedImage croppedImage) {
this.croppedImage = croppedImage;
}
public String getNewImageName() {
return newImageName;
}
public void setNewImageName(String newImageName) {
this.newImageName = newImageName;
}
}