Sunday, 10 April 2016

如何用 Print Screen

先来看视频 (因为没打算 edit video,所以想下一个步骤会有点 delay, 最终还是漏了一个步骤,需要事后补上去,后面冷场可以加速 x2 观看的):


制作步骤:

[1] 设置三个快捷键,分别是 xdotool, 两种 --countdown 和 --area 两种选项。之所以需要 xdotool 当代理人是因为无法直接用 scrot -s/gnome-screenshot -a, shutter 没这个问题。/home/xiaobai/note/sh/my_gnome_area.sh 是我的代码文件路径。




【2】
my_gnome_area.sh script 代码 (无 comments 纯净版):

for cmd in "mktemp" "shutter" "feh" "wmctrl" "notify-send" "ts" "eog" "gimp" "convert" "tesseract" "gedit" "firefox" "curl" "xargs" "konsole" "vimx" "yad"; do 
    command -v $cmd >/dev/null 2>&1 || {  LANG=POSIX; xmessage "Require $cmd but it's not installed.  Aborting." >&2; exit 1; }; :;
done
mkdir -p -- "$HOME/Pictures/print_screen_note/"
tmpj="$(mktemp /tmp/`date +"%s_%Y-%m-%d"`_XXXXXXXXXX.png)"
tmpocr="$(mktemp -u /tmp/`date +"%s_%Y-%m-%d"`_ocr_XXXXX)"
tmpocr_p="$tmpocr"+'.png'
if [[ "$@" == "--area" ]]; then
    gnome-screenshot -a -f "$tmpj" 2>&1 >/dev/null | ts >>/tmp/gnome_area_PrtSc_error.log
elif [[ "$@" == "--countdown" ]]; then
    shutter -s -d 5 -c -e -o "$tmpj" 2>&1 >/dev/null | ts >>/tmp/shutter_PrtSc_error.log
else
    echo "Invalid argument." | ts >>/tmp/PrtSc_error.log
    exit 1
fi
function ocr () {
    tmpj="$1"
    tmpocr="$2"
    tmpocr_p="$3"
    atom="$(tesseract --list-langs 2>&1)"; atom=(`echo "${atom#*:}"`); atom=(`echo "$(printf 'FALSE\n%s\n' "${atom[@]}")"`); atom[0]='True'
    ans=(`yad --center --height=200 --width=300 --separator='|' --on-top --list --title '' --text='Select Languages:' --radiolist --column '✓' --column 'Languages' "${atom[@]}" 2>/dev/null`) && ans="$(echo "${ans:5:-1}")" &&  convert "$tmpj[x2000]" -unsharp 15.6x7.8+2.69+0 "$tmpocr_p" | yad --on-top --title '' --text='Converting ...' --progress --pulsate --auto-close 2>/dev/null && tesseract "$tmpocr_p" "$tmpocr" -l "$ans" 2>>/tmp/tesseract.log | yad --percentage=50 --on-top --title '' --text='Tesseracting ...' --progress --pulsate --auto-close 2>/dev/null && if [[ "$ans" == 'eng' ]]; then konsole -e "vimx -c 'setlocal spell spelllang=en_us' -n $tmpocr.txt" 2>/dev/null; else gedit "$tmpocr.txt"; fi
    rm "$tmpocr_p"
}
export -f ocr
feh -x \
-A "cp %F ~/Pictures/print_screen_note/%N" \
--action1 "notify-send ' ' -u critical 'd: title, up/down: zoom, w: win_to_img, </>: rotate, *: orig, Enter/0: save to ~/Pictures/print_screen_note/, 1: Help, m/right_clic: context menu, 2: Always on top, 3: Remove always on top, 4: shutter, 5: eog, 6: gimp, 7: OCR, 8: Note directory(Left/Right to navigate), 9: Google. Alt+F7(Might cause mouse pointer lag) to move windows like Left_mouse_click+Super keys. After position changed, Esc to cancel, Enter to confirm.'" \
--action2 "wmctrl -a \"feh [1 of 1] - $tmpj\" -b add,above" \
--action3 "wmctrl -a \"feh [1 of 1] - $tmpj\" -b remove,above" \
--action4 "shutter $tmpj &" \
--action5 "eog $tmpj &" \
--action6 "gimp $tmpj &" \
--action7 "ocr $tmpj $tmpocr $tmpocr_p &" \
--action8 "feh -x ~/Pictures/print_screen_note/ &" \
--action9 "(curl -sf --output /dev/null -w '%{redirect_url}' -F 'image_url=' -F 'image_content=' -F 'filename=' -F 'h1=en'  -F 'bih=' -F 'biw=' -F "encoded_image=@$tmpj" 'https://www.google.com/searchbyimage/upload' | xargs -rL1 firefox -new-tab)&" \
"$tmpj" 2>&1 >/dev/null | ts >>/tmp/PrtSc_error.log


