diff --git a/pom.xml b/pom.xml
index c3c843d..2b04043 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,129 +1,139 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 3.1.5
-
-
- com.appdev
- all-in
- 0.0.1-SNAPSHOT
- all-in
- All In Backend
-
- 17
-
-
-
- org.imgscalr
- imgscalr-lib
- 4.2
-
-
- com.drewnoakes
- metadata-extractor
- 2.18.0
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.springframework.boot
- spring-boot-devtools
- true
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
- com.mysql
- mysql-connector-j
- runtime
-
-
- org.springdoc
- springdoc-openapi-starter-webmvc-ui
- 2.6.0
-
-
- org.apache.commons
- commons-math3
- 3.6.1
-
-
- org.jsoup
- jsoup
- 1.17.2
-
-
- com.github.javafaker
- javafaker
- 1.0.2
-
-
- com.google.firebase
- firebase-admin
- 9.4.1
-
-
- org.springframework.boot
- spring-boot-starter-security
-
-
-
-
-
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+
org.springframework.boot
- spring-boot-maven-plugin
-
-
- com.diffplug.spotless
- spotless-maven-plugin
- 2.43.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.jacoco
- jacoco-maven-plugin
- 0.8.12
-
-
- prepare-agent
-
- prepare-agent
-
-
-
- report
-
- report
-
- test
-
-
-
-
+ spring-boot-starter-parent
+ 3.1.5
+
+
+ com.appdev
+ all-in
+ 0.0.1-SNAPSHOT
+ all-in
+ All In Backend
+
+ 17
+
+
+
+ org.imgscalr
+ imgscalr-lib
+ 4.2
+
+
+ com.drewnoakes
+ metadata-extractor
+ 2.18.0
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.6.0
+
+
+ org.apache.commons
+ commons-math3
+ 3.6.1
+
+
+ org.jsoup
+ jsoup
+ 1.17.2
+
+
+ com.github.javafaker
+ javafaker
+ 1.0.2
+
+
+ com.google.firebase
+ firebase-admin
+ 9.4.1
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ com.twelvemonkeys.imageio
+ imageio-core
+ 3.9.4
+
+
+ com.twelvemonkeys.imageio
+ imageio-webp
+ 3.9.4
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ 2.43.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.12
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+ report
+
+ report
+
+ test
+
+
+
+
-
+
diff --git a/src/main/java/com/appdev/allin/scrapers/PlayerScraper.java b/src/main/java/com/appdev/allin/scrapers/PlayerScraper.java
index 8c60e71..435cde4 100644
--- a/src/main/java/com/appdev/allin/scrapers/PlayerScraper.java
+++ b/src/main/java/com/appdev/allin/scrapers/PlayerScraper.java
@@ -14,6 +14,7 @@
import com.appdev.allin.player.Player;
import com.appdev.allin.player.PlayerService;
import com.appdev.allin.player.Position;
+import com.appdev.allin.utils.ImageProcessor;
public class PlayerScraper {
private static final Logger logger = LoggerFactory.getLogger(PlayerScraper.class);
@@ -62,6 +63,15 @@ public void populate() throws IOException {
Element imageElement = playerElement.selectFirst("div.sidearm-roster-player-image img");
String imageUrl = imageElement != null ? "https://cornellbigred.com" + imageElement.attr("data-src") : "";
+
+ String bucketUrl = "";
+ if (!imageUrl.isEmpty()) {
+ String b64Image = "data:image/webp;base64," + ImageProcessor.urlToBase64(imageUrl);
+ if (b64Image != null && !b64Image.isEmpty()) {
+ bucketUrl = ImageProcessor.uploadImage(b64Image, 250, 250);
+ System.out.println("Image URL: " + bucketUrl);
+ }
+ }
if (number == null || firstName.isEmpty() || lastName.isEmpty()) {
logger.warn("Bad data for player {} {}", firstName, lastName);
@@ -75,7 +85,7 @@ public void populate() throws IOException {
}
Player player = new Player(firstName, lastName, positions, number, height, weight, hometown, highSchool,
- imageUrl);
+ bucketUrl);
if (playerService.getPlayerByNumber(player.getNumber()) == null) {
playerService.savePlayer(player);
diff --git a/src/main/java/com/appdev/allin/utils/ImageProcessor.java b/src/main/java/com/appdev/allin/utils/ImageProcessor.java
index 870b5be..d8edcff 100644
--- a/src/main/java/com/appdev/allin/utils/ImageProcessor.java
+++ b/src/main/java/com/appdev/allin/utils/ImageProcessor.java
@@ -1,226 +1,206 @@
package com.appdev.allin.utils;
-
-import com.drew.imaging.ImageMetadataReader;
-import com.drew.metadata.Metadata;
-import com.drew.metadata.exif.ExifIFD0Directory;
-
-import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
-
-import javax.imageio.ImageIO;
-
+import java.io.InputStream;
+import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
+import javax.imageio.ImageIO;
+
+import org.imgscalr.Scalr;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.*;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
+
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.exif.ExifIFD0Directory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.imgscalr.Scalr;
-
public class ImageProcessor {
-
@Value("${all-in.image-upload-url}")
private static String imageUploadUrl;
-
- @Value("${all-in.image-upload-bucket}")
- private static String imageUploadBucket;
-
- /**
- * Crops the given image to the specified width and height.
- * If the specified dimensions are larger than the original image,
- * the method ensures that the cropped area does not exceed the image bounds.
- *
- * @param originalImage The original BufferedImage to be cropped.
- * @param targetWidth The desired width of the cropped image.
- * @param targetHeight The desired height of the cropped image.
- * @return A new BufferedImage representing the cropped portion of the original
- * image.
- */
+ @Value("${allin.bucket}")
+ private String bucket;
public static BufferedImage cropImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
int originalWidth = originalImage.getWidth();
int originalHeight = originalImage.getHeight();
-
- int x = (originalWidth - targetWidth) / 2;
- int y = (originalHeight - targetHeight) / 2;
-
- x = Math.max(0, x);
- y = Math.max(0, y);
-
+ int x = Math.max(0, (originalWidth - targetWidth) / 2);
+ int y = Math.max(0, (originalHeight - targetHeight) / 2);
targetWidth = Math.min(targetWidth, originalWidth - x);
targetHeight = Math.min(targetHeight, originalHeight - y);
-
return originalImage.getSubimage(x, y, targetWidth, targetHeight);
}
-
- /**
- * Corrects the orientation of an image based on its EXIF metadata.
- * For images with metadata specifying an orientation, the image is rotated
- * to match the correct orientation. If no metadata is available or if an error
- * occurs, the original image is returned.
- *
- * @param image The BufferedImage to correct.
- * @param file The image file used to retrieve EXIF metadata.
- * @return A new BufferedImage with corrected orientation, or the original image
- * if no correction is necessary.
- * @throws IOException If an error occurs while reading the file.
- */
public static BufferedImage correctOrientation(BufferedImage image, File file) throws IOException {
try {
Metadata metadata = ImageMetadataReader.readMetadata(file);
- if (metadata == null) {
- System.err.println("No metadata found for orientation correction.");
- return image;
- }
+ if (metadata == null) return image;
ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
int orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
- switch (orientation) {
- case 6:
- return rotateImage(image, 90);
- case 3:
- return rotateImage(image, 180);
- case 8:
- return rotateImage(image, 270);
- default:
- return image;
- }
+ return switch (orientation) {
+ case 6 -> rotateImage(image, 90);
+ case 3 -> rotateImage(image, 180);
+ case 8 -> rotateImage(image, 270);
+ default -> image;
+ };
}
} catch (Exception e) {
System.err.println("Could not determine image orientation: " + e.getMessage());
}
return image;
}
-
- /**
- * Rotates image by [angle] degrees.
- *
- * @param image The original BufferedImage to rotate.
- * @param angle The angle in degrees by which to rotate the image. Positive
- * values rotate the image clockwise, and negative values rotate it
- * counterclockwise.
- * @return A new BufferedImage representing the rotated image.
- */
public static BufferedImage rotateImage(BufferedImage image, double angle) {
- // Calculate the new image dimensions after rotation
double radians = Math.toRadians(angle);
- int newWidth = (int) Math.abs(image.getWidth() * Math.cos(radians))
- + (int) Math.abs(image.getHeight() * Math.sin(radians));
- int newHeight = (int) Math.abs(image.getWidth() * Math.sin(radians))
- + (int) Math.abs(image.getHeight() * Math.cos(radians));
-
- // Create a new image with the calculated dimensions
+ int newWidth = (int) Math.abs(image.getWidth() * Math.cos(radians)) + (int) Math.abs(image.getHeight() * Math.sin(radians));
+ int newHeight = (int) Math.abs(image.getWidth() * Math.sin(radians)) + (int) Math.abs(image.getHeight() * Math.cos(radians));
BufferedImage rotatedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = rotatedImage.createGraphics();
-
- // Set the rendering hints for better quality
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-
- // Calculate the rotation point (center of the original image)
int x = (newWidth - image.getWidth()) / 2;
int y = (newHeight - image.getHeight()) / 2;
-
- // Rotate around the center of the new image
g2d.rotate(radians, newWidth / 2.0, newHeight / 2.0);
g2d.drawImage(image, x, y, null);
g2d.dispose();
-
- System.out.println("Image rotated by " + angle + " degrees.");
return rotatedImage;
}
-
- /**
- * Scales image to target width and height.
- *
- * @param originalImage The original BufferedImage to be scaled.
- * @param targetWidth The desired width of the scaled image.
- * @param targetHeight The desired height of the scaled image.
- * @return A new BufferedImage representing the scaled image.
- */
public static BufferedImage scaleImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
return Scalr.resize(originalImage, Scalr.Method.ULTRA_QUALITY, targetWidth, targetHeight);
}
-
- /**
- * Converts image from base64 string to BufferedImage.
- *
- * @param base64String The original base64 string to be converted.
- * @return A BufferedImage representing the original image.
- */
public static BufferedImage convertBase64ToImage(String base64String) throws IOException {
- // Remove the data:image/...;base64, prefix if it exists
String base64Image = base64String.split(",")[base64String.split(",").length - 1];
-
byte[] imageBytes = Base64.getDecoder().decode(base64Image);
try (ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes)) {
return ImageIO.read(bis);
}
}
- /**
- * Scales and uploads an image in base64 form to digital ocean.
- *
- * @param encodedImage The unmodified base64 image.
- * @param targetWidth The desired width of the scaled image.
- * @param targetHeight The desired height of the scaled image.
- * @return A url representing the uploaded image.
- */
+ public static String urlToBase64(String imageUrl) throws IOException {
+ if (imageUrl == null || imageUrl.trim().isEmpty()) {
+ throw new IllegalArgumentException("Provided imageUrl is null or empty");
+ }
+
+ URL url = new URL(imageUrl);
+
+ try (InputStream is = url.openStream();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+
+ byte[] buffer = new byte[8192];
+ int bytesRead;
+
+ while ((bytesRead = is.read(buffer)) != -1) {
+ baos.write(buffer, 0, bytesRead);
+ }
+
+ byte[] imageBytes = baos.toByteArray();
+
+ if (imageBytes.length == 0) {
+ throw new IOException("No data read from the provided image URL: " + imageUrl);
+ }
+
+ return Base64.getEncoder().encodeToString(imageBytes);
+ }
+ }
+
public static String uploadImage(String encodedImage, int targetWidth, int targetHeight) {
try {
- // Assume base64 starts with data URI prefix — extract format
String[] parts = encodedImage.split(",");
String format = "png";
- if (parts[0].contains("jpeg"))
- format = "jpg";
-
- // Decode base64 and convert to scaled image
+ if (parts[0].contains("jpeg")) format = "jpg";
+ else if (parts[0].contains("webp")) format = "webp";
BufferedImage image = convertBase64ToImage(encodedImage);
image = scaleImage(image, targetWidth, targetHeight);
-
- // Re-encode using original format
+ if ("webp".equals(format)) {
+ System.out.println("Converting WebP to PNG");
+ format = "png";
+ }
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, format, os);
byte[] imageBytes = os.toByteArray();
-
- // Add proper prefix
- String mimeType = format.equals("jpg") ? "image/jpeg" : "image/png";
+ String mimeType = switch (format) {
+ case "jpg" -> "image/jpeg";
+ case "png" -> "image/png";
+ default -> "image/png";
+ };
String dataUri = "data:" + mimeType + ";base64," + Base64.getEncoder().encodeToString(imageBytes);
-
- // Build payload
Map payload = new HashMap<>();
- payload.put("bucket", imageUploadBucket);
+ payload.put("bucket", "all-in");
payload.put("image", dataUri);
-
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity