loader.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gltf
  5. import (
  6. "bytes"
  7. "encoding/base64"
  8. "encoding/binary"
  9. "encoding/json"
  10. "fmt"
  11. "image"
  12. "image/draw"
  13. "io"
  14. "io/ioutil"
  15. "os"
  16. "path/filepath"
  17. "strings"
  18. "unsafe"
  19. "github.com/g3n/engine/camera"
  20. "github.com/g3n/engine/core"
  21. "github.com/g3n/engine/geometry"
  22. "github.com/g3n/engine/gls"
  23. "github.com/g3n/engine/graphic"
  24. "github.com/g3n/engine/material"
  25. "github.com/g3n/engine/math32"
  26. "github.com/g3n/engine/texture"
  27. )
  28. // ParseJSON parses the glTF data from the specified JSON file
  29. // and returns a pointer to the parsed structure.
  30. func ParseJSON(filename string) (*GLTF, error) {
  31. // Opens file
  32. f, err := os.Open(filename)
  33. if err != nil {
  34. return nil, err
  35. }
  36. // Extract path from file
  37. path := filepath.Dir(filename)
  38. defer f.Close()
  39. return ParseJSONReader(f, path)
  40. }
  41. // ParseJSONReader parses the glTF JSON data from the specified reader
  42. // and returns a pointer to the parsed structure
  43. func ParseJSONReader(r io.Reader, path string) (*GLTF, error) {
  44. g := new(GLTF)
  45. g.path = path
  46. dec := json.NewDecoder(r)
  47. err := dec.Decode(g)
  48. if err != nil {
  49. return nil, err
  50. }
  51. return g, nil
  52. }
  53. // ParseBin parses the glTF data from the specified binary file
  54. // and returns a pointer to the parsed structure.
  55. func ParseBin(filename string) (*GLTF, error) {
  56. // Opens file
  57. f, err := os.Open(filename)
  58. if err != nil {
  59. return nil, err
  60. }
  61. // Extract path from file
  62. path := filepath.Dir(filename)
  63. defer f.Close()
  64. return ParseBinReader(f, path)
  65. }
  66. // ParseBinReader parses the glTF data from the specified binary reader
  67. // and returns a pointer to the parsed structure
  68. func ParseBinReader(r io.Reader, path string) (*GLTF, error) {
  69. // Reads header
  70. var header GLBHeader
  71. err := binary.Read(r, binary.LittleEndian, &header)
  72. if err != nil {
  73. return nil, err
  74. }
  75. // Checks magic and version
  76. if header.Magic != GLBMagic {
  77. return nil, fmt.Errorf("Invalid GLB Magic field")
  78. }
  79. if header.Version < 2 {
  80. return nil, fmt.Errorf("GLB version:%v not supported", header.Version)
  81. }
  82. // Reads first chunk header (JSON)
  83. var chunk0 GLBChunk
  84. err = binary.Read(r, binary.LittleEndian, &chunk0)
  85. if err != nil {
  86. return nil, err
  87. }
  88. // Checks chunk type
  89. if chunk0.Type != GLBJson {
  90. return nil, fmt.Errorf("GLB Chunk0 type:%v not recognized", chunk0.Type)
  91. }
  92. // Reads first chunck data (JSON)
  93. buf := make([]byte, chunk0.Length)
  94. err = binary.Read(r, binary.LittleEndian, &buf)
  95. if err != nil {
  96. return nil, err
  97. }
  98. // Parses JSON
  99. bb := bytes.NewBuffer(buf)
  100. g, err := ParseJSONReader(bb, path)
  101. if err != nil {
  102. return nil, err
  103. }
  104. // Checks for chunk 1 (optional)
  105. var chunk1 GLBChunk
  106. err = binary.Read(r, binary.LittleEndian, &chunk1)
  107. if err != nil {
  108. if err != io.EOF {
  109. return nil, err
  110. }
  111. return g, nil
  112. }
  113. // Check chunk1 type
  114. if chunk1.Type != GLBBin {
  115. return nil, fmt.Errorf("GLB Chunk1 type:%v not recognized", chunk1.Type)
  116. }
  117. // Reads chunk1 data
  118. data := make([]byte, chunk1.Length)
  119. err = binary.Read(r, binary.LittleEndian, &data)
  120. if err != nil {
  121. return nil, err
  122. }
  123. g.data = data
  124. return g, nil
  125. }
  126. // NewScene creates a parent Node which contains all nodes contained by
  127. // the specified scene index from the GLTF Scenes array
  128. func (g *GLTF) NewScene(si int) (core.INode, error) {
  129. if si < 0 || si >= len(g.Scenes) {
  130. return nil, fmt.Errorf("Invalid Scene index")
  131. }
  132. s := g.Scenes[si]
  133. scene := core.NewNode()
  134. scene.SetName(s.Name)
  135. for i := 0; i < len(s.Nodes); i++ {
  136. child, err := g.NewNode(i)
  137. if err != nil {
  138. return nil, err
  139. }
  140. scene.Add(child)
  141. }
  142. return scene, nil
  143. }
  144. // NewNode creates and returns a new Node described by the specified index
  145. // in the decoded GLTF Nodes array.
  146. func (g *GLTF) NewNode(i int) (core.INode, error) {
  147. var in core.INode
  148. var err error
  149. node := g.Nodes[i]
  150. // Checks if the node is a Mesh (triangles, lines, etc...)
  151. if node.Mesh != nil {
  152. in, err = g.loadMesh(*node.Mesh)
  153. if err != nil {
  154. return nil, err
  155. }
  156. // Checks if the node is Camera
  157. } else if node.Camera != nil {
  158. in, err = g.loadCamera(*node.Camera)
  159. if err != nil {
  160. return nil, err
  161. }
  162. // Other cases, returns empty node
  163. } else {
  164. in = core.NewNode()
  165. }
  166. // Get *core.Node from core.INode
  167. n := in.GetNode()
  168. n.SetName(node.Name)
  169. // If defined, sets node local transformation matrix
  170. if node.Matrix != nil {
  171. n.SetMatrix((*math32.Matrix4)(node.Matrix))
  172. // Otherwise, checks rotation, scale and translation fields.
  173. } else {
  174. // Rotation quaternion
  175. if node.Rotation != nil {
  176. n.SetQuaternion(node.Rotation[0], node.Rotation[1], node.Rotation[2], node.Rotation[3])
  177. } else {
  178. n.SetQuaternion(0, 0, 0, 1)
  179. }
  180. // Scale
  181. if node.Scale != nil {
  182. n.SetScale(node.Scale[0], node.Scale[1], node.Scale[2])
  183. } else {
  184. n.SetScale(1, 1, 1)
  185. }
  186. // Translation
  187. if node.Translation != nil {
  188. log.Error("translation:%v", node.Translation)
  189. n.SetPosition(node.Translation[0], node.Translation[1], node.Translation[2])
  190. } else {
  191. n.SetPosition(0, 0, 0)
  192. }
  193. }
  194. // Loads node children recursively and adds to the parent
  195. for _, ci := range node.Children {
  196. child, err := g.NewNode(ci)
  197. if err != nil {
  198. return nil, err
  199. }
  200. n.Add(child)
  201. }
  202. return in, nil
  203. }
  204. // loadCamera creates and returns a Camera Node
  205. // from the specified GLTF.Cameras index
  206. func (g *GLTF) loadCamera(ci int) (core.INode, error) {
  207. camDesc := g.Cameras[ci]
  208. if camDesc.Type == "perspective" {
  209. desc := camDesc.Perspective
  210. fov := 360 * (desc.Yfov) / 2 * math32.Pi
  211. aspect := float32(2) // TODO how to get the current aspect ratio of the viewport from here ?
  212. if desc.AspectRatio != nil {
  213. aspect = *desc.AspectRatio
  214. }
  215. far := float32(2E6)
  216. if desc.Zfar != nil {
  217. far = *desc.Zfar
  218. }
  219. return camera.NewPerspective(fov, aspect, desc.Znear, far), nil
  220. }
  221. if camDesc.Type == "orthographic" {
  222. desc := camDesc.Orthographic
  223. cam := camera.NewOrthographic(desc.Xmag/-2, desc.Xmag/2, desc.Ymag/2, desc.Ymag/-2,
  224. desc.Znear, desc.Zfar)
  225. return cam, nil
  226. }
  227. return nil, fmt.Errorf("Unsupported camera type:%s", camDesc.Type)
  228. }
  229. // loadMesh creates and returns a Graphic Node (graphic.Mesh, graphic.Lines, graphic.Points, etc)
  230. // from the specified GLTF Mesh index
  231. func (g *GLTF) loadMesh(mi int) (core.INode, error) {
  232. // Create attribute buffers
  233. indices := math32.NewArrayU32(0, 0)
  234. positions := math32.NewArrayF32(0, 0)
  235. normals := math32.NewArrayF32(0, 0)
  236. uvs0 := math32.NewArrayF32(0, 0)
  237. // Array of primitive materials
  238. type matGroup struct {
  239. imat material.IMaterial
  240. start int
  241. count int
  242. }
  243. grMats := make([]matGroup, 0)
  244. // Process mesh primitives
  245. var mode int = -1
  246. var err error
  247. m := g.Meshes[mi]
  248. for i := 0; i < len(m.Primitives); i++ {
  249. p := m.Primitives[i]
  250. // Indexed Geometry
  251. if p.Indices != nil {
  252. pidx, err := g.loadIndices(*p.Indices)
  253. if err != nil {
  254. return nil, err
  255. }
  256. indices = append(indices, pidx...)
  257. } else {
  258. // Non-indexed primitive
  259. // indices array stay empty
  260. }
  261. // Currently the mode MUST be the same for all primitives
  262. if p.Mode != nil {
  263. mode = *p.Mode
  264. } else {
  265. mode = TRIANGLES
  266. }
  267. // Load primitive material
  268. var mat material.IMaterial
  269. if p.Material != nil {
  270. mat, err = g.loadMaterial(*p.Material)
  271. if err != nil {
  272. return nil, err
  273. }
  274. } else {
  275. mat = g.newDefaultMaterial()
  276. }
  277. grMats = append(grMats, matGroup{
  278. imat: mat,
  279. start: int(0),
  280. count: len(indices),
  281. })
  282. // Load primitive attributes
  283. for name, aci := range p.Attributes {
  284. if name == "POSITION" {
  285. ppos, err := g.loadVec3(aci)
  286. if err != nil {
  287. return nil, err
  288. }
  289. positions = append(positions, ppos...)
  290. continue
  291. }
  292. if name == "NORMAL" {
  293. pnorms, err := g.loadVec3(aci)
  294. if err != nil {
  295. return nil, err
  296. }
  297. normals = append(normals, pnorms...)
  298. continue
  299. }
  300. if name == "TEXCOORD_0" {
  301. puvs, err := g.loadVec2(aci)
  302. if err != nil {
  303. return nil, err
  304. }
  305. uvs0 = append(uvs0, puvs...)
  306. continue
  307. }
  308. }
  309. }
  310. // Creates Geometry and add attribute VBOs
  311. geom := geometry.NewGeometry()
  312. if len(indices) > 0 {
  313. geom.SetIndices(indices)
  314. }
  315. if len(positions) > 0 {
  316. geom.AddVBO(gls.NewVBO().AddAttrib("VertexPosition", 3).SetBuffer(positions))
  317. }
  318. if len(normals) > 0 {
  319. geom.AddVBO(gls.NewVBO().AddAttrib("VertexNormal", 3).SetBuffer(normals))
  320. }
  321. if len(uvs0) > 0 {
  322. geom.AddVBO(gls.NewVBO().AddAttrib("VertexTexcoord", 2).SetBuffer(uvs0))
  323. }
  324. //log.Error("positions:%v", positions)
  325. //log.Error("indices..:%v", indices)
  326. //log.Error("normals..:%v", normals)
  327. //log.Error("uvs0.....:%v", uvs0)
  328. // Create Mesh
  329. if mode == TRIANGLES {
  330. node := graphic.NewMesh(geom, nil)
  331. for i := 0; i < len(grMats); i++ {
  332. grm := grMats[i]
  333. node.AddMaterial(grm.imat, grm.start, grm.count)
  334. }
  335. return node, nil
  336. }
  337. // Create Lines
  338. if mode == LINES {
  339. node := graphic.NewLines(geom, grMats[0].imat)
  340. return node, nil
  341. }
  342. // Create LineStrip
  343. if mode == LINE_STRIP {
  344. node := graphic.NewLineStrip(geom, grMats[0].imat)
  345. return node, nil
  346. }
  347. // Create Points
  348. if mode == POINTS {
  349. node := graphic.NewPoints(geom, grMats[0].imat)
  350. return node, nil
  351. }
  352. return nil, fmt.Errorf("Unsupported primitive:%v", mode)
  353. }
  354. func (g *GLTF) newDefaultMaterial() material.IMaterial {
  355. return material.NewStandard(&math32.Color{0.5, 0.5, 0.5})
  356. }
  357. // loadMaterials loads the material specified by the material index
  358. func (g *GLTF) loadMaterial(mi int) (material.IMaterial, error) {
  359. mat := g.Materials[mi]
  360. // Checks for material extensions
  361. if mat.Extensions != nil {
  362. for ext, v := range mat.Extensions {
  363. if ext == "KHR_materials_common" {
  364. return g.loadMaterialCommon(v)
  365. } else {
  366. return nil, fmt.Errorf("Unsupported extension:%s", ext)
  367. }
  368. }
  369. return nil, fmt.Errorf("Empty material extensions")
  370. // Material should be PBR
  371. } else {
  372. return g.loadMaterialPBR(&mat)
  373. }
  374. }
  375. // loadTextureInfo loads the texture specified by the TextureInfo pointer
  376. func (g *GLTF) loadTextureInfo(ti *TextureInfo) (*texture.Texture2D, error) {
  377. log.Error("loadTexture:%+v", ti)
  378. // loads texture image
  379. texDesc := g.Textures[ti.Index]
  380. img, err := g.loadImage(texDesc.Source)
  381. if err != nil {
  382. return nil, err
  383. }
  384. tex := texture.NewTexture2DFromRGBA(img)
  385. // Get sampler and apply texture parameters
  386. samp := g.Samplers[texDesc.Sampler]
  387. // Magnification filter
  388. magFilter := gls.NEAREST
  389. if samp.MagFilter != nil {
  390. magFilter = *samp.MagFilter
  391. }
  392. tex.SetMagFilter(uint32(magFilter))
  393. // Minification filter
  394. minFilter := gls.NEAREST
  395. if samp.MinFilter != nil {
  396. minFilter = *samp.MinFilter
  397. }
  398. tex.SetMinFilter(uint32(minFilter))
  399. // S coordinate wrapping mode
  400. wrapS := gls.REPEAT
  401. if samp.WrapS != nil {
  402. wrapS = *samp.WrapS
  403. }
  404. tex.SetWrapS(uint32(wrapS))
  405. // T coordinate wrapping mode
  406. wrapT := gls.REPEAT
  407. if samp.WrapT != nil {
  408. wrapT = *samp.WrapT
  409. }
  410. tex.SetWrapT(uint32(wrapT))
  411. return tex, nil
  412. }
  413. // loadImage loads the image specified by the index of GLTF.Images
  414. // Image can be loaded from binary chunk file or data URI or external file.
  415. func (g *GLTF) loadImage(ii int) (*image.RGBA, error) {
  416. log.Error("loadImage:%v", ii)
  417. imgDesc := g.Images[ii]
  418. var data []byte
  419. var err error
  420. // If Uri is empty, load image from chunk
  421. if imgDesc.Uri == "" {
  422. bvi := imgDesc.BufferView
  423. if bvi == nil {
  424. return nil, fmt.Errorf("Image has empty URI and no BufferView")
  425. }
  426. bv := g.BufferViews[*bvi]
  427. offset := 0
  428. if bv.ByteOffset != nil {
  429. offset = *bv.ByteOffset
  430. }
  431. data = g.data[offset : offset+bv.ByteLength]
  432. // Checks if image URI is data URL
  433. } else if isDataURL(imgDesc.Uri) {
  434. data, err = loadDataURL(imgDesc.Uri)
  435. if err != nil {
  436. return nil, err
  437. }
  438. // Loads external buffer file
  439. } else {
  440. // Load image data from file
  441. fpath := filepath.Join(g.path, imgDesc.Uri)
  442. f, err := os.Open(fpath)
  443. if err != nil {
  444. return nil, err
  445. }
  446. defer f.Close()
  447. data, err = ioutil.ReadAll(f)
  448. if err != nil {
  449. return nil, err
  450. }
  451. }
  452. // Decodes image data
  453. bb := bytes.NewBuffer(data)
  454. img, _, err := image.Decode(bb)
  455. if err != nil {
  456. return nil, err
  457. }
  458. // Converts image to RGBA format
  459. rgba := image.NewRGBA(img.Bounds())
  460. if rgba.Stride != rgba.Rect.Size().X*4 {
  461. return nil, fmt.Errorf("unsupported stride")
  462. }
  463. draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)
  464. return rgba, nil
  465. }
  466. // loadVec3 load array of Vector3 from the specified accessor index
  467. func (g *GLTF) loadVec3(ai int) (math32.ArrayF32, error) {
  468. // Get Accessor for the specified index
  469. ac := g.Accessors[ai]
  470. if ac.BufferView == nil {
  471. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  472. }
  473. // Checks acessor ComponentType
  474. if ac.ComponentType != FLOAT {
  475. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  476. }
  477. // Checks acessor Type
  478. if ac.Type != VEC3 {
  479. return nil, fmt.Errorf("Accessor.ComponentType != VEC3 NOT SUPPORTED")
  480. }
  481. // Loads data from associated BufferView
  482. data, err := g.loadBufferView(*ac.BufferView)
  483. if err != nil {
  484. return nil, err
  485. }
  486. // Accessor offset into BufferView
  487. offset := 0
  488. if ac.ByteOffset != nil {
  489. offset = *ac.ByteOffset
  490. }
  491. data = data[offset:]
  492. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*3]
  493. return math32.ArrayF32(arr), nil
  494. }
  495. // loadVec2 load array of Vector2 from the specified accessor index
  496. func (g *GLTF) loadVec2(ai int) (math32.ArrayF32, error) {
  497. // Get Accessor for the specified index
  498. ac := g.Accessors[ai]
  499. if ac.BufferView == nil {
  500. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  501. }
  502. // Checks acessor ComponentType
  503. if ac.ComponentType != FLOAT {
  504. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  505. }
  506. // Checks acessor Type
  507. if ac.Type != VEC2 {
  508. return nil, fmt.Errorf("Accessor.ComponentType != VEC2 NOT SUPPORTED")
  509. }
  510. // Loads data from associated BufferView
  511. data, err := g.loadBufferView(*ac.BufferView)
  512. if err != nil {
  513. return nil, err
  514. }
  515. // Accessor offset into BufferView
  516. offset := 0
  517. if ac.ByteOffset != nil {
  518. offset = *ac.ByteOffset
  519. }
  520. data = data[offset:]
  521. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*2]
  522. return math32.ArrayF32(arr), nil
  523. }
  524. // loadIndices load the indices array specified by the Accessor index.
  525. func (g *GLTF) loadIndices(ai int) (math32.ArrayU32, error) {
  526. // Get Accessor for the specified index
  527. ac := g.Accessors[ai]
  528. if ac.BufferView == nil {
  529. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED YET")
  530. }
  531. // Loads indices data from associated BufferView
  532. data, err := g.loadBufferView(*ac.BufferView)
  533. if err != nil {
  534. return nil, err
  535. }
  536. // Accessor offset into BufferView
  537. offset := 0
  538. if ac.ByteOffset != nil {
  539. offset = *ac.ByteOffset
  540. }
  541. data = data[offset:]
  542. // If index component is UNSIGNED_INT nothing to do
  543. if ac.ComponentType == UNSIGNED_INT {
  544. arr := (*[1 << 30]uint32)(unsafe.Pointer(&data[0]))[:ac.Count]
  545. return math32.ArrayU32(arr), nil
  546. }
  547. // Converts UNSIGNED_SHORT indices to UNSIGNED_INT
  548. if ac.ComponentType == UNSIGNED_SHORT {
  549. indices := math32.NewArrayU32(ac.Count, ac.Count)
  550. for i := 0; i < ac.Count; i++ {
  551. indices[i] = uint32(data[i*2]) + uint32(data[i*2+1])*256
  552. }
  553. return indices, nil
  554. }
  555. // Converts UNSIGNED_BYTE indices to UNSIGNED_INT
  556. if ac.ComponentType == UNSIGNED_BYTE {
  557. indices := math32.NewArrayU32(ac.Count, ac.Count)
  558. for i := 0; i < ac.Count; i++ {
  559. indices[i] = uint32(data[i*4]) + uint32(data[i*4+1])*256 +
  560. uint32(data[i*4+2])*256*256 + uint32(data[i*4+3])*256*256*256
  561. }
  562. return indices, nil
  563. }
  564. return nil, fmt.Errorf("Unsupported Accessor ComponentType:%v", ac.ComponentType)
  565. }
  566. // loadBufferView loads and returns a byte slice with data from the specified
  567. // BufferView index
  568. func (g *GLTF) loadBufferView(bvi int) ([]byte, error) {
  569. bv := g.BufferViews[bvi]
  570. buf, err := g.loadBuffer(bv.Buffer)
  571. if err != nil {
  572. return nil, err
  573. }
  574. offset := 0
  575. if bv.ByteOffset != nil {
  576. offset = *bv.ByteOffset
  577. }
  578. return buf[offset : offset+bv.ByteLength], nil
  579. }
  580. // loadBuffer loads and returns the data from the specified GLTF Buffer index
  581. func (g *GLTF) loadBuffer(bi int) ([]byte, error) {
  582. buf := &g.Buffers[bi]
  583. // If Buffer URI uses the chunk data field
  584. if buf.Uri == "" {
  585. return g.data, nil
  586. }
  587. // If buffer already loaded:
  588. log.Error("loadBuffer cache:%v", len(buf.data))
  589. if len(buf.data) > 0 {
  590. return buf.data, nil
  591. }
  592. // Checks if buffer URI is a data URI
  593. var data []byte
  594. var err error
  595. if isDataURL(buf.Uri) {
  596. data, err = loadDataURL(buf.Uri)
  597. if err != nil {
  598. return nil, err
  599. }
  600. // Loads external buffer file
  601. } else {
  602. log.Error("loadBuffer: loading file")
  603. // Try to load buffer from file
  604. fpath := filepath.Join(g.path, buf.Uri)
  605. f, err := os.Open(fpath)
  606. if err != nil {
  607. return nil, err
  608. }
  609. defer f.Close()
  610. data, err = ioutil.ReadAll(f)
  611. if err != nil {
  612. return nil, err
  613. }
  614. }
  615. // Checks data length
  616. if len(data) != buf.ByteLength {
  617. return nil, fmt.Errorf("Buffer:%d read data length:%d expected:%d", bi, len(data), buf.ByteLength)
  618. }
  619. // Cache buffer data
  620. buf.data = data
  621. log.Error("cache data:%v", len(buf.data))
  622. return data, nil
  623. }
  624. // dataURL describes a decoded data url string
  625. type dataURL struct {
  626. MediaType string
  627. Encoding string
  628. Data string
  629. }
  630. const (
  631. dataURLprefix = "data:"
  632. mimeBIN = "application/octet-stream"
  633. mimePNG = "image/png"
  634. mimeJPEG = "image/jpeg"
  635. )
  636. var validMediaTypes = []string{mimeBIN, mimePNG, mimeJPEG}
  637. // isDataURL checks if the specified string has the prefix of data URL
  638. func isDataURL(url string) bool {
  639. if strings.HasPrefix(url, dataURLprefix) {
  640. return true
  641. }
  642. return false
  643. }
  644. // loadDataURL decodes the specified data URI string (base64)
  645. func loadDataURL(url string) ([]byte, error) {
  646. var du dataURL
  647. err := parseDataURL(url, &du)
  648. if err != nil {
  649. return nil, err
  650. }
  651. // Checks for valid media type
  652. found := false
  653. for i := 0; i < len(validMediaTypes); i++ {
  654. if validMediaTypes[i] == du.MediaType {
  655. found = true
  656. break
  657. }
  658. }
  659. if !found {
  660. return nil, fmt.Errorf("Data URI media type:%s not supported", du.MediaType)
  661. }
  662. // Checks encoding
  663. if du.Encoding != "base64" {
  664. return nil, fmt.Errorf("Data URI encoding:%s not supported", du.Encoding)
  665. }
  666. // Decodes data from BASE64
  667. data, err := base64.StdEncoding.DecodeString(du.Data)
  668. if err != nil {
  669. return nil, err
  670. }
  671. return data, nil
  672. }
  673. // parseDataURL tries to parse the specified string as a data URL with the format:
  674. // data:[<mediatype>][;base64],<data>
  675. // and if successfull returns true and updates the specified pointer with the parsed fields.
  676. func parseDataURL(url string, du *dataURL) error {
  677. // Checks prefix
  678. if !isDataURL(url) {
  679. return fmt.Errorf("Specified string is not a data URL")
  680. }
  681. // Separates header from data
  682. body := url[len(dataURLprefix):]
  683. parts := strings.Split(body, ",")
  684. if len(parts) != 2 {
  685. return fmt.Errorf("Data URI contains more than one ','")
  686. }
  687. du.Data = parts[1]
  688. // Separates media type from optional encoding
  689. res := strings.Split(parts[0], ";")
  690. du.MediaType = res[0]
  691. if len(res) < 2 {
  692. return nil
  693. }
  694. if len(res) >= 2 {
  695. du.Encoding = res[1]
  696. }
  697. return nil
  698. }