Skip to content

Commit

Permalink
Misc changes and docker nft volume
Browse files Browse the repository at this point in the history
  • Loading branch information
b-j-roberts committed Nov 25, 2024
1 parent 04ff04c commit 7498f5b
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 90 deletions.
82 changes: 4 additions & 78 deletions backend/routes/nft.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package routes

import (
"context"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -244,94 +243,21 @@ func getNftPixelData(w http.ResponseWriter, r *http.Request) {
return
}

// Get colors from postgres for consistent palette
colors, err := core.PostgresQuery[string]("SELECT hex FROM colors ORDER BY key")
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to get color palette")
return
}

// Try to read from file first
roundNumber := os.Getenv("ROUND_NUMBER")
if roundNumber == "" {
roundNumber = "1" // Default to round 1 if not set
}

filename := fmt.Sprintf("./nfts/round-%s/images/nft-%s.png", roundNumber, tokenId)
filename := fmt.Sprintf("nfts/round-%s/images/nft-%s.png", roundNumber, tokenId)
fileBytes, err := os.ReadFile(filename)
if err != nil {
filename = fmt.Sprintf("nfts/round-%s/images/nft-%s.png", roundNumber, tokenId)
fileBytes, err = os.ReadFile(filename)
if err != nil {
// If file not found, fallback to canvas data
ctx := context.Background()
canvas, err := core.ArtPeaceBackend.Databases.Redis.Get(ctx, "canvas").Result()
if err != nil {
routeutils.WriteErrorJson(w, http.StatusNotFound, "NFT image not found and canvas data unavailable")
return
}

// Create response using NFT dimensions
response := struct {
Width int `json:"width"`
Height int `json:"height"`
PixelData []int `json:"pixelData"`
}{
Width: nftData.Width,
Height: nftData.Height,
PixelData: make([]int, nftData.Width*nftData.Height),
}

bitWidth := core.ArtPeaceBackend.CanvasConfig.ColorsBitWidth
canvasWidth := int(core.ArtPeaceBackend.CanvasConfig.Canvas.Width)

// Extract pixel data from canvas
for y := 0; y < nftData.Height; y++ {
for x := 0; x < nftData.Width; x++ {
pos := nftData.Position + x + (y * canvasWidth)
bitPos := uint(pos) * bitWidth
bytePos := int(bitPos / 8)
bitOffset := uint(bitPos % 8)

// Handle out of bounds as transparent (0xFF)
if bytePos >= len(canvas) {
response.PixelData[x+y*nftData.Width] = 0xFF
continue
}

var colorIdx int
if bitOffset <= 3 {
colorIdx = int((canvas[bytePos] >> (8 - bitWidth - bitOffset)) & ((1 << bitWidth) - 1))
} else {
if bytePos+1 >= len(canvas) {
response.PixelData[x+y*nftData.Width] = 0xFF
continue
}
colorIdx = int(((uint16(canvas[bytePos])<<8)|uint16(canvas[bytePos+1]))>>(16-bitWidth-bitOffset)) & ((1 << bitWidth) - 1)
}

// Validate color index
if colorIdx >= len(colors) {
response.PixelData[x+y*nftData.Width] = 0xFF
} else {
response.PixelData[x+y*nftData.Width] = colorIdx
}
}
}

jsonResponse, err := json.Marshal(response)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to create response")
return
}

routeutils.WriteDataJson(w, string(jsonResponse))
return
}
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to read image file")
return
}

// If we have the file, process it using imageToPixelData
pixelData, err := imageToPixelData(fileBytes)
pixelData, err := imageToPixelData(fileBytes, 10)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to process image")
return
Expand Down
24 changes: 14 additions & 10 deletions backend/routes/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func hexToRGBA(colorBytes string) color.RGBA {
return color.RGBA{uint8(r), uint8(g), uint8(b), 255}
}

func imageToPixelData(imageData []byte) ([]int, error) {
func imageToPixelData(imageData []byte, scaleFactor int) ([]int, error) {
img, _, err := image.Decode(bytes.NewReader(imageData))
if err != nil {
return nil, err
Expand All @@ -96,16 +96,20 @@ func imageToPixelData(imageData []byte) ([]int, error) {

bounds := img.Bounds()
width, height := bounds.Max.X, bounds.Max.Y
pixelData := make([]int, width*height)

for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
scaledWidth := width / scaleFactor
scaledHeight := height / scaleFactor
pixelData := make([]int, scaledWidth*scaledHeight)

for y := 0; y < height; y += scaleFactor {
for x := 0; x < width; x += scaleFactor {
newX := x / scaleFactor
newY := y / scaleFactor
rgba := color.RGBAModel.Convert(img.At(x, y)).(color.RGBA)
if rgba.A < 128 { // Consider pixels with less than 50% opacity as transparent
pixelData[y*width+x] = 0xFF
pixelData[newY*scaledWidth+newX] = 0xFF
} else {
closestIndex := findClosestColor(rgba, palette)
pixelData[y*width+x] = closestIndex
pixelData[newY*scaledWidth+newX] = closestIndex
}
}
}
Expand Down Expand Up @@ -229,7 +233,7 @@ func buildTemplateImg(w http.ResponseWriter, r *http.Request) {
return
}

imageData, err := imageToPixelData(fileBytes)
imageData, err := imageToPixelData(fileBytes, 1)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to convert image to pixel data")
return
Expand Down Expand Up @@ -314,7 +318,7 @@ func addTemplateImg(w http.ResponseWriter, r *http.Request) {

r.Body.Close()

imageData, err := imageToPixelData(fileBytes)
imageData, err := imageToPixelData(fileBytes, 1)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to convert image to pixel data")
return
Expand Down Expand Up @@ -473,7 +477,7 @@ func getTemplatePixelData(w http.ResponseWriter, r *http.Request) {
}

// Convert image to pixel data using existing function
pixelData, err := imageToPixelData(fileBytes)
pixelData, err := imageToPixelData(fileBytes, 1)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to process image")
return
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ services:
- ART_PEACE_END_TIME=3000000000
- ART_PEACE_HOST=0328ced46664355fc4b885ae7011af202313056a7e3d44827fb24c9d3206aaa0
- ROUND_NUMBER=1
volumes:
- nfts:/app/nfts
consumer:
build:
dockerfile: backend/Dockerfile.consumer
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/configs/backend.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"host": "api.art-peace.net",
"port": 8081,
"port": 8080,
"consumer_port": 8081,
"scripts": {
"place_pixel_devnet": "../tests/integration/local/place_pixel.sh",
"place_extra_pixels_devnet": "../tests/integration/local/place_extra_pixels.sh",
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/tabs/nfts/NFTItem.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@
margin: 0;
padding: 0;
image-rendering: pixelated;
cursor: pointer;

transition: all 0.2s;
}

/* pulse animation */
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}

.NFTItem__image:hover {
animation: pulse 1s infinite;
transform: scale(1.03);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
}

.NFTItem__image:active {
transform: scale(1);
}

.NFTItem__buttons {
Expand Down
2 changes: 1 addition & 1 deletion onchain/src/art_peace.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ pub mod ArtPeace {
let test_address = starknet::contract_address_const::<
0x328ced46664355fc4b885ae7011af202313056a7e3d44827fb24c9d3206aaa0
>();
self.extra_pixels.write(test_address, 1000);
self.extra_pixels.write(test_address, 100000);
}
self.devmode.write(init_params.devmode);

Expand Down

0 comments on commit 7498f5b

Please sign in to comment.