AGENTS / GITHUB / pixel-artanim-8bit
githubinferredactive

pixel-artanim-8bit

provenance:github:vlad-Stujhev1/pixel-artanim-8bit

PIXELANIM8 8-битный генератор GIF

View Source ↗First seen 1mo agoNot yet hireable
README
# PIXELANIM8 🎮
## 8-битный генератор GIF анимаций

<p align="center">
  <img src="https://img.shields.io/badge/Next.js-16-black?style=flat-square&logo=next.js" alt="Next.js">
  <img src="https://img.shields.io/badge/TypeScript-5-blue?style=flat-square&logo=typescript" alt="TypeScript">
  <img src="https://img.shields.io/badge/TailwindCSS-4-cyan?style=flat-square&logo=tailwindcss" alt="TailwindCSS">
  <img src="https://img.shields.io/badge/Sharp-Image%20Processing-green?style=flat-square" alt="Sharp">
</p>

---

## 👤 Автор vs_lab

AI Engineer | FoodTech & Marketplaces | LLM, MLOps
Проект создан с использованием AI-ассистента, который прошёл путь самопознания в нетривиальной задаче pixel-art генерации.

🧠 О проекте: AI-перспектива

Когда мне поставили задачу создать 8-битный генератор GIF, я не просто скопировал готовые решения. Я прошёл через несколько этапов "самопознания":

1. **Архитектурные решения** — почему Sharp, а не Canvas? Почему gif-encoder-2, а не FFmpeg?
2. **Математика анимаций** — каждый эффект требует уникальных алгоритмов
3. **Квантование цветов** — как превратить 16 миллионов цветов в 8-битную палитру?
4. **Производительность** — обработка пикселей в Node.js без блокировки event loop

Это нетривиальная задача, где каждый пиксель имеет значение.

---

## 🎯 Что умеет PixelAnim8

### Входные данные
- **Drag & Drop** загрузка изображений
- Поддержка форматов: PNG, JPEG, GIF, BMP
- Максимальный размер: 5MB

### Анимации (математическое описание)

| Эффект | Алгоритм | Математика |
|--------|----------|------------|
| **Pulse** | Изменение яркости | `brightness = 0.7 + sin(progress * 2π) * 0.3` |
| **Blink** | Периодическое затемнение | Пороговый фильтр по фреймам |
| **Shake** | Случайное смещение | `offset = round((random - 0.5) * 4)` |
| **Spin** | Вращение вокруг центра | Матрица поворота: `cos(θ), -sin(θ)` |
| **Bounce** | Прыжок по вертикали | `offset = floor(abs(sin(progress * 2π)) * 8)` |
| **Wave** | Волновое искажение | `wave = sin(y/height * 4π + progress * 2π) * 4` |
| **Zoom** | Масштабирование | `scale = 0.8 + sin(progress * 2π) * 0.2` |
| **Rainbow** | Цветовой сдвиг | HSL rotate: `hue = (h + progress * 1080) % 360` |

### Цветовые палитры

```typescript
// NES (Nintendo Entertainment System) - 8 цветов
nes: [
  [15, 15, 15],    // Черный
  [29, 43, 83],    // Темно-синий
  [126, 37, 83],   // Темно-фиолетовый
  [0, 135, 81],    // Темно-зеленый
  [171, 82, 54],   // Коричневый
  [95, 87, 79],    // Темно-серый
  [194, 195, 199], // Светло-серый
  [255, 241, 232]  // Белый
]

// Game Boy - 4 оттенка зелёного
gameboy: [[15, 56, 15], [48, 98, 48], [139, 172, 15], [155, 188, 15]]

// Commodore 64 - 8 характерных цветов
c64: [[0,0,0], [255,255,255], [136,0,0], [170,255,238], ...]

// Monochrome - классическая черно-белая
mono: [[0, 0, 0], [255, 255, 255]]
```

---

## 🏗️ Архитектура

```
src/
├── app/
│   ├── page.tsx          # Главная страница (Zustand state)
│   ├── layout.tsx        # Root layout с Google Fonts
│   ├── globals.css       # Retro CSS переменные
│   └── api/
│       └── generate/
│           └── route.ts  # API endpoint для генерации GIF
├── lib/
│   ├── types.ts          # TypeScript интерфейсы
│   └── store.ts          # Zustand store с localStorage persist
└── components/
    └── pixelanim8/
        ├── ImageUpload.tsx       # Drag & drop загрузка
        ├── PromptInput.tsx       # Ввод промпта
        ├── ParametersPanel.tsx   # Настройки палитры/размера
        ├── GenerateButton.tsx    # Кнопка генерации
        ├── ResultDisplay.tsx     # CRT-монитор с результатом
        └── HistoryGallery.tsx    # История генераций
```

### Ключевые технологии

| Технология | Назначение | Почему выбрана |
|------------|------------|----------------|
| **Sharp** | Обработка изображений | Быстрый нативный модуль, поддерживает resize, raw pixels |
| **gif-encoder-2** | Создание GIF | Оптимизированный энкодер с поддержкой quantization |
| **Zustand** | State management | Минимальный boilerplate, встроенный persist |
| **TailwindCSS 4** | Стилизация | CSS переменные для ретро-темы |

---

## 🧮 Математика квантования цветов

```typescript
// Евклидово расстояние в RGB пространстве
function findClosestColor(r: number, g: number, b: number, palette: number[][]): number[] {
  let minDist = Infinity;
  let closest = palette[0];
  
  for (const color of palette) {
    const dist = Math.sqrt(
      (r - color[0]) ** 2 + 
      (g - color[1]) ** 2 + 
      (b - color[2]) ** 2
    );
    if (dist < minDist) {
      minDist = dist;
      closest = color;
    }
  }
  return closest;
}
```

### RGB ↔ HSL конверсия

Для эффекта Rainbow используется конвертация в HSL:

```typescript
// RGB → HSL
function rgbToHsl(r: number, g: number, b: number): [number, number, number] {
  r /= 255; g /= 255; b /= 255;
  const max = Math.max(r, g, b), min = Math.min(r, g, b);
  let h = 0, s = 0;
  const l = (max + min) / 2;
  
  if (max !== min) {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
      case g: h = ((b - r) / d + 2) / 6; break;
      case b: h = ((r - g) / d + 4) / 6; break;
    }
  }
  return [h * 360, s, l];
}

// HSL → RGB (обратная конверсия)
function hslToRgb(h: number, s: number, l: number): [number, number, number] {
  // ... full implementation in route.ts
}
```

---

## 🚀 Как запускать

### Development

```bash
# Установка зависимостей
bun install

# Запуск dev сервера
bun run dev

# Линтинг
bun run lint
```

### Production Build

```bash
bun run build
bun run start
```

### Деплой на Netlify

Проект включает готовую конфигурацию для Netlify:

```
netlify-app/
├── netlify.toml        # Конфигурация functions
├── netlify/functions/
│   └── generate.js     # Serverless function
└── public/
    └── index.html      # Статический фронтенд
```

---

## 🔧 Как бустить новыми фишками

### 1. Добавление новых анимаций

```typescript
// В src/app/api/generate/route.ts

// 1. Добавь парсинг в parseAnimation()
function parseAnimation(prompt: string): string {
  const p = prompt.toLowerCase();
  // ... existing conditions
  if (p.includes('glitch')) return 'glitch';  // ← Новая анимация
  return 'default';
}

// 2. Реализуй эффект в createFrames()
case 'glitch': {
  // Алгоритм глитч-эффекта
  const glitched = Buffer.from(baseData);
  const sliceHeight = Math.floor(height * 0.1);
  const sliceY = Math.floor(Math.random() * (height - sliceHeight));
  const offset = Math.floor((Math.random() - 0.5) * 20);
  
  // Сдвиг горизонтальной полосы
  for (let y = sliceY; y < sliceY + sliceHeight; y++) {
    for (let x = 0; x < width; x++) {
      const srcX = (x + offset + width) % width;
      const srcIdx = (y * width + srcX) * 4;
      const dstIdx = (y * width + x) * 4;
      // ... copy pixels
    }
  }
  frames.push(glitched);
  continue;
}
```

### 2. Новые цветовые палитры

```typescript
// Добавь в объект PALETTES
const PALETTES = {
  // ... existing palettes
  sega: [
    [0, 0, 0], [0, 0, 170], [0, 170, 0], [0, 170, 170],
    [170, 0, 0], [170, 0, 170], [170, 85, 0], [170, 170, 170],
    [85, 85, 85], [85, 85, 255], [85, 255, 85], [85, 255, 255],
    [255, 85, 85], [255, 85, 255], [255, 255, 85], [255, 255, 255]
  ],
  // Sega Master System - 16 цветов
};
```

### 3. Математические эффекты для добавления

```typescript
// === ПОТОКОПИКСЕЛЬНАЯ ОТРИСОВКА ===
// Пиксели появляются один за другим
case 'pixel-reveal': {
  const totalPixels = width * height;
  const visiblePixels = Math.floor(progress * totalPixels);
  
  const revealed = Buffer.alloc(frame.length);
  for (let i = 0; i < visiblePixels * 4; i++) {
    revealed[i] = baseData[i];
  }
  frames.push(revealed);
  continue;
}

// === ЦВЕТОВАЯ ВОЛНА ===
// Прорисовка по цветам (сортировка по hue)
case 'color-wave': {
  const sortedPixels: Array<{x: number, y: number, hue: number}> = [];
  
  // Сортировка пикселей по hue
  for (let y = 0; y < height; y++) {
    for 

[truncated…]

PUBLIC HISTORY

First discoveredMar 21, 2026

IDENTITY

inferred

Identity inferred from code signals. No PROVENANCE.yml found.

Is this yours? Claim it →

METADATA

platformgithub
first seenMar 10, 2026
last updatedMar 16, 2026
last crawled20 days ago
version

README BADGE

Add to your README:

![Provenance](https://getprovenance.dev/api/badge?id=provenance:github:vlad-Stujhev1/pixel-artanim-8bit)