117 lines
3.0 KiB
TypeScript
117 lines
3.0 KiB
TypeScript
import type { GeneratedImage } from '../stores'
|
|
|
|
interface Band {
|
|
x: number
|
|
width: number
|
|
y: number
|
|
}
|
|
|
|
interface BandLayer {
|
|
divisions: number
|
|
bands: Band[]
|
|
opacity: number
|
|
}
|
|
|
|
function generateBandLayer(canvasWidth: number, canvasHeight: number): BandLayer {
|
|
const possibleDivisions = [2, 4, 8, 16, 32, 64, 128]
|
|
const divisions = possibleDivisions[Math.floor(Math.random() * possibleDivisions.length)]
|
|
const sectionWidth = canvasWidth / divisions
|
|
|
|
// Density varies from very sparse (20%) to very dense (95%)
|
|
const densityOptions = [0.2, 0.4, 0.6, 0.8, 0.95]
|
|
const density = densityOptions[Math.floor(Math.random() * densityOptions.length)]
|
|
|
|
const bands: Band[] = []
|
|
|
|
for (let i = 0; i < divisions; i++) {
|
|
if (Math.random() < density) {
|
|
const x = i * sectionWidth
|
|
const yValue = Math.random() // 0.0 to 1.0
|
|
// Convert y value where 0.0 is bottom and 1.0 is top
|
|
const y = canvasHeight - yValue * canvasHeight
|
|
|
|
bands.push({
|
|
x,
|
|
width: sectionWidth,
|
|
y,
|
|
})
|
|
}
|
|
}
|
|
|
|
return {
|
|
divisions,
|
|
bands,
|
|
opacity: 0.8, // Slight transparency for superimposition
|
|
}
|
|
}
|
|
|
|
function drawBandLayer(ctx: CanvasRenderingContext2D, layer: BandLayer, strokeHeight: number) {
|
|
ctx.globalAlpha = layer.opacity
|
|
|
|
layer.bands.forEach(band => {
|
|
ctx.fillRect(band.x, band.y - strokeHeight / 2, band.width, strokeHeight)
|
|
})
|
|
|
|
ctx.globalAlpha = 1.0 // Reset alpha
|
|
}
|
|
|
|
export function generateBandsImages(count: number, size: number): GeneratedImage[] {
|
|
const images: GeneratedImage[] = []
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
try {
|
|
const canvas = document.createElement('canvas')
|
|
const ctx = canvas.getContext('2d')!
|
|
|
|
canvas.width = size
|
|
canvas.height = size
|
|
|
|
// Fill background (always black)
|
|
ctx.fillStyle = '#000000'
|
|
ctx.fillRect(0, 0, size, size)
|
|
|
|
// Generate three superimposed band layers
|
|
const layers: BandLayer[] = []
|
|
for (let j = 0; j < 3; j++) {
|
|
layers.push(generateBandLayer(size, size))
|
|
}
|
|
|
|
// Draw the three layers
|
|
ctx.fillStyle = '#ffffff'
|
|
const strokeHeight = Math.max(1, size * 0.002) // Stroke height is 0.2% of canvas size, minimum 1px - much thinner bands
|
|
|
|
layers.forEach(layer => {
|
|
drawBandLayer(ctx, layer, strokeHeight)
|
|
})
|
|
|
|
const imageData = ctx.getImageData(0, 0, size, size)
|
|
|
|
const image: GeneratedImage = {
|
|
id: `bands-${Date.now()}-${i}`,
|
|
canvas,
|
|
imageData,
|
|
generator: 'bands',
|
|
params: {
|
|
layers: layers.map(layer => ({
|
|
divisions: layer.divisions,
|
|
bands: layer.bands.map(band => ({
|
|
x: band.x,
|
|
width: band.width,
|
|
y: band.y,
|
|
})),
|
|
opacity: layer.opacity,
|
|
})),
|
|
strokeHeight,
|
|
size,
|
|
},
|
|
}
|
|
|
|
images.push(image)
|
|
} catch (error) {
|
|
console.error(`Failed to generate bands image ${i + 1}:`, error)
|
|
}
|
|
}
|
|
|
|
return images
|
|
}
|