xpm.go (2193B)
1 package main 2 3 import ( 4 "fmt" 5 "image" 6 "image/color" 7 "strings" 8 ) 9 10 func ParseXpm(lines []string) (*image.RGBA, int) { 11 nr := 0 12 var img *image.RGBA 13 start := false 14 cformat := false 15 last := false 16 pal := make(map[string]color.RGBA) 17 var w, h, cols, cpp, y int 18 for _, l := range lines { 19 nr++ 20 if !start && !strings.HasPrefix(l, "/* XPM */") && !strings.HasPrefix(l, "! XPM2") { 21 continue 22 } 23 if !start { 24 start = true 25 continue 26 } 27 if strings.Contains(l, "static char ") { 28 cformat = true 29 continue 30 } 31 if cformat { 32 if strings.HasPrefix(l, "/*") || strings.HasPrefix(l, "//") { 33 continue 34 } 35 if strings.HasSuffix(l, "};") { 36 last = true 37 l = strings.TrimRight(l, "};") 38 } 39 l = strings.TrimRight(l, ",") 40 l = strings.Trim(l, "\"") 41 } 42 l = strings.Replace(l, "\t", " ", -1) 43 if cols == 0 { /* desc line */ 44 dsc := strings.Split(l, " ") 45 if len(dsc) != 4 { 46 return nil, 0 47 } 48 if len, _ := fmt.Sscanf(dsc[0], "%d", &w); len != 1 { 49 return nil, 0 50 } 51 if len, _ := fmt.Sscanf(dsc[1], "%d", &h); len != 1 { 52 return nil, 0 53 } 54 if len, _ := fmt.Sscanf(dsc[2], "%d", &cols); len != 1 { 55 return nil, 0 56 } 57 if len, _ := fmt.Sscanf(dsc[3], "%d", &cpp); len != 1 { 58 return nil, 0 59 } 60 upLeft := image.Point{0, 0} 61 lowRight := image.Point{w, h} 62 img = image.NewRGBA(image.Rectangle{upLeft, lowRight}) 63 continue 64 } 65 if cols > 0 { 66 dsc := strings.Split(l, " c ") 67 if len(dsc) != 2 { 68 return nil, 0 69 } 70 rgb := color.RGBA{A: 255} 71 len, _ := fmt.Sscanf(dsc[1], "#%02x%02x%02x", &rgb.R, &rgb.G, &rgb.B) 72 if len != 3 { 73 if dsc[1] != "None" { 74 return nil, 0 75 } 76 rgb.R, rgb.G, rgb.B, rgb.A = 255, 255, 255, 0 77 } 78 pal[dsc[0]] = rgb 79 cols-- 80 if cols == 0 { 81 cols = -1 // done 82 } 83 continue 84 } 85 if y >= h && strings.HasPrefix(l, "}") { 86 break 87 } 88 // image data 89 for i := 0; i < len(l); i += 1 { 90 e := i + cpp 91 if e > len(l) { 92 return nil, 0 93 } 94 sym := l[i:e] 95 rgba, ok := pal[sym] 96 if !ok { 97 return nil, 0 98 } 99 img.Set(i/cpp, y, color.RGBA(rgba)) 100 } 101 y++ 102 if y >= h && (!cformat || last) { 103 break 104 } 105 } 106 if y < h { 107 return nil, 0 108 } 109 return img, nr 110 }