Skip to content

Commit eda6c15

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 2dc6c7a + 7fb552e commit eda6c15

5 files changed

Lines changed: 29 additions & 30 deletions

File tree

simplix-auth/src/main/java/dev/simplecore/simplix/auth/autoconfigure/SimpliXAuthSecurityConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public SecurityFilterChain webSecurityFilterChain(
219219
}
220220
String permissions = properties.getSecurity().getPermissionsPolicy();
221221
if (permissions != null && !permissions.isEmpty()) {
222-
headers.permissionsPolicy(pp -> pp.policy(permissions));
222+
headers.permissionsPolicyHeader(pp -> pp.policy(permissions));
223223
}
224224
});
225225

simplix-file/src/main/java/dev/simplecore/simplix/file/config/ImageProperties.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ public class ImageProperties {
5252
*/
5353
private int defaultQuality = 85;
5454

55+
/**
56+
* Whether to downscale images that exceed the configured maximum dimensions
57+
* at upload time. When false, the original is stored losslessly and only
58+
* derived thumbnails are resized on demand.
59+
*/
60+
private boolean resizeOnUpload = true;
61+
5562
/**
5663
* Maximum file size for images
5764
*/

simplix-file/src/main/java/dev/simplecore/simplix/file/infrastructure/image/impl/AwtImageProcessingService.java

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -150,44 +150,32 @@ public ProcessedImage generateThumbnail(InputStream input, int width, int height
150150
);
151151
}
152152

153-
// Calculate crop dimensions to center-crop to target aspect ratio
154153
int originalWidth = image.getWidth();
155154
int originalHeight = image.getHeight();
156155

157-
double targetRatio = (double) width / height;
158-
double originalRatio = (double) originalWidth / originalHeight;
159-
160-
int cropWidth;
161-
int cropHeight;
162-
int cropX;
163-
int cropY;
164-
165-
if (originalRatio > targetRatio) {
166-
// Original is wider, crop sides
167-
cropHeight = originalHeight;
168-
cropWidth = (int) (originalHeight * targetRatio);
169-
cropX = (originalWidth - cropWidth) / 2;
170-
cropY = 0;
171-
} else {
172-
// Original is taller, crop top/bottom
173-
cropWidth = originalWidth;
174-
cropHeight = (int) (originalWidth / targetRatio);
175-
cropX = 0;
176-
cropY = (originalHeight - cropHeight) / 2;
156+
// Fit the whole image inside the width x height bounding box, preserving
157+
// aspect ratio (no cropping). The box is treated as a maximum; the output
158+
// dimensions vary so the entire image stays visible (object-contain).
159+
// Never upscale beyond the original size.
160+
double scale = Math.min((double) width / originalWidth, (double) height / originalHeight);
161+
if (scale > 1.0) {
162+
scale = 1.0;
177163
}
178164

179-
// Crop to target aspect ratio
180-
BufferedImage cropped = image.getSubimage(cropX, cropY, cropWidth, cropHeight);
165+
int targetWidth = Math.max(1, (int) Math.round(originalWidth * scale));
166+
int targetHeight = Math.max(1, (int) Math.round(originalHeight * scale));
181167

182-
// Resize to target dimensions
183-
BufferedImage thumbnail = resizeImage(cropped, width, height);
168+
// Resize to the fitted dimensions (resizeImage fully covers the canvas, so
169+
// no padding is baked in — letterboxing is handled by the display CSS).
170+
BufferedImage thumbnail = resizeImage(image, targetWidth, targetHeight);
184171

185172
int quality = imageProperties.getThumbnail().getDefaultQuality();
186173
byte[] resultBytes = writeImage(thumbnail, "jpg", quality);
187174

188-
log.debug("Generated thumbnail {}x{} from {}x{}", width, height, originalWidth, originalHeight);
175+
log.debug("Generated thumbnail {}x{} (box {}x{}) from {}x{}",
176+
targetWidth, targetHeight, width, height, originalWidth, originalHeight);
189177

190-
return new ProcessedImage(resultBytes, "image/jpeg", width, height);
178+
return new ProcessedImage(resultBytes, "image/jpeg", targetWidth, targetHeight);
191179
} catch (IOException e) {
192180
throw new ImageProcessingException(
193181
ImageProcessingException.ImageErrorCode.THUMBNAIL_GENERATION_FAILED,

simplix-file/src/main/java/dev/simplecore/simplix/file/infrastructure/upload/impl/DefaultFileProcessingService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ private ProcessedFileResult processImage(FileProcessingRequest request) {
171171
metadata.width(), metadata.height(), finalWidth, finalHeight,
172172
optimized.data().length);
173173

174-
} else if (metadata.width() > maxWidth || metadata.height() > maxHeight) {
174+
} else if (imageProperties.isResizeOnUpload()
175+
&& (metadata.width() > maxWidth || metadata.height() > maxHeight)) {
175176
// Only resize without WebP conversion
176177
ProcessedImage resized = imageProcessingService.resizeIfExceeds(
177178
file.getInputStream(), maxWidth, maxHeight

simplix-hibernate/src/main/java/dev/simplecore/simplix/hibernate/event/EntityEventPublishingListener.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.slf4j.MDC;
2121
import org.springframework.beans.factory.annotation.Autowired;
2222
import org.springframework.context.ApplicationEventPublisher;
23+
import org.springframework.core.annotation.AnnotationUtils;
2324
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
2425
import org.springframework.stereotype.Component;
2526

@@ -156,7 +157,9 @@ private boolean shouldPublish(Object entity) {
156157
}
157158

158159
private EntityEventConfig getConfig(Object entity) {
159-
return entity.getClass().getAnnotation(EntityEventConfig.class);
160+
// Use Spring AnnotationUtils to traverse @MappedSuperclass / interface hierarchy.
161+
// A subclass-level @EntityEventConfig still takes precedence (direct annotation first).
162+
return AnnotationUtils.findAnnotation(entity.getClass(), EntityEventConfig.class);
160163
}
161164

162165
private void publishEvent(String eventType, Object entity, Set<String> changedProperties,

0 commit comments

Comments
 (0)