Skip to content

Commit d27c8f7

Browse files
committed
initial commit
0 parents  commit d27c8f7

File tree

9 files changed

+262
-0
lines changed

9 files changed

+262
-0
lines changed

Diff for: .gitignore

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
### Go template
2+
# If you prefer the allow list template instead of the deny list, see community template:
3+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
4+
#
5+
# Binaries for programs and plugins
6+
*.exe
7+
*.exe~
8+
*.dll
9+
*.so
10+
*.dylib
11+
12+
# Test binary, built with `go test -c`
13+
*.test
14+
15+
# Output of the go coverage tool, specifically when used with LiteIDE
16+
*.out
17+
18+
# Dependency directories (remove the comment below to include it)
19+
# vendor/
20+
21+
# Go workspace file
22+
go.work
23+
24+
### GoLand template
25+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
26+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
27+
28+
# User-specific stuff
29+
.idea/**/workspace.xml
30+
.idea/**/tasks.xml
31+
.idea/**/usage.statistics.xml
32+
.idea/**/dictionaries
33+
.idea/**/shelf
34+
35+
# AWS User-specific
36+
.idea/**/aws.xml
37+
38+
# Generated files
39+
.idea/**/contentModel.xml
40+
41+
# Sensitive or high-churn files
42+
.idea/**/dataSources/
43+
.idea/**/dataSources.ids
44+
.idea/**/dataSources.local.xml
45+
.idea/**/sqlDataSources.xml
46+
.idea/**/dynamic.xml
47+
.idea/**/uiDesigner.xml
48+
.idea/**/dbnavigator.xml
49+
50+
# Gradle
51+
.idea/**/gradle.xml
52+
.idea/**/libraries
53+
54+
# Gradle and Maven with auto-import
55+
# When using Gradle or Maven with auto-import, you should exclude module files,
56+
# since they will be recreated, and may cause churn. Uncomment if using
57+
# auto-import.
58+
# .idea/artifacts
59+
# .idea/compiler.xml
60+
# .idea/jarRepositories.xml
61+
# .idea/modules.xml
62+
# .idea/*.iml
63+
# .idea/modules
64+
# *.iml
65+
# *.ipr
66+
67+
# CMake
68+
cmake-build-*/
69+
70+
# Mongo Explorer plugin
71+
.idea/**/mongoSettings.xml
72+
73+
# File-based project format
74+
*.iws
75+
76+
# IntelliJ
77+
out/
78+
79+
# mpeltonen/sbt-idea plugin
80+
.idea_modules/
81+
82+
# JIRA plugin
83+
atlassian-ide-plugin.xml
84+
85+
# Cursive Clojure plugin
86+
.idea/replstate.xml
87+
88+
# SonarLint plugin
89+
.idea/sonarlint/
90+
91+
# Crashlytics plugin (for Android Studio and IntelliJ)
92+
com_crashlytics_export_strings.xml
93+
crashlytics.properties
94+
crashlytics-build.properties
95+
fabric.properties
96+
97+
# Editor-based Rest Client
98+
.idea/httpRequests
99+
100+
# Android studio 3.1+ serialized cache file
101+
.idea/caches/build_file_checksums.ser
102+
103+
#gifs/*
104+
frames/*
105+
main

Diff for: .idea/.gitignore

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/terminal-dance.iml

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Terminal Dance
2+
3+
4+
## Credits
5+
6+
- [GIPHY - Be Animated](https://giphy.com/)

Diff for: gifs/tom.gif

5.89 MB
Loading

Diff for: go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/tasnimzotder/terminal-dance
2+
3+
go 1.21.1

Diff for: main.go

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"image"
6+
"image/color"
7+
"image/gif"
8+
"log"
9+
"os"
10+
"time"
11+
)
12+
13+
const (
14+
CHARS = " .:-=+*#%@"
15+
REQ_SIZE = 250
16+
)
17+
18+
// reduce the size of the gif to 100x100
19+
func resizeFrames(frames []*image.Paletted, width, height int) []*image.Paletted {
20+
hScale := float64(height) / float64(frames[0].Bounds().Dy())
21+
wScale := float64(width) / float64(frames[0].Bounds().Dx())
22+
23+
resizedFrames := make([]*image.Paletted, len(frames))
24+
25+
for i, frame := range frames {
26+
newWidth := int(float64(frame.Bounds().Dx()) * wScale)
27+
newHeight := int(float64(frame.Bounds().Dy()) * hScale)
28+
29+
resizedFrames[i] = image.NewPaletted(image.Rect(0, 0, newWidth, newHeight), frame.Palette)
30+
31+
for x := 0; x < newWidth; x++ {
32+
for y := 0; y < newHeight; y++ {
33+
resizedFrames[i].Set(x, y, frame.At(int(float64(x)/wScale), int(float64(y)/hScale)))
34+
}
35+
36+
}
37+
38+
}
39+
40+
return resizedFrames
41+
}
42+
43+
func readGif(fileName string) *gif.GIF {
44+
file, err := os.Open("gifs/tom.gif")
45+
if err != nil {
46+
log.Fatalf("Error opening file: %s", err)
47+
}
48+
defer func(file *os.File) {
49+
err := file.Close()
50+
if err != nil {
51+
log.Fatalf("Error closing file: %s", err)
52+
}
53+
}(file)
54+
55+
gifImage, err := gif.DecodeAll(file)
56+
if err != nil {
57+
log.Fatalf("Error decoding file: %s", err)
58+
}
59+
60+
return gifImage
61+
}
62+
63+
func readFrames(fileName string) []*image.Paletted {
64+
gifImage := readGif(fileName)
65+
// resize the gif
66+
gifImage.Image = resizeFrames(gifImage.Image, REQ_SIZE, REQ_SIZE)
67+
68+
return gifImage.Image
69+
}
70+
71+
// convert color to grayscale
72+
func grayscaleChar(color color.Color) int {
73+
r, g, b, _ := color.RGBA()
74+
val := int(0.299*float64(r)+0.587*float64(g)+0.114*float64(b)) / 256
75+
76+
val = val * (len(CHARS) - 1) / 255
77+
78+
return val
79+
}
80+
81+
func clearConsole() {
82+
fmt.Print("\033[H\033[2J")
83+
}
84+
85+
func main() {
86+
fileName := "gifs/tom.gif"
87+
gifImage := readFrames(fileName)
88+
89+
frameValues := make([][]int, len(gifImage))
90+
91+
for i, frame := range gifImage {
92+
frameValues[i] = make([]int, frame.Bounds().Dx()*frame.Bounds().Dy())
93+
for x := 0; x < frame.Bounds().Dx(); x++ {
94+
for y := 0; y < frame.Bounds().Dy(); y++ {
95+
frameValues[i][x*frame.Bounds().Dy()+y] = grayscaleChar(frame.At(x, y))
96+
}
97+
}
98+
}
99+
100+
for {
101+
for i, frame := range frameValues {
102+
// roate the image 90 degrees
103+
for y := 0; y < gifImage[i].Bounds().Dy(); y++ {
104+
for x := 0; x < gifImage[i].Bounds().Dx(); x++ {
105+
char := CHARS[frame[x*gifImage[i].Bounds().Dy()+y]]
106+
fmt.Printf("%c%c%c", char, char, char)
107+
}
108+
fmt.Printf("\n")
109+
}
110+
111+
fmt.Printf("\n\n")
112+
113+
time.Sleep(30 * time.Millisecond)
114+
clearConsole()
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)