Add ability to tell image to shrink only

Useful for thumbnails, no need to enlarge a small image
This commit is contained in:
rubikscraft
2022-09-01 15:40:56 +02:00
parent 3a1f279d32
commit 83cc652b52
8 changed files with 45 additions and 22 deletions

View File

@@ -72,19 +72,22 @@ export class ImageConverterService {
// Do modifications
if (options.height || options.width) {
if (options.height && options.width) {
if ((options.height && options.width)) {
sharpWrapper.operation('resize', {
width: options.width,
height: options.height,
fit: 'fill',
kernel: 'cubic',
withoutEnlargement: options.shrinkonly,
});
} else {
sharpWrapper.operation('resize', {
width: options.width,
height: options.height,
fit: 'contain',
fit: 'inside',
kernel: 'cubic',
withoutEnlargement: options.shrinkonly,
});
}
}

View File

@@ -71,7 +71,7 @@ export class ImagesComponent implements OnInit {
getThumbnailUrl(image: EImage) {
return (
this.imageService.GetImageURL(image.id, ImageFileType.QOI) + '?height=480'
this.imageService.GetImageURL(image.id, ImageFileType.QOI) + '?height=480&shrinkonly=yes'
);
}

View File

@@ -68,6 +68,10 @@
</mat-slide-toggle>
</div>
<div class="col-xl-4 col-sm-6 col-12">
<mat-slide-toggle [(ngModel)]="shrinkonly">Shrink only</mat-slide-toggle>
</div>
<div class="col-xl-4 col-sm-6 col-12">
<mat-slide-toggle [(ngModel)]="greyscale">Greyscale</mat-slide-toggle>
</div>

View File

@@ -32,6 +32,7 @@ export class CustomizeDialogComponent implements OnInit {
public rotate: number;
public flipx: boolean;
public flipy: boolean;
public shrinkonly: boolean;
public greyscale: boolean;
public noalpha: boolean;
public negative: boolean;
@@ -64,6 +65,7 @@ export class CustomizeDialogComponent implements OnInit {
quality: this.quality ?? undefined,
flipx: this.flipx,
flipy: this.flipy,
shrinkonly: this.shrinkonly,
greyscale: this.greyscale,
noalpha: this.noalpha,
negative: this.negative,

View File

@@ -80,11 +80,13 @@ export class ViewComponent implements OnInit {
if (HasFailed(metadata))
return this.utilService.quitError(metadata.getReason());
// Get width of screen in pixels
const width = window.innerWidth * window.devicePixelRatio;
// Populate fields with metadata
this.previewLink = this.imageService.GetImageURL(
this.id,
metadata.fileTypes.master,
);
this.previewLink =
this.imageService.GetImageURL(this.id, metadata.fileTypes.master) +
(width > 1 ? `?width=${width}&shrinkonly=yes` : '');
this.hasOriginal = metadata.fileTypes.original !== undefined;
@@ -162,10 +164,7 @@ export class ViewComponent implements OnInit {
);
}
this.utilService.showSnackBar(
'Image deleted',
SnackBarType.Success,
);
this.utilService.showSnackBar('Image deleted', SnackBarType.Success);
this.router.navigate(['/']);
}

View File

@@ -15,7 +15,13 @@ import { ImageLinks } from 'picsur-shared/dist/dto/image-links.class';
import { FileType2Ext } from 'picsur-shared/dist/dto/mimes.dto';
import { EImage } from 'picsur-shared/dist/entities/image.entity';
import { AsyncFailable } from 'picsur-shared/dist/types';
import { Fail, FT, HasFailed, HasSuccess, Open } from 'picsur-shared/dist/types/failable';
import {
Fail,
FT,
HasFailed,
HasSuccess,
Open
} from 'picsur-shared/dist/types/failable';
import { ImageUploadRequest } from '../../models/dto/image-upload-request.dto';
import { ApiService } from './api.service';
import { UserService } from './user.service';
@@ -107,7 +113,9 @@ export class ImageService {
const baseURL = this.location.protocol + '//' + this.location.host;
const extension = FileType2Ext(filetype ?? '');
return `${baseURL}/i/${image}${HasSuccess(extension) ? '.' + extension : ''}`;
return `${baseURL}/i/${image}${
HasSuccess(extension) ? '.' + extension : ''
}`;
}
public GetImageURLCustomized(
@@ -129,6 +137,8 @@ export class ImageService {
queryParams.push(`rotate=${options.rotate}`);
if (options.flipx !== undefined) queryParams.push(`flipx=${options.flipx}`);
if (options.flipy !== undefined) queryParams.push(`flipy=${options.flipy}`);
if (options.shrinkonly !== undefined)
queryParams.push(`shrinkonly=${options.shrinkonly}`);
if (options.greyscale !== undefined)
queryParams.push(`greyscale=${options.greyscale}`);
if (options.noalpha !== undefined)

View File

@@ -2,15 +2,15 @@ import { z } from 'zod';
import { EImageSchema } from '../../entities/image.entity';
import { EUserSchema } from '../../entities/user.entity';
import { createZodDto } from '../../util/create-zod-dto';
import { ParseBool } from '../../util/parse-simple';
import { ParseBool, ParseInt } from '../../util/parse-simple';
import { ImageEntryVariant } from '../image-entry-variant.enum';
export const ImageRequestParamsSchema = z
.object({
height: z.preprocess(Number, z.number().int().min(1).max(32767)),
width: z.preprocess(Number, z.number().int().min(1).max(32767)),
height: z.preprocess(ParseInt, z.number().int().min(1).max(32767)),
width: z.preprocess(ParseInt, z.number().int().min(1).max(32767)),
rotate: z.preprocess(
Number,
ParseInt,
z.number().int().multipleOf(90).min(0).max(360),
),
flipx: z.preprocess(ParseBool, z.boolean()),
@@ -18,7 +18,8 @@ export const ImageRequestParamsSchema = z
greyscale: z.preprocess(ParseBool, z.boolean()),
noalpha: z.preprocess(ParseBool, z.boolean()),
negative: z.preprocess(ParseBool, z.boolean()),
quality: z.preprocess(Number, z.number().int().min(1).max(100)),
shrinkonly: z.preprocess(ParseBool, z.boolean()),
quality: z.preprocess(ParseInt, z.number().int().min(1).max(100)),
})
.partial();

View File

@@ -14,13 +14,17 @@ export const ParseInt = <T extends number | null = null>(
value: unknown,
fallback?: T,
): number | T => {
if (typeof value === 'number') return value;
if (typeof value === 'number') return Math.round(value);
if (typeof value === 'boolean') return value ? 1 : 0;
if (typeof value === 'string') {
const parsed = parseInt(value);
if (!isNaN(parsed)) return parsed;
const parsed = Number(value);
if (!isNaN(parsed)) return Math.round(parsed);
}
return fallback === undefined ? (null as T) : fallback;
return fallback === undefined
? (null as T)
: fallback === null
? fallback
: Math.round(fallback);
};
export const ParseString = <T extends string | null = null>(