// Write the spritesheet image to a file. func WriteSpriteSheet(img image.Image, folder string, name string, log *golog.Logger) (err error) { dir, err := os.Open(folder) if err != nil { err = os.MkdirAll(folder, 0775) if err != nil { log.Errorf("Unable to create sprite-sheet output folder '%s'", folder) return err } else { log.Infof("Created sprite-sheet output folder '%s'", folder) } } else { defer dir.Close() } fullname := filepath.Join(folder, name+".png") os.Remove(fullname) outFile, err := os.Create(fullname) if err != nil { log.Errorf("Couldn't create sprite-sheet output file '%s'", fullname) return err } else { defer outFile.Close() } err = png.Encode(outFile, img) if err != nil { log.Warningf("Problem writing sprite-sheet to '%s'", fullname) return err } return nil }
// Compose the spritesheet image and return an array of individual sprite data. func GenerateSpriteSheet(images []Image, log *golog.Logger) (sheet draw.Image, sprites []Sprite) { var ( sheetHeight int = 0 sheetWidth int = 0 ) sprites = make([]Sprite, 0) // calculate the size of the spritesheet and accumulate position and padding // data for the individual sprites within the sheet for _, img := range images { bounds := img.Bounds() _, name, factor := IsMagnified(img.Name) thisTopPadding := math.Ceil(factor) thisBottomPadding := thisTopPadding // see if the image dimensions are a multiple of the magnification factor fudge := 0 if math.Mod(float64(bounds.Dy()), factor) != 0 { fudge = 1 log.Warningf("Height of sprite `%s` (%dpx) is not a multiple of its magnification factor (%vx); rounding up to avoid truncated pixels.", name, bounds.Dy(), factor) } var prevBottomPadding float64 if len(sprites) == 0 { prevBottomPadding = 0 thisTopPadding = 0 } else { prevBottomPadding = float64(sprites[len(sprites)-1].BottomPadding) } thisTopPadding = math.Max(thisTopPadding, prevBottomPadding) thisTopPaddingInt := int(thisTopPadding) thisBottomPaddingInt := int(thisBottomPadding) newSprite := Sprite{ name, factor, thisTopPaddingInt, thisBottomPaddingInt, image.Rect(0, sheetHeight+thisTopPaddingInt-fudge, bounds.Dx(), sheetHeight+thisTopPaddingInt+bounds.Dy()), } sprites = append(sprites, newSprite) sheetHeight += bounds.Dy() + thisTopPaddingInt if bounds.Dx() > sheetWidth { sheetWidth = bounds.Dx() } } // create the sheet image sheet = image.NewRGBA(image.Rect(0, 0, sheetWidth, sheetHeight)) // compose the sheet for i, img := range images { draw.Draw(sheet, sprites[i].Rectangle, img, image.Pt(0, 0), draw.Src) } return sheet, sprites }
// Take a folder name, read all the images within, and return them in an array. func ReadImageFolder(path string, log *golog.Logger) (images []Image, err error) { dir, err := os.Open(path) if err != nil { log.Errorf("Couldn't open folder '%s'", path) return nil, err } else { defer dir.Close() } dirInfo, err := dir.Stat() if err != nil { log.Errorf("Couldn't gather information for folder '%s'", path) return nil, err } if !dirInfo.IsDir() { // just ignore the request if it isn't a folder return nil, nil } names, err := dir.Readdirnames(0) if err != nil { log.Errorf("Problem gathering names of image files in '%s'", path) return nil, err } // put these in a canonical order, otherwise it'll be platform-specific sort.Strings(names) images = make([]Image, 0) for _, name := range names { fullName := filepath.Join(path, name) imgFile, err := os.Open(fullName) if err != nil { log.Errorf("Couldn't open image file '%s'", fullName) continue } else { defer imgFile.Close() } imgInfo, err := imgFile.Stat() if err != nil { log.Errorf("Couldn't gather information for image file '%s'", fullName) } if imgInfo.IsDir() { // skip non-files continue } ext := strings.ToLower(filepath.Ext(name)) if ext == ".png" { img, err := png.Decode(imgFile) if err != nil { log.Errorf("Problem decoding png image in '%s'", fullName) continue } name = name[0 : len(name)-len(ext)] images = append(images, Image{name, img}) } else if ext == ".jpg" || ext == ".jpeg" { img, err := jpeg.Decode(imgFile) if err != nil { log.Errorf("Problem decoding jpeg image in '%s'", fullName) continue } name = name[0 : len(name)-len(ext)] images = append(images, Image{name, img}) } else { log.Debugf("Ignoring unrecognized file '%s'", fullName) } } if len(images) == 0 { log.Warningf("Folder '%s' contains no images; no sprite-sheet will be generated", path) } return images, nil }