【3】
虽然我上面的代码开头有检查需要用的 utilities/工具然后给出错误信息,但还是要说,最好先手动试这些 commands 能跑,往后就可以 comment out 那个 checking:

[1] mktemp
- coreutils  package
[2] shutter
[3] feh

这个 我记得是自己 compile 才能完全 borderless 的。新的 Fedora 不懂有没有 fix。

[4] wmctrl
[5] notify-send
- libnotify package, 如果 install 找不到 package,可以用 dnf whatprovides /usr/bin/notify-send 寻找真正的 package 名字来安装。
[6] ts
- moreutils package
[7] eog
[8] gimp
[9] convert
- ImageMagick package
[10] tesseract

- 用这个 command 确保有三种语言, 英文/繁体/简体:
[xiaobai@xiaobai sh]$ tesseract --list-langs
List of available languages (3):
eng
chi_tra
chi_sim
[xiaobai@xiaobai sh]$

如果没有繁体/简体(通常都是没有的 la),就安装语言包, 例如 dnf 安装:
- dnf install tesseract-langpack-chi_sim tesseract-langpack-chi_tra

- 不过那个代码是 dynamic list down  语言来 create dialog 的, 所以其实你可以有很多语言。

[11] gedit
[12] firefox
[13] curl
[14] xargs
- findutils package
[15] konsole
- 虽然 heavy, 我坚持安装 kde terminal 在 gnome 主要是因为只有 konsole 能支持全局 highlight 搜索, 其它 terminal 最多只能同时 highlight 一个。由于本人很依赖全局 highlight(grep 做不到的,跑完 command 又要重新跑多一次 grep 咩,又或者还要 copy 去 gedit 全局搜索 ? 天黑 lor), 所以真的很惊讶到现在 2016 年 gnome-terminal 还是没有这个功能。就算 terminology 很 cool 都然并卵。
[16] vimx
- vim-X11 package
[17] yad
[18] gnome-screenshot
[19] xmessage, X 都有吧,所以我才用它当检查 commands 不在的默认 dialog。
- [更正] Fedora 24 需要安装 org-x11-apps 才有 xmessage。也要安装 xdotool 才能给  shortcut key 那边用。

【4】
还有一些零碎的要点:
[1] 我用的是没有 wallpaper 的黑屏幕。Fedora 21 Gnome 3。
[2] 用 [Super+mouse] 有时会拉上去 top panel, 只要用 [Super+mouse] 拉下来即可。
[3] 需要 Notifications settings 那里 Enable "Show Pop Up Banners" 才能看到 Help menu dialog, 不过正常应该已经  Enable 的。
[4] 我用的 gnome extension 包括 Disable window is ready notification, 以及让 notification 出现在上面而不是下面的 Panel OSD
[5] 在 feh 按 [a] 会出现 --action
[6] [上/下键] 缩大小, 是和 [w] fit window 一起用的组合。
[7] scrot 选 area 的线条有时会闪出很多条线,用 gnome-screenshot 比较好。
[8] [Super+mouse], Super 键按一次其实已经是 drag 着了,不需要一直按,虽说我还是习惯一直按方便改位置。


【5】
my_gnome_area.sh script 代码 (comments 版):

#keep in mind, use >> instead of > to log
<<"TODO"
[1] Add open /tmp/ dir support, in case accidentally close
[2] Make #[1] and note dir open as this customized --action feh #The quick workaround is screenshot again on note window, not a MUST have feature though
[3] not sure if better default to "alwasy on top" when feh display
TODO
#User should ensure tesseract installed "tesseract-langpack-chi_sim" "tesseract-langpack-chi_tra"
#search and replace all for "firefox" and "drive-linux-x64" if you are prefer difference web browser or gdrive-linux-386 ...etc 
#use yad instead of zenity to support --on-top
for cmd in "mktemp" "shutter" "feh" "wmctrl" "notify-send" "ts" "eog" "gimp" "convert" "tesseract" "gedit" "firefox" "curl" "xargs" "konsole" "vimx" "yad"; do #moreutils for `ts` AND diff err filename help to distinguish the occurrence, which unreliable to prefix some title before stderr append to err file tricks #| ts is stdout only, |& is 2>&1 stdout+stderr, [optional 1]>/dev/null |& is stderr only #When `ls -R /tmp/* 2>&1 2>/dev/null | grep i` the 2nd 2>/dev/null actually bring 
<<"PIPE" #imagine: #will stderr "my_gnome_area.sh: line 4: imagine:: command not found" if not put '#' infront "imagine:"
original:
#nobody --> /dev/null fd
#1 symlink --> stdout fd
#2 symlink --> stderr fd

2>&1 means point to #1's fd
#nobody --> /dev/null fd
#1 symlink --> stdout fd
#2 symlink -----^ 
#nobody --> stderr fd

then 1>/dev/null means
#1 symlink --> /dev/null fd
#2 symlink --> stdout fd(so only #2 will pipe and become next command's #1)
#nobody --> stderr fd

So, `>/dev/null |&` same like `>/dev/null 2>&1 |`  and means stdout fd is empty to pipe (e.g. `ls -R /tmp/* >/dev/null 2>&1 |  grep i` will give empty, but `ls -R /tmp/* 2>&1 >/dev/null |  grep i` will got #2 as explained above)

Noted oso 2>/dev/null will only tied fd without execute remove yet, so if 2>/dev/null 2>&1 will still able to pipe

All due to no such thing stdin_pre_out and stdin_pre_err, instead only have one door for stdin per process/pipe which accept stdout only from prev pipe, stderr nid bundle with stdout or use other trick to pass to next pipe.
PIPE
command -v $cmd >/dev/null 2>&1 || {  LANG=POSIX; xmessage "Require $cmd but it's not installed.  Aborting." >&2; exit 1; }; :;
done

mkdir -p -- "$HOME/Pictures/print_screen_note/"
tmpj="$(mktemp /tmp/`date +"%s_%Y-%m-%d"`_XXXXXXXXXX.png)" #Use .jpg will blur, see below comments [#keyword 'blur']
tmpocr="$(mktemp -u /tmp/`date +"%s_%Y-%m-%d"`_ocr_XXXXX)" #-u means --dry-run, not -d
tmpocr_p="$tmpocr"+'.png'

if [[ "$@" == "--area" ]]; then
    gnome-screenshot -a -f "$tmpj" 2>&1 >/dev/null | ts >>/tmp/gnome_area_PrtSc_error.log #bug: blur quality rf: https://bugs.launchpad.net/ubuntu/+source/gtk+3.0/+bug/1512290 #for gnome-screenshot, blur img due to it's jpg, if use png will good quality

    #scrot -s "$tmpj" 2>&1 >/dev/null | ts >>/tmp/scrot_area_PrtSc_error.log
    #scrot -s -e 'mv $f'" $tmpj" 2>&1 >/dev/null | ts >>/tmp/scrot_area_PrtSc_error.log #originally the img is blur, then i figure out direct_shortcut/cmd no problem, only script(not exactly true, see later comment #1),  then use strace and found the filename diff, so i realize is bcoz "$tmpj" is set here and i play around `scrot -s /tmp/xxx` inside konsole and got error "giblib error: Saving to file /tmp/xxx failed". Then i realize script without predefined_filename have good quality [#1]. So the problem actually is predefined_filename even though still can output blur img to next instruction/feh. 
    #So why 'mv $f'" $tmpj" got mix single/double quotes ? Bcoz $f not suppose to be expand by bash, instead if should keep literaly '$f' and pass to scrot to interprete/process. And so we write '$f' for unexpand by bash, and "$tmpj" for expand by bash.
    #[REAL REASON] the above mentioned 'without predefined_filename have good quality' is misleading, bcoz the real reason is bcoz i use .jpg when `mktemp`, so either scrot or gnome-screenshot will both blur bcoz it assume i want JPEG which poor quality. But, if no predefined_filename means assume PNG by default, even after `mv` to .jpg, it's actually a PNG image(can check by `exiftool`) with wrong extension(`eog` will not show mismatch extension but `display` did).

elif [[ "$@" == "--countdown" ]]; then
    shutter -s -d 5 -c -e -o "$tmpj" 2>&1 >/dev/null | ts >>/tmp/shutter_PrtSc_error.log #shutter no nid agent custome shortcut key to works #-c include cursor, -e dont show shutter viewer after captured
    #gnome-screenshot -d 5 -f "$tmpj" 2>&1 >/dev/null | ts >>/tmp/gnome_area_error.log #unable include context menu with area #use xclock to show time if used
else
    echo "Invalid argument." | ts >>/tmp/PrtSc_error.log
    exit 1
fi

<<"GDRIVE" #deprecated since Google not strict on encoded anymore #oso remove on the top's checking
#Full request(refer it if not working): curl -s -F "image_url=" -F "image_content=" -F "filename=" -F "h1=en"  -F "bih=" -F "biw=" -F "encoded_image=@1460127392_2016-04-08_i092fx0gu2.png" https://www.google.co.in/searchbyimage/upload
#base64 url: echo "data:image/jpeg;base64,$(base64 -w 0 $tmpj)"
function gdrive () {
    img_id="$(drive-linux-x64 upload --share -f $1 | head -n1 | cut -f2 -d ' ')"; firefox -new-tab 'https://www.google.com/searchbyimage?site=search&sa=X&image_url=https://drive.google.com/uc?id='"$img_id"
    #Unless u can firefox open new tab return 200 google ok, otherwise sleep only lor, so you nid visits gdrive to delete manually if shutdown before wake up something
    #so, give up to 30 seconds for google get the uploaded large file
    sleep 30; drive-linux-x64 delete -i "$img_id"
}
export -f gdrive #use 'gdrive "$tmpj" &' to call
GDRIVE

#Bcoz common use of "Always on top" on feh, better if can focus zenity, but it's still mark as [todo] target at 3.2(mine is 3.14.0), rf: https://wiki.gnome.org/Projects/Zenity 
#zenity's -radiolist nid --hide-header if used, yad no such arg
#yad's has new args: --center(progress better on upper left(curr default) instead of middle), --separator='|'(set it even though currently is default for safety to parse "$ans") and --on-top over zenity
#depends on current mouse focus, zenity/yad/konsole will on relevant monitor display when pop up
#yad -pulsate not working but zenity works fine, but still --on-top more important than this progress bar animation, so still use yad
#keep in mind if konsole support language other than english then vimx's "setlocal spell spelllang=en_us" might nid consider to redesign to support misc lang, not MUST though
function ocr () {
    tmpj="$1"
    tmpocr="$2"
    tmpocr_p="$3"
    #[WRONG bcoz i'm accidentally put double (()) in 1st statements, actually no nid atom[-1]=${atom[-1]%?};  to remove trailing ')' ]
    #atom="($(tesseract --list-langs 2>&1))"; atom=(`echo "${atom#*:}"`); atom[-1]=${atom[-1]%?}; atom=(`echo "$(printf 'FALSE\n%s\n' "${atom[@]}")"`); atom[0]='True'
    atom="$(tesseract --list-langs 2>&1)"; atom=(`echo "${atom#*:}"`); atom=(`echo "$(printf 'FALSE\n%s\n' "${atom[@]}")"`); atom[0]='True'

    ans=(`yad --center --height=200 --width=300 --separator='|' --on-top --list --title '' --text='Select Languages:' --radiolist --column '✓' --column 'Languages' "${atom[@]}" 2>/dev/null`) && ans="$(echo "${ans:5:-1}")" &&  convert "$tmpj[x2000]" -unsharp 15.6x7.8+2.69+0 "$tmpocr_p" | yad --on-top --title '' --text='Converting ...' --progress --pulsate --auto-close 2>/dev/null && tesseract "$tmpocr_p" "$tmpocr" -l "$ans" 2>>/tmp/tesseract.log | yad --percentage=50 --on-top --title '' --text='Tesseracting ...' --progress --pulsate --auto-close 2>/dev/null && if [[ "$ans" == 'eng' ]]; then konsole -e "vimx -c 'setlocal spell spelllang=en_us' -n $tmpocr.txt" 2>/dev/null; else gedit "$tmpocr.txt"; fi

    rm "$tmpocr_p"
}
export -f ocr

<<"SEARCH_BY_IMG"
- https://developer.chrome.com/extensions/settings_override
- https://chromium.googlesource.com/chromium/src.git/+/46.0.2478.0/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
- http://extra.dyndns-web.com/105/10500021_1_JPG.TXT
- https://www.chromium.org/administrators/policy-list-3
- https://chrome.googleblog.com/2013/10/search-by-image-and-new-chrome-for.html
SEARCH_BY_IMG

feh -x \
-A "cp %F ~/Pictures/print_screen_note/%N" ${IFS# [1] no nid cp bcoz after mv still can navigate/zoom...etc. [UPDATE] use cp bcoz what if trigger eog after Enter ? [2] -A means --action0 too} \
--action1 "notify-send ' ' -u critical 'd: title, up/down: zoom, w: win_to_img, </>: rotate, *: orig, Enter/0: save to ~/Pictures/print_screen_note/, 1: Help, m/right_clic: context menu, 2: Always on top, 3: Remove always on top, 4: shutter, 5: eog, 6: gimp, 7: OCR, 8: Note directory(Left/Right to navigate), 9: Google. Alt+F7(Might cause mouse pointer lag) to move windows like Left_mouse_click+Super keys. After position changed, Esc to cancel, Enter to confirm.'" ${IFS# alternative is xmessage ''}  \
--action2 "wmctrl -a \"feh [1 of 1] - $tmpj\" -b add,above" ${IFS# [1] use wmctrl -l too see the title or feh without -x to double check [2] toggle,above not working}  \
--action3 "wmctrl -a \"feh [1 of 1] - $tmpj\" -b remove,above" \
--action4 "shutter $tmpj &" ${IFS# [1] 'sometime' no nid & like other gui [2] not sure why got use mktemp-like 10 chars create new /tmp/ file [3] feature: can set arrow} \
--action5 "eog $tmpj &" ${IFS# [1] nid & to continue play feh base image without have to close gui or xkill base img, but no nid disown [2] can drag and drop to fb comment}  \
--action6 "gimp $tmpj &" ${IFS# f free select, ctrl+shift+v from clipboard, ctrl+e export} \
--action7 "ocr $tmpj $tmpocr $tmpocr_p &" ${IFS# see #OCR comment} \
--action8 "feh -x ~/Pictures/print_screen_note/ &" ${IFS# only refresh latest pictures on next --action8} \
--action9 "(curl -sf --output /dev/null -w '%{redirect_url}' -F 'image_url=' -F 'image_content=' -F 'filename=' -F 'h1=en'  -F 'bih=' -F 'biw=' -F "encoded_image=@$tmpj" 'https://www.google.com/searchbyimage/upload' | xargs -rL1 firefox -new-tab)&" ${IFS# see #gdrive comemnt}  \
"$tmpj" 2>&1 >/dev/null | ts >>/tmp/PrtSc_error.log
<<"OCR"
[1] quality 100% bigger size but same output.
[2] -alpha reset or activate or deactivate same and copy is bad.
[3] -colorspace gray is lose even though have some win.
[4] recommended 0x0.75+0.75+0.008 if larger than 500 pixels is bad,
[5] no nid care about random files for ocr, support multi convert in the same time is overkill.
[6] use "Always on Top" for other windows is normal to build your screen layout :)
[7] use ()& to bundle whole commands to bg, not just put at the end.
[8] For unknown reason tesseract normal log oso stderr, so nid /tmp/tesseract.log to avoid ocr success still update PrtSc_error.log.
[9] got `convert -monitor` but how to pass its updating % to zenity on the fly 
[10] zenity 2>/dev/null to discard "Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged."
[11] gedit better chinese chars look, and no point check spelling
[12] can better if able make konsole pop up in medium win size

rf1: http://www.imagemagick.org/Usage/resize/#resize_unsharp, rf2: http://stackoverflow.com/questions/9480013/image-processing-to-improve-tesseract-ocr-accuracy (radius = 6.8, amount = 2.69, threshold = 0, which 6.8+1 and *2, threshold 0/255 still 0), rf3: http://www.imagemagick.org/Usage/blur/#unsharp, rf4: http://www.imagemagick.org/discourse-server/viewtopic.php?t=23747, rf5: http://www.imagemagick.org/discourse-server/viewtopic.php?t=22998
OCR

【6】[更正] 不同于 Fedora 21, 新的 Fedora 24 的 notify-send 需要题目至少要有 '  ' 才能看到完整的内容。Credit

有一些无法实现的,如 gimp free selection 变成相对应的 borderless。

无论如何,想象一下未来,随手一剪,就能把浏览器的穿一个洞。随手一剪,就能把 fb 的 album 拉出来变成 standalone 的 window。

[更新: kali]
本人用  debian based 的 kali 2016.2 后,发现一些不同的地方。
[1] 安装的命令: sudo apt-get install tesseract-ocr-chi-sim tesseract-ocr-chi-tra yad gimp moreutils notify-osd libnotify-bin wmctrl feh shutter xdotool vim-gtk3
[2] 其中, tesseract 改了一点名字,notify-osd 和 libnotify-bin 提供 notify-send。要注意的是,安装 vim-gtk3 后,  有了 gvim,然后做 `mv /usr/bin/gvim /usr/bin/vimx` 以及 `ln -s /usr/bin/vimx /usr/bin/gvim`,理由是我的 Fedora 24, vimx 本来就是 link 去 gvim,只不过必须要用 vimx 的名义才不会出现新的 GUI, 而是在 terminal 里头。(更新) 好像是 sudo apt-get install vim-gnome 才对,总之刚才被 vimrc 搞得团团转我现在很晕,不懂 default 是怎样的 (现在是 /usr/bin/vimx -> /etc/alternatives/gvim* --> ... ---> /usr/bin/vim.gtk3*)。
[3] xdotool 不稳定,把那个原本 <Super+S> 的 agent 按 Backspace disable 掉它。<Super+S> 需要 restart ganti 掉原本的 key 才稳定。
[4] export -f ocr 竟然不能 work !!! 应该是 kali 默认用速度快但功能老牙的 dash 弄到的。所以把 OCR 那部分拉出来放在 /usr/bin/ocr,首行加上 #!/bin/bash,然后 `sudo chmod +x` 它:



[再更新:]
我刚才终于有空研究了一下,发现是 feh 默认使用 sh, 或 kali 的 dash (用 type -a 的 error 是一样的,就是不能用 -a)。这里的 export -f ocr  运行在 bash 当然只对 bash 有效而不是 dash,所以不能把问题归咎于 bash 不支持 export。 改成 --action7 "/bin/bash -c \"ocr $tmpj $tmpocr $tmpocr_p & \"" ${IFS# see #OCR comment} \ 后,问题即可解决。

[更新: Ubuntu 17.04]
[1] 默认是 <Alt> 键+ left-click 来搬图片 window。 必须打开 dconf-editor, 然后去 org → gnome → desktop → wm → preferences → mouse-button-modifier 把 <Alt> 改成 <Super>。
[2] 还是必须用 /usr/bin/ocr 解决类似 kali 的 `export -f ocr` 不 work 问题。

[Skyshot]
我独自开发的革命性 screenshot app, Skyshot 在 Google Play 上架啦。
免费+无广告,欢迎亲们下载哟 爱你们
https://play.google.com/store/apps/details?id=com.blogspot.diannaoxiaobai.skyshot



[更新]
后来我自创的 print screen 风格已很完善了,此文没更新我使用 ev_test 来达成浏览 /tmp/ 文件。