feat: add core type definitions
- Device, ImageEntry, Dimensions types - PipelineConfig with all processing steps - Built-in pipeline presets (default, high-contrast, etc.) - Validation constraints and utility functions Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
216
src/lib/types.ts
Normal file
216
src/lib/types.ts
Normal file
@@ -0,0 +1,216 @@
|
||||
// Core type definitions for 2eInk
|
||||
|
||||
export type GreyLevel = 2 | 4 | 8 | 16 | 256;
|
||||
export type OutputFormat = 'png' | 'jpeg';
|
||||
export type ImageStatus = 'pending' | 'processing' | 'complete' | 'error';
|
||||
|
||||
export interface Dimensions {
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
}
|
||||
|
||||
export interface Device {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly brand: string;
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
readonly greyLevels: GreyLevel;
|
||||
readonly outputFormat: OutputFormat;
|
||||
}
|
||||
|
||||
export interface ImageEntry {
|
||||
readonly id: string;
|
||||
readonly file: File;
|
||||
readonly filename: string;
|
||||
originalDimensions: Dimensions | null;
|
||||
originalDataUrl: string | null;
|
||||
processedBlob: Blob | null;
|
||||
processedDataUrl: string | null;
|
||||
status: ImageStatus;
|
||||
error: string | null;
|
||||
pipelineOverride: PipelineConfig | null;
|
||||
}
|
||||
|
||||
export interface CustomDeviceFormData {
|
||||
name: string;
|
||||
width: number;
|
||||
height: number;
|
||||
greyLevels: GreyLevel;
|
||||
outputFormat: OutputFormat;
|
||||
}
|
||||
|
||||
export const CONSTRAINTS = {
|
||||
MAX_FILE_SIZE_MB: 25,
|
||||
MAX_FILE_SIZE_BYTES: 25 * 1024 * 1024,
|
||||
MIN_DIMENSION: 100,
|
||||
MAX_DIMENSION: 5000,
|
||||
MAX_DEVICE_NAME_LENGTH: 50,
|
||||
SUPPORTED_FORMATS: ['image/jpeg', 'image/png', 'image/webp'],
|
||||
GREY_LEVEL_OPTIONS: [2, 4, 8, 16, 256],
|
||||
OUTPUT_FORMAT_OPTIONS: ['png', 'jpeg']
|
||||
} as const;
|
||||
|
||||
export function isSupportedFormat(file: File): boolean {
|
||||
return CONSTRAINTS.SUPPORTED_FORMATS.includes(
|
||||
file.type as (typeof CONSTRAINTS.SUPPORTED_FORMATS)[number]
|
||||
);
|
||||
}
|
||||
|
||||
export function getExtension(format: OutputFormat): string {
|
||||
return format === 'jpeg' ? 'jpg' : 'png';
|
||||
}
|
||||
|
||||
// Pipeline Configuration
|
||||
|
||||
export type CropMode = 'center' | 'top' | 'bottom' | 'manual';
|
||||
export type ResizeMode = 'cover' | 'contain' | 'stretch';
|
||||
export type GreyscaleMethod = 'luminosity' | 'average' | 'lightness' | 'red' | 'green' | 'blue';
|
||||
export type DitherAlgorithm = 'floyd-steinberg' | 'ordered' | 'atkinson';
|
||||
|
||||
export interface CropRegion {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface CropConfig {
|
||||
enabled: boolean;
|
||||
mode: CropMode;
|
||||
region?: CropRegion;
|
||||
}
|
||||
|
||||
export interface ResizeConfig {
|
||||
enabled: boolean;
|
||||
mode: ResizeMode;
|
||||
}
|
||||
|
||||
export interface BrightnessConfig {
|
||||
enabled: boolean;
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface ContrastConfig {
|
||||
enabled: boolean;
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface GammaConfig {
|
||||
enabled: boolean;
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface AutoLevelsConfig {
|
||||
enabled: boolean;
|
||||
clipPercent: number;
|
||||
}
|
||||
|
||||
export interface GreyscaleConfig {
|
||||
enabled: boolean;
|
||||
method: GreyscaleMethod;
|
||||
}
|
||||
|
||||
export interface SharpenConfig {
|
||||
enabled: boolean;
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export interface QuantizeConfig {
|
||||
enabled: boolean;
|
||||
levels: number;
|
||||
}
|
||||
|
||||
export interface DitherConfig {
|
||||
enabled: boolean;
|
||||
algorithm: DitherAlgorithm;
|
||||
}
|
||||
|
||||
export interface PipelineConfig {
|
||||
crop: CropConfig;
|
||||
resize: ResizeConfig;
|
||||
brightness: BrightnessConfig;
|
||||
contrast: ContrastConfig;
|
||||
gamma: GammaConfig;
|
||||
autoLevels: AutoLevelsConfig;
|
||||
greyscale: GreyscaleConfig;
|
||||
sharpen: SharpenConfig;
|
||||
quantize: QuantizeConfig;
|
||||
dither: DitherConfig;
|
||||
}
|
||||
|
||||
export interface PipelinePreset {
|
||||
id: string;
|
||||
name: string;
|
||||
config: PipelineConfig;
|
||||
isBuiltIn: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_PIPELINE_CONFIG: PipelineConfig = {
|
||||
crop: { enabled: true, mode: 'center' },
|
||||
resize: { enabled: true, mode: 'cover' },
|
||||
brightness: { enabled: false, value: 0 },
|
||||
contrast: { enabled: true, value: 10 },
|
||||
gamma: { enabled: false, value: 1.0 },
|
||||
autoLevels: { enabled: false, clipPercent: 0.5 },
|
||||
greyscale: { enabled: true, method: 'luminosity' },
|
||||
sharpen: { enabled: false, amount: 0 },
|
||||
quantize: { enabled: true, levels: 16 },
|
||||
dither: { enabled: true, algorithm: 'floyd-steinberg' }
|
||||
};
|
||||
|
||||
export const BUILT_IN_PRESETS: PipelinePreset[] = [
|
||||
{
|
||||
id: 'default',
|
||||
name: 'Default',
|
||||
config: DEFAULT_PIPELINE_CONFIG,
|
||||
isBuiltIn: true
|
||||
},
|
||||
{
|
||||
id: 'high-contrast',
|
||||
name: 'High Contrast',
|
||||
config: {
|
||||
...DEFAULT_PIPELINE_CONFIG,
|
||||
contrast: { enabled: true, value: 30 },
|
||||
brightness: { enabled: true, value: 5 },
|
||||
gamma: { enabled: true, value: 1.2 }
|
||||
},
|
||||
isBuiltIn: true
|
||||
},
|
||||
{
|
||||
id: 'no-dither',
|
||||
name: 'No Dither',
|
||||
config: {
|
||||
...DEFAULT_PIPELINE_CONFIG,
|
||||
dither: { enabled: false, algorithm: 'floyd-steinberg' },
|
||||
contrast: { enabled: false, value: 0 },
|
||||
gamma: { enabled: false, value: 1.0 }
|
||||
},
|
||||
isBuiltIn: true
|
||||
},
|
||||
{
|
||||
id: 'photo',
|
||||
name: 'Photo (256 levels)',
|
||||
config: {
|
||||
...DEFAULT_PIPELINE_CONFIG,
|
||||
quantize: { enabled: false, levels: 256 },
|
||||
dither: { enabled: false, algorithm: 'floyd-steinberg' },
|
||||
contrast: { enabled: true, value: 5 },
|
||||
gamma: { enabled: true, value: 1.05 }
|
||||
},
|
||||
isBuiltIn: true
|
||||
},
|
||||
{
|
||||
id: 'atkinson',
|
||||
name: 'Atkinson Dither',
|
||||
config: {
|
||||
...DEFAULT_PIPELINE_CONFIG,
|
||||
dither: { enabled: true, algorithm: 'atkinson' }
|
||||
},
|
||||
isBuiltIn: true
|
||||
}
|
||||
];
|
||||
|
||||
export function clonePipelineConfig(config: PipelineConfig): PipelineConfig {
|
||||
return JSON.parse(JSON.stringify(config));
|
||||
}
|
||||
Reference in New Issue
Block a user