Skip to content

Commit

Permalink
feat(fun): Add deepfry command to process and modify images
Browse files Browse the repository at this point in the history
  • Loading branch information
Paranoia8972 committed Jan 19, 2025
1 parent e178e3c commit e5d34f3
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (

require (
github.com/bwmarrin/dgvoice v0.0.0-20210225172318-caaac756e02e
github.com/disintegration/imaging v1.6.2
github.com/fatih/color v1.17.0
github.com/fogleman/gg v1.3.0
github.com/gorilla/websocket v1.5.3 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd
github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/elliotwms/fakediscord v0.16.4 h1:yHuiwdbLSbg4MbXzhcD9JxWMn9Fi2CDSheTVFT4irQo=
github.com/elliotwms/fakediscord v0.16.4/go.mod h1:uw9CFPmgeR1f2NoOdzv87gyzmQxAhPQX0WCyEFOhQKo=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
Expand Down Expand Up @@ -50,6 +52,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
Expand Down
12 changes: 12 additions & 0 deletions internal/pkg/commands/A_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,18 @@ func RegisterCommands(s *discordgo.Session, cfg *config.Config) {
},
},
},
{
Name: "deepfry",
Description: "Deepfries an image",
Options: []*discordgo.ApplicationCommandOption{
{
Name: "image",
Description: "Image to deepfry",
Type: discordgo.ApplicationCommandOptionAttachment,
Required: true,
},
},
},
}

commands := make([]*discordgo.ApplicationCommand, len(Commands))
Expand Down
150 changes: 150 additions & 0 deletions internal/pkg/commands/fun/deepfry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package fun

import (
"bytes"
"image"
"image/color"
"image/jpeg"
"math"
"math/rand"
"net/http"

"github.com/bwmarrin/discordgo"
"github.com/disintegration/imaging"
"github.com/fogleman/gg"
)

func applyDeepfry(img image.Image) image.Image {
bounds := img.Bounds()
dc := gg.NewContext(bounds.Dx(), bounds.Dy())
dc.DrawImage(img, 0, 0)

for x := 0; x < bounds.Dx(); x++ {
for y := 0; y < bounds.Dy(); y++ {
r, g, b, a := img.At(x, y).RGBA()
r = (r * 2) & 0xffff
g = (g * 2) & 0xffff
b = (b * 2) & 0xffff
dc.SetRGBA255(int(r>>8), int(g>>8), int(b>>8), int(a>>8))
dc.SetPixel(x, y)
}
}

for i := 0; i < (bounds.Dx()*bounds.Dy())/10; i++ {
x := rand.Intn(bounds.Dx())
y := rand.Intn(bounds.Dy())
dc.SetRGBA255(rand.Intn(255), rand.Intn(255), rand.Intn(255), 255)
dc.SetPixel(x, y)
}

img = dc.Image()
bounds = img.Bounds()
adjusted := image.NewRGBA(bounds)

for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
r, g, b, a := img.At(x, y).RGBA()

r = r >> 8
g = g >> 8
b = b >> 8

contrast := 2.0
r = uint32(math.Min(255, math.Max(0, float64(r)*contrast)))
g = uint32(math.Min(255, math.Max(0, float64(g)*contrast)))
b = uint32(math.Min(255, math.Max(0, float64(b)*contrast)))

adjusted.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a >> 8)})
}
}

dc = gg.NewContext(bounds.Dx(), bounds.Dy())
dc.DrawImage(adjusted, 0, 0)

for i := 0; i < 5; i++ {
buf := new(bytes.Buffer)
jpeg.Encode(buf, dc.Image(), &jpeg.Options{Quality: 1})
tmpImg, _ := jpeg.Decode(buf)
dc = gg.NewContext(bounds.Dx(), bounds.Dy())
dc.DrawImage(tmpImg, 0, 0)
}

return dc.Image()
}

func DeepfryCommand(s *discordgo.Session, i *discordgo.InteractionCreate) {
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
})
if err != nil {
return
}

options := i.ApplicationCommandData().Options
if len(options) == 0 {
RespondWithMessage(s, i, "Please provide an image to deepfry")
return
}

attachment := i.ApplicationCommandData().Resolved.Attachments[options[0].Value.(string)]
if attachment == nil {
content := "Please provide a valid image attachment"
s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: &content,
})
return
}

resp, err := http.Get(attachment.URL)
if err != nil {
RespondWithMessage(s, i, "Failed to download image")
return
}
defer resp.Body.Close()

img, _, err := image.Decode(resp.Body)
if err != nil {
RespondWithMessage(s, i, "Failed to decode image")
return
}

deepfried := applyDeepfry(img)

buf := new(bytes.Buffer)
jpeg.Encode(buf, deepfried, &jpeg.Options{Quality: 1})

_, err = s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Files: []*discordgo.File{
{
Name: "deepfried.jpg",
Reader: buf,
},
},
})
if err != nil {
content := "Failed to send deepfried image"
s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: &content,
})
return
}
}

func DeepFryImage(inputPath, outputPath string) error {
src, err := imaging.Open(inputPath)
if err != nil {
return err
}

adjusted := imaging.AdjustBrightness(src, 30)
adjusted = imaging.AdjustContrast(adjusted, 50)

adjusted = imaging.AdjustSaturation(adjusted, 80)

err = imaging.Save(adjusted, outputPath)
if err != nil {
return err
}

return nil
}
22 changes: 22 additions & 0 deletions internal/pkg/commands/fun/fun.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package fun

import (
"github.com/Paranoia8972/PixelBot/internal/app/config"
"github.com/bwmarrin/discordgo"
)

var cfg *config.Config

func init() {
cfg = config.LoadConfig()
}

func RespondWithMessage(s *discordgo.Session, i *discordgo.InteractionCreate, message string) {
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: message,
Flags: 64,
},
})
}
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/Paranoia8972/PixelBot/internal/db"
"github.com/Paranoia8972/PixelBot/internal/events"
"github.com/Paranoia8972/PixelBot/internal/pkg/commands"
"github.com/Paranoia8972/PixelBot/internal/pkg/commands/fun"
"github.com/Paranoia8972/PixelBot/internal/pkg/commands/games"
"github.com/Paranoia8972/PixelBot/internal/pkg/commands/moderation"
"github.com/Paranoia8972/PixelBot/internal/pkg/transcript"
Expand Down Expand Up @@ -109,6 +110,8 @@ func main() {
commands.StickyCommand(s, i)
case "tictactoe":
games.CreateTicTacToeCommand(s, i)
case "deepfry":
fun.DeepfryCommand(s, i)
}
}
})
Expand Down

0 comments on commit e5d34f3

Please sign in to comment.