Files
coolsoup/src/generators/bands.ts

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
}