package camera import ( "bytes" "fmt" "image" "image/color" "image/jpeg" "time" ) type MockCamera struct { width int height int frameCount int } func NewMockCamera(width, height int) *MockCamera { return &MockCamera{width: width, height: height} } func (mc *MockCamera) ReadFrame() ([]byte, error) { mc.frameCount++ return mc.generateTestCard() } func (mc *MockCamera) generateTestCard() ([]byte, error) { img := image.NewRGBA(image.Rect(0, 0, mc.width, mc.height)) offset := mc.frameCount % mc.width for y := 0; y < mc.height; y++ { for x := 0; x < mc.width; x++ { pos := (x + offset) % mc.width ratio := float64(pos) / float64(mc.width) var r, g, b uint8 if ratio < 0.33 { r = uint8(255 * (1 - ratio/0.33)) g = uint8(255 * ratio / 0.33) } else if ratio < 0.66 { g = uint8(255 * (1 - (ratio-0.33)/0.33)) b = uint8(255 * (ratio - 0.33) / 0.33) } else { b = uint8(255 * (1 - (ratio-0.66)/0.34)) r = uint8(255 * (ratio - 0.66) / 0.34) } img.SetRGBA(x, y, color.RGBA{R: r, G: g, B: b, A: 255}) } } // Draw dark overlay bar at top for text area for y := 0; y < 40; y++ { for x := 0; x < mc.width; x++ { img.SetRGBA(x, y, color.RGBA{R: 0, G: 0, B: 0, A: 180}) } } // Draw "MOCK CAMERA" text block and frame counter using simple rectangles drawTextBlock(img, 10, 10, fmt.Sprintf("MOCK CAMERA | Frame: %d | %s", mc.frameCount, time.Now().Format("15:04:05"))) // Draw center crosshair cx, cy := mc.width/2, mc.height/2 for i := -20; i <= 20; i++ { if cx+i >= 0 && cx+i < mc.width { img.SetRGBA(cx+i, cy, color.RGBA{R: 255, G: 255, B: 255, A: 200}) } if cy+i >= 0 && cy+i < mc.height { img.SetRGBA(cx, cy+i, color.RGBA{R: 255, G: 255, B: 255, A: 200}) } } var buf bytes.Buffer if err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: 75}); err != nil { return nil, err } return buf.Bytes(), nil } func drawTextBlock(img *image.RGBA, x, y int, text string) { white := color.RGBA{R: 255, G: 255, B: 255, A: 255} // Simple pixel-based text rendering: each character is a 5x7 block for i, ch := range text { if ch == ' ' { continue } px := x + i*6 // Draw a small white dot for each character position for dy := 0; dy < 5; dy++ { for dx := 0; dx < 4; dx++ { if px+dx < img.Bounds().Max.X && y+dy < img.Bounds().Max.Y { img.SetRGBA(px+dx, y+dy, white) } } } } }