internal/graphicscommand: browser screenshot/image dump support (#2269)

Closes #2265
This commit is contained in:
Terra Brown 2022-08-26 23:51:30 -04:00 committed by GitHub
parent 3259ef3daf
commit 232cadf15a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 117 additions and 19 deletions

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build android || ios || js
// +build android ios js
//go:build android || ios
// +build android ios
package ebiten

View File

@ -12,14 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !android && !ios && !js
// +build !android,!ios,!js
//go:build !android && !ios
// +build !android,!ios
package ebiten
import (
"errors"
"fmt"
"os"
"syscall"
"time"
"github.com/hajimehoshi/ebiten/v2/internal/debug"
@ -34,7 +36,7 @@ func availableFilename(prefix, postfix string) (string, error) {
name := fmt.Sprintf("%s%s%s", prefix, now.Format(datetimeFormat), postfix)
for i := 1; ; i++ {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
if os.IsNotExist(err) || errors.Is(err, syscall.ENOSYS) {
break
}
if !os.IsNotExist(err) {

View File

@ -15,11 +15,9 @@
package graphicscommand
import (
"fmt"
"image"
"os"
"io"
"sort"
"strings"
"github.com/hajimehoshi/ebiten/v2/internal/affine"
"github.com/hajimehoshi/ebiten/v2/internal/debug"
@ -190,25 +188,17 @@ func (i *Image) IsInvalidated() bool {
return i.image.IsInvalidated()
}
// Dump dumps the image to the specified path.
// In the path, '*' is replaced with the image's ID.
// dumpTo dumps the image to the specified writer.
//
// If blackbg is true, any alpha values in the dumped image will be 255.
//
// This is for testing usage.
func (i *Image) Dump(graphicsDriver graphicsdriver.Graphics, path string, blackbg bool, rect image.Rectangle) error {
func (i *Image) dumpTo(w io.Writer, graphicsDriver graphicsdriver.Graphics, blackbg bool, rect image.Rectangle) error {
// Screen image cannot be dumped.
if i.screen {
return nil
}
path = strings.ReplaceAll(path, "*", fmt.Sprintf("%d", i.id))
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
pix := make([]byte, 4*i.width*i.height)
if err := i.ReadPixels(graphicsDriver, pix); err != nil {
return err
@ -220,13 +210,14 @@ func (i *Image) Dump(graphicsDriver graphicsdriver.Graphics, path string, blackb
}
}
if err := png.Encode(f, (&image.RGBA{
if err := png.Encode(w, (&image.RGBA{
Pix: pix,
Stride: 4 * i.width,
Rect: image.Rect(0, 0, i.width, i.height),
}).SubImage(rect)); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,58 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package graphicscommand
import (
"bytes"
"image"
"path/filepath"
"strconv"
"strings"
"syscall/js"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
)
func (i *Image) Dump(graphicsDriver graphicsdriver.Graphics, path string, blackbg bool, rect image.Rectangle) error {
// Screen image cannot be dumped.
if i.screen {
return nil
}
path = strings.ReplaceAll(path, "*", strconv.Itoa(i.id))
path = filepath.Base(path)
global := js.Global()
buf := &bytes.Buffer{}
if err := i.dumpTo(buf, graphicsDriver, blackbg, rect); err != nil {
return err
}
jsData := global.Get("Uint8Array").New(buf.Len())
js.CopyBytesToJS(jsData, buf.Bytes())
a := global.Get("document").Call("createElement", "a")
blob := global.Get("Blob").New(
[]interface{}{jsData},
map[string]interface{}{"type": "image/png"},
)
a.Set("href", global.Get("URL").Call("createObjectURL", blob))
a.Set("download", path)
a.Call("click")
return nil
}

View File

@ -0,0 +1,47 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !js
// +build !js
package graphicscommand
import (
"image"
"os"
"strconv"
"strings"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
)
func (i *Image) Dump(graphicsDriver graphicsdriver.Graphics, path string, blackbg bool, rect image.Rectangle) error {
// Screen image cannot be dumped.
if i.screen {
return nil
}
path = strings.ReplaceAll(path, "*", strconv.Itoa(i.id))
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if err := i.dumpTo(f, graphicsDriver, blackbg, rect); err != nil {
return err
}
return nil
}