<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
)

type atlas struct {
	dimX, dimY int
	space      int
	sprites    []sprite
	img        *image.RGBA
	data       []byte
}

func (a *atlas) readDir(dir string) error {
	var area int

	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}

	a.sprites = make([]sprite, len(files))

	for i := range a.sprites {
		s, err := readSprite(dir, files[i].Name(), a.space)
		if err != nil {
			return err
		}
		area += s.area
		a.sprites[i] = s
	}

	if area > a.dimX*a.dimY {
		return fmt.Errorf("atlas to small")
	}

	return nil
}

func readSprite(dir, name string, space int) (s sprite, err error) {
	path := path.Join(dir, name)
	reader, err := os.Open(path)
	if err != nil {
		return
	}
	defer reader.Close()

	img, _, err := image.Decode(reader)
	if err != nil {
		return
	}

	s.Name = strings.TrimSuffix(name, filepath.Ext(name))
	s.img = img
	rect := img.Bounds()
	s.Size = Size{rect.Dx() + space, rect.Dy() + space}
	s.area = s.Size.X * s.Size.Y
	return
}

func (a *atlas) pack() error {

	// we want to place the largest sprite first
	sort.Sort(sort.Reverse(ByArea(a.sprites)))

	a.img = image.NewRGBA(image.Rect(0, 0, a.dimX, a.dimY))

	n := Node{rect: image.Rect(0, 0, a.dimX, a.dimY)}

	a.data = []byte("[")

	for i := range a.sprites {
		s := &a.sprites[i]
		node := n.insert(s)

		// need to remove all space added around the sprite
		s.Size.X -= a.space
		s.Size.Y -= a.space

		j, err := json.MarshalIndent(s, "", " ")
		if err != nil {
			return err
		}
		a.data = append(a.data, '\n')
		a.data = append(a.data, j...)

		if node != nil {
			draw.Draw(a.img, node.rect, s.img, image.ZP, draw.Src)
		} else {
			return fmt.Errorf("could not place %s\n", s.Name)
		}

	}

	a.data = append(a.data, []byte("]")...)

	return nil
}

func (a *atlas) write(name string) error {
	imageName := name + ".png"
	dataName := name + ".json"

	imageWriter, err := os.Create(imageName)
	if err != nil {<commit_msg>Comment atlas functions<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
)

type atlas struct {
	dimX, dimY int
	space      int
	sprites    []sprite
	img        *image.RGBA
	data       []byte
}

// readDir takes a directory and processes the sprites in it\
// if it encounters a non image file it crashes
func (a *atlas) readDir(dir string) error {
	var area int

	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}

	a.sprites = make([]sprite, len(files))

	for i := range a.sprites {
		s, err := readSprite(dir, files[i].Name(), a.space)
		if err != nil {
			return err
		}
		area += s.area
		a.sprites[i] = s
	}

	if area > a.dimX*a.dimY {
		return fmt.Errorf("atlas to small")
	}

	return nil
}

// readSprite takes a file and returns the sprite
func readSprite(dir, name string, space int) (s sprite, err error) {
	path := path.Join(dir, name)
	reader, err := os.Open(path)
	if err != nil {
		return
	}
	defer reader.Close()

	img, _, err := image.Decode(reader)
	if err != nil {
		return
	}

	s.Name = strings.TrimSuffix(name, filepath.Ext(name))
	s.img = img
	rect := img.Bounds()
	s.Size = Size{rect.Dx() + space, rect.Dy() + space}
	s.area = s.Size.X * s.Size.Y
	return
}

// pack finds a way to layout all the atlas' sprites so that
// they fit inside the atlas nicely
func (a *atlas) pack() error {

	// we want to place the largest sprite first
	sort.Sort(sort.Reverse(ByArea(a.sprites)))

	a.img = image.NewRGBA(image.Rect(0, 0, a.dimX, a.dimY))

	n := Node{rect: image.Rect(0, 0, a.dimX, a.dimY)}

	a.data = []byte("[")

	for i := range a.sprites {
		s := &a.sprites[i]
		node := n.insert(s)

		// need to remove all space added around the sprite
		s.Size.X -= a.space
		s.Size.Y -= a.space

		j, err := json.MarshalIndent(s, "", " ")
		if err != nil {
			return err
		}
		a.data = append(a.data, '\n')
		a.data = append(a.data, j...)

		if node != nil {
			draw.Draw(a.img, node.rect, s.img, image.ZP, draw.Src)
		} else {
			return fmt.Errorf("could not place %s\n", s.Name)
		}

	}

	a.data = append(a.data, []byte("]")...)

	return nil
}

// write creates name.png and name.json
// for the atlas texture and data
func (a *atlas) write(name string) error {
	imageName := name + ".png"
	dataName := name + ".json"

	imageWriter, err := os.Create(imageName)
	if err != nil {
{'fraction_non_alphanumeric': 0.1675206059255959, 'fraction_numerical': 0.0017821341055914458, 'mean_word_length': 2.8607050730868444, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6373729', 'n_tokens_mistral': 1912, 'n_tokens_neox': 1803, 'n_words': 498}