123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /*
- * Public Domain Software
- *
- * I (Matthias Ladkau) am the author of the source code in this file.
- * I have placed the source code in this file in the public domain.
- *
- * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
- */
- /*
- Package imageutil contains utility function to create/manipulate images.
- Asciiraster contains support for raster fonts for images. Using RenderSymbols you
- can add text and symbols to an image. By specifying a symbol map containing ASCII art
- it is possible to define how each rune should be rendered.
- */
- package imageutil
- import (
- "bufio"
- "bytes"
- "fmt"
- "image"
- "image/color"
- "unicode"
- )
- /*
- SymbolSpacing defines the spacing in pixels between two symbols
- */
- var SymbolSpacing = 1
- /*
- SpaceSymbolSpacing defines the space in pixels of a space character if the
- character is not defined in the font map
- */
- var SpaceSymbolSpacing = 5
- /*
- RenderSymbols renders the symbols in the given string str at the given point p in the
- given Image img in the color col using smap as symbol mapping.
- */
- func RenderSymbols(img image.Image, p image.Point, str string,
- col color.Color, smap map[rune]string) (image.Image, error) {
- var offset int
- imgc := wrapImage(img)
- // Iterate over the string
- for _, r := range str {
- sym, ok := smap[r]
- if !ok {
- if unicode.IsSpace(r) {
- // If a space character is encountered and it is not defined in the map
- // then just move the offset and continue
- offset += SpaceSymbolSpacing
- continue
- }
- return nil, fmt.Errorf("Cannot find mapping for rune: %q", r)
- }
- sline := 0
- rwidth := 0
- // Go through the symbold line by line
- scanner := bufio.NewScanner(bytes.NewBufferString(sym))
- for scanner.Scan() {
- line := scanner.Text()
- // Set max width of symbol
- if l := len(line); rwidth < l {
- rwidth = l
- }
- soffset := 0
- for _, sr := range line {
- // Draw each pixel
- if !(unicode.IsSpace(sr) || unicode.IsControl(sr)) {
- imgc.Set(offset+soffset+p.X, sline+p.Y, col)
- }
- soffset++
- }
- sline++
- }
- // Advance the offset
- offset += rwidth + SymbolSpacing
- }
- return imgc, nil
- }
- /*
- wrapImage wraps a given image.
- */
- func wrapImage(img image.Image) *imageWrapper {
- return &imageWrapper{img, make(map[image.Point]color.Color)}
- }
- /*
- imageWrapper is a wrapper class for images which allows setting single pixels.
- */
- type imageWrapper struct {
- image.Image // Original image
- pixMap map[image.Point]color.Color // Modified pixels
- }
- /*
- Set sets the color of the pixel at (x, y).
- */
- func (m *imageWrapper) Set(x, y int, c color.Color) {
- m.pixMap[image.Point{x, y}] = c
- }
- /*
- At returns the color of the pixel at (x, y).
- */
- func (m *imageWrapper) At(x, y int) color.Color {
- if c := m.pixMap[image.Point{x, y}]; c != nil {
- return c
- }
- return m.Image.At(x, y)
- }
|