修复gtk读取图片像素时alpha通道异常的bug
parent
c0011b582d
commit
8ab9ea2dd9
|
@ -0,0 +1 @@
|
|||
__pycache__
|
153
app.js
153
app.js
|
@ -5,58 +5,107 @@
|
|||
*/
|
||||
|
||||
import 'es.shim'
|
||||
import { $, bind } from 'wkit'
|
||||
import { html, css, Component } from 'wkit'
|
||||
|
||||
async function test1() {
|
||||
let txt = await native.clipboard.readText()
|
||||
$('input').value = txt
|
||||
class App extends Component {
|
||||
static props = {
|
||||
input: '',
|
||||
img: ''
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
.output {
|
||||
max-width: 100%;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
`
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<button @click=${this.test1}>Test 1</button>
|
||||
<button @click=${this.test2}>Test 2</button>
|
||||
|
||||
<a target="_blank" href="about:blank">打开控制台</a>
|
||||
|
||||
<div class="output">loading...</div>
|
||||
|
||||
<input value=${this.input} />
|
||||
|
||||
<hr />
|
||||
<button @click=${this.writeImage}>写图片到剪切板</button>
|
||||
<button
|
||||
@click=${async function () {
|
||||
native.quit()
|
||||
}}
|
||||
>
|
||||
退出
|
||||
</button>
|
||||
<button @click=${this.createTray}>tray</button>
|
||||
<button @click=${this.register}>screen</button>
|
||||
<img style="width:100px;border:1px solid #09f;" src=${this.img} />
|
||||
<textarea @paste=${this.pasteImg}></textarea>
|
||||
`
|
||||
}
|
||||
|
||||
async test1() {
|
||||
let txt = await native.clipboard.readText()
|
||||
console.log('<><><>', txt)
|
||||
this.input = txt
|
||||
}
|
||||
|
||||
async test2() {
|
||||
native.clipboard.writeText('这是一段写进剪切板的文本')
|
||||
}
|
||||
|
||||
async writeImage() {
|
||||
// let img = await native.image('/code/gtk/webkit/debian.png')
|
||||
// native.clipboard.writeImage(img)
|
||||
native.clipboard.writeImage('/code/gtk/webkit/red.png')
|
||||
// try {
|
||||
// this.img = URL.createObjectURL(await img.export())
|
||||
// } catch (err) {
|
||||
// alert(err)
|
||||
// }
|
||||
}
|
||||
|
||||
quit() {
|
||||
native.quit()
|
||||
}
|
||||
|
||||
createTray() {
|
||||
native.tray()
|
||||
}
|
||||
|
||||
async register() {
|
||||
// console.log(await native.globalShortcut.enabled)
|
||||
|
||||
native.globalShortcut.register('<Ctrl>2', function () {
|
||||
alert('<Ctrl>2被绑定了')
|
||||
})
|
||||
// console.log(await native.screen.getAllDisplays())
|
||||
// console.log(await native.screen.getPrimaryDisplay())
|
||||
}
|
||||
|
||||
async pasteImg(ev) {
|
||||
let items = ev.clipboardData.items
|
||||
|
||||
let img = await window?.native?.clipboard?.readImage()
|
||||
|
||||
console.log(img)
|
||||
|
||||
if (img) {
|
||||
this.img = URL.createObjectURL(await img.export())
|
||||
}
|
||||
|
||||
for (let it of items) {
|
||||
let file = it.getAsFile()
|
||||
if (file) {
|
||||
this.img = URL.createObjectURL(file)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function test2() {
|
||||
native.clipboard.writeText('这是一段写进剪切板的文本')
|
||||
// native.handler('blabla', { foo: 'bar' }).then(r => {
|
||||
// $('#output').innerHTML = JSON.stringify(r)
|
||||
// })
|
||||
}
|
||||
|
||||
bind($('.btn1'), 'click', test1)
|
||||
bind($('.btn2'), 'click', test2)
|
||||
bind($('.btn3'), 'click', async function () {
|
||||
// window.open('about:blank')
|
||||
// let img = await native.clipboard.writeImage('/code/gtk/webkit/debian.png')
|
||||
let img = await native.image('/code/gtk/webkit/debian.png')
|
||||
native.clipboard.writeImage(img)
|
||||
// native.clipboard.writeImage('/code/gtk/webkit/debian.png')
|
||||
try {
|
||||
$('img').src = URL.createObjectURL(await img.export())
|
||||
} catch (err) {
|
||||
alert(err)
|
||||
}
|
||||
})
|
||||
bind($('.btn4'), 'click', async function () {
|
||||
native.quit()
|
||||
// native.clipboard.clear()
|
||||
})
|
||||
|
||||
bind($('.btn5'), 'click', async function () {
|
||||
native.tray()
|
||||
})
|
||||
|
||||
bind($('.btn6'), 'click', async function () {
|
||||
// console.log(await native.globalShortcut.enabled)
|
||||
|
||||
native.globalShortcut.register('<Ctrl>2', function () {
|
||||
alert('<Ctrl>2被绑定了')
|
||||
})
|
||||
// console.log(await native.screen.getAllDisplays())
|
||||
// console.log(await native.screen.getPrimaryDisplay())
|
||||
})
|
||||
|
||||
bind($('textarea'), 'paste', async function (ev) {
|
||||
let items = ev.clipboardData.items
|
||||
for (let it of items) {
|
||||
let file = it.getAsFile()
|
||||
$('img').src = URL.createObjectURL(file)
|
||||
break
|
||||
}
|
||||
})
|
||||
App.reg('app')
|
||||
|
|
5
demo.js
5
demo.js
|
@ -1,5 +0,0 @@
|
|||
import fs from 'iofs'
|
||||
|
||||
let buf = fs.cat('./debian.png')
|
||||
console.log(buf)
|
||||
console.log([...buf], buf.byteLength)
|
23
index.html
23
index.html
|
@ -16,30 +16,11 @@
|
|||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
#output {max-width:100%;white-space: pre-wrap;word-break: break-all;}
|
||||
</style>
|
||||
<script type="module" src="/app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<button class="btn1">Test 1</button>
|
||||
<button class="btn2">Test 2</button>
|
||||
|
||||
<a target="_blank" href="about:blank">打开控制台</a>
|
||||
|
||||
<div id="output">loading...</div>
|
||||
|
||||
<input type="text">
|
||||
|
||||
<hr>
|
||||
<button class="btn3">写图片到剪切板</button>
|
||||
<button class="btn4">退出</button>
|
||||
<button class="btn5">tray</button>
|
||||
<button class="btn6">screen</button>
|
||||
<img style="width:100px;border:1px solid #09f;" src="" alt="">
|
||||
<textarea></textarea>
|
||||
|
||||
<script type="module" src="/app.js"></script>
|
||||
<wc-app></wc-app>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -83,6 +83,7 @@ class NativeImage {
|
|||
this.width = obj.width
|
||||
this.height = obj.height
|
||||
this.type = MIME_TYPES[obj.filepath.split('.').pop()]
|
||||
console.log(obj)
|
||||
}
|
||||
|
||||
toPixbuf() {
|
||||
|
@ -179,7 +180,9 @@ Object.assign(native, {
|
|||
return handler('clipboard', { action: 'set_text', value }, null)
|
||||
},
|
||||
readImage() {
|
||||
return handler('clipboard', { action: 'wait_for_image' })
|
||||
return handler('clipboard', { action: 'wait_for_image' }).then(r =>
|
||||
r ? new NativeImage(r) : r
|
||||
)
|
||||
},
|
||||
writeImage(value) {
|
||||
if (typeof value === 'object') {
|
||||
|
|
39
main.py
39
main.py
|
@ -10,6 +10,8 @@ gi.require_version("Keybinder", "3.0")
|
|||
from gi.repository import Gtk, Gdk, WebKit2, GLib, Keybinder
|
||||
from gi.repository.GdkPixbuf import Pixbuf
|
||||
|
||||
from notes.utils import *
|
||||
|
||||
# 优先尝试使用指示器, 没有再使用 Gtk.StatusIcon
|
||||
try:
|
||||
gi.require_version('AyatanaAppIndicator3', '0.1')
|
||||
|
@ -22,21 +24,6 @@ except (ValueError, ImportError):
|
|||
Keybinder.init()
|
||||
|
||||
|
||||
def get_monitor_info(monitor):
|
||||
return {
|
||||
"model": monitor.props.model,
|
||||
"scale_factor": monitor.props.scale_factor,
|
||||
"manufacturer": monitor.props.manufacturer,
|
||||
"refresh_rate": monitor.props.refresh_rate,
|
||||
"is_primary": monitor.is_primary(),
|
||||
"geometry": {
|
||||
"width": monitor.props.geometry.width,
|
||||
"height": monitor.props.geometry.height,
|
||||
"x": monitor.props.geometry.x,
|
||||
"y": monitor.props.geometry.y,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WebKitWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
|
@ -164,6 +151,7 @@ class WebKitWindow(Gtk.Window):
|
|||
# 前端传进来的值, 如果是路径的话, 直接读取
|
||||
if type(image) == str:
|
||||
image = Pixbuf.new_from_file(image)
|
||||
print(pixbuf_to_dict(image, params['value']))
|
||||
else:
|
||||
image = Pixbuf.new_from_data(
|
||||
data = bytes(image['bytes']),
|
||||
|
@ -174,18 +162,21 @@ class WebKitWindow(Gtk.Window):
|
|||
height = image['height'],
|
||||
rowstride = image['rowstride']
|
||||
)
|
||||
|
||||
self.clipboard.set_image(image)
|
||||
self.clipboard.store()
|
||||
|
||||
# 读图片
|
||||
elif params['action'] == 'wait_for_image':
|
||||
output = self.clipboard.wait_for_image()
|
||||
output = pixbuf_to_dict(output, 'noname.png')
|
||||
|
||||
# 清除剪切板
|
||||
elif params['action'] == 'clear':
|
||||
self.clipboard.clear()
|
||||
|
||||
# 回调给前端
|
||||
if callback and output:
|
||||
if callback:
|
||||
scripts = 'native.$emit("' + callback + '",' + json.dumps(output) + ')'
|
||||
print(scripts)
|
||||
self.webview.evaluate_javascript(scripts, -1)
|
||||
|
||||
# 退出app
|
||||
|
@ -196,17 +187,7 @@ class WebKitWindow(Gtk.Window):
|
|||
case 'image':
|
||||
filename = params['value']
|
||||
pixbuf = Pixbuf.new_from_file(filename)
|
||||
image = {
|
||||
"width": pixbuf.get_width(),
|
||||
"height": pixbuf.get_height(),
|
||||
"colorspace": pixbuf.get_colorspace(),
|
||||
"has_alpha": pixbuf. get_has_alpha(),
|
||||
"bits_per_sample": pixbuf.get_bits_per_sample(),
|
||||
"rowstride": pixbuf.get_rowstride(),
|
||||
"filepath": filename,
|
||||
"bytes": list(pixbuf.get_pixels())
|
||||
}
|
||||
|
||||
image = pixbuf_to_dict(pixbuf, filename)
|
||||
|
||||
scripts = 'native.$emit("' + callback + '",' + json.dumps(image) + ')'
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# @author yutent<yutent.io@gmail.com>
|
||||
# @date 2023/07/28 14:39:33
|
||||
|
||||
|
||||
def get_monitor_info(monitor):
|
||||
return {
|
||||
"model": monitor.props.model,
|
||||
"scale_factor": monitor.props.scale_factor,
|
||||
"manufacturer": monitor.props.manufacturer,
|
||||
"refresh_rate": monitor.props.refresh_rate,
|
||||
"is_primary": monitor.is_primary(),
|
||||
"geometry": {
|
||||
"width": monitor.props.geometry.width,
|
||||
"height": monitor.props.geometry.height,
|
||||
"x": monitor.props.geometry.x,
|
||||
"y": monitor.props.geometry.y,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def pixbuf_to_dict(pixbuf, filename = ''):
|
||||
has_alpha = pixbuf.get_has_alpha()
|
||||
|
||||
# 没有apha通道时, get_pixels() 得到像素矩阵会出现极个别像素出现alpha通道
|
||||
# 所以, 这里强制设置alpha通道为false, 补全像素矩阵的数据
|
||||
if has_alpha is False:
|
||||
pixbuf = pixbuf.add_alpha(False, 0, 0, 0)
|
||||
|
||||
if pixbuf:
|
||||
image = {
|
||||
"width": pixbuf.get_width(),
|
||||
"height": pixbuf.get_height(),
|
||||
"colorspace": pixbuf.get_colorspace(),
|
||||
"has_alpha": has_alpha,
|
||||
"bits_per_sample": pixbuf.get_bits_per_sample(),
|
||||
"rowstride": pixbuf.get_rowstride(),
|
||||
"filepath": filename,
|
||||
"length": pixbuf.get_byte_length(),
|
||||
"bytes": list(pixbuf.get_pixels())
|
||||
}
|
||||
else:
|
||||
image = None
|
||||
|
||||
return image
|
Reference in New Issue