Skip to content

Instantly share code, notes, and snippets.

@Deleplace
Created December 8, 2016 13:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Deleplace/50387a5d1c22acb2647d16fa74dcac29 to your computer and use it in GitHub Desktop.
Save Deleplace/50387a5d1c22acb2647d16fa74dcac29 to your computer and use it in GitHub Desktop.
Brutal extraction of the thumbnail PNG of a Sketchup file
package main
import (
"bytes"
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
)
// PNG 8-byte header
const hexPNGSignature = "89504E470D0A1A0A"
// Four bytes "IEND"
const hexIEND = "49454E44"
func main() {
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Usage:")
fmt.Fprintln(os.Stderr, " ", os.Args[0], "file.skp")
return
}
skpFilename := os.Args[1]
data, err := ioutil.ReadFile(skpFilename)
checkerr(err)
PNGsignature, err := hex.DecodeString(hexPNGSignature)
checkerr(err)
IEND, err := hex.DecodeString(hexIEND)
checkerr(err)
var offset = 0
n := 0
for {
i := bytes.Index(data[offset+1:], PNGsignature)
if i == -1 {
if offset == 0 {
fmt.Fprintln(os.Stderr, "Signature", hexPNGSignature, "not found in", skpFilename)
}
break
}
offset += 1 + i
// This is an approximation: jump to next IEND occurrence.
// But it would be more correct to scan PNG chunks until a proper IEND chunk is encountered.
j := bytes.Index(data[offset:], IEND)
if j == -1 {
panic("IEND not found :(")
}
pngdata := data[offset : offset+j]
pngfilename := strings.Replace(skpFilename, ".skp", "", -1) + "." + strconv.Itoa(n) + ".png"
ioutil.WriteFile(pngfilename, pngdata, 0777)
n++
if n == 2 {
// We are currently interested only in first 2 pictures
break
}
}
fmt.Println("Extracted", n, "png files (out of a total of", bytes.Count(data, PNGsignature), "png).")
}
func checkerr(err error) {
if err != nil {
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment