ビギグラマーのノート

自作PCやプログラミングについてのブログです。

『OpenCV for iOS』ポートレート撮影しUIImageToMatすると画像が横向く

 はじめに

 いつにも増して題名がイミフですので、写真で説明しましょう。

f:id:BegiGrammer:20180904002121p:plain

 上の段が現在カメラで見えているものです。そしてその下の段がOpenCVのUIImageToMat・MatToUIImageを経てUIImageViewに貼り付けられた画像になります。ポートレートで撮影しているにも関わらず、横向きになっていることがわかります。これをどうにかしようとするのがこの記事になります。

原因と解決法

 iPhoneの縦長撮影は実を言うと横向き撮影とデータは変わりません。そのためkeyで横向き・縦向きを制御しているのですが、OpeCVのMatに変換されるとそのkeyが脱落してしまいます。そのため90度回転した画像が送られてくるわけです。

 以下が元々のキーを付け直す作業になります。

ネタ元

stackoverflow.com

NavigationBarとStatusBarの隙間を埋める

 はじめに

 NavigationBarを手動で追加した場合StatusBarの色が違います。文字にすると表現しずらいため画像で表すと。

f:id:BegiGrammer:20180703213334p:plain

 こんな感じになっているところを次のようにしたいと思います。

f:id:BegiGrammer:20180703213448p:plain

方法

UIBarPositionDelegateを追加してNavigation Bar のdelegateにselfを設定する、そして

 func position(for bar: UIBarPositioning) -> UIBarPosition {

     return .topAttached

 }

これでNavigationBarがStatusBarまで延長されて良さげになるようです。

参照

日本語のHow to ブログがあったと思ったのですが、ざっと探す感じ見当たらなくなっていたため備忘録として残します。

stackoverflow.com

【Swift】UITextViewのカーソルの位置・サイズを取得する

前置き

 UITextViewはなかなか痒いところに手が届かないクラスだと思います。今回はTextViewのカーソルの位置をCGPointで取得したかったのですが、なかなか検索に引っかからなかったので備忘録として残しておきます。

コード

    func textViewDidChangeSelection(_ textView: UITextView) {

        guard let range = textView.selectedTextRange else {return}

        let cursor = textView.caretRect(for: range.end)

        print(cursor)

    }

 

参考

stackoverflow.com

MacのBluetoothイヤホンが異常に音質が悪い

 状況

 普段はiPhoneに接続して使っているこのPowerbeats3をMacに繋いで作業しようとしていた時のことでした。なんだこれ 異常に音質が悪い。言葉で表現するなら膜で隔たれた ぼやけた感じになっていました。

f:id:BegiGrammer:20180520101637p:plain

 

問題の把握

 このぼやけ具合は昔ハンズフリーを使った時の感じと似ています。そこでBluetoothの送信方式(コーデック)を確認します。コーデックはBluetoothを接続した状態で Optionキーを押しながら上に出ているバーのBluetoothボタンをクリックします。

f:id:BegiGrammer:20180526210633p:plain

 有効なコーデックがSCOになっていたらハンズフリーイヤホンとしてMacに接続されています。 

解決法

 ハンズフリーのコーデックから音楽鑑賞用のAACに戻すためにはイヤホンとして接続されているものを変えればいいのです。

 具体的には 設定 -> サウンド -> 入力 の「サウンドを入力する装置を選択」で内臓マイクに入力を切り替えます。

f:id:BegiGrammer:20180520103243p:plain

 あなたが音楽鑑賞をしつつこの設定をいじった場合一度音が途切れクリアな音に生まれ変わったのが確認できるでしょう。ここでもう一度Bluetoothのコーデックを確認して見ましょう。確認方法は上のバーのBluetoothボタンを Optionキーを押しながらクリックします。

f:id:BegiGrammer:20180526210711p:plain

 無事AACに切り替わったでしょうか。

参考

 Airpods codec stuck on SCO via Macbook Pro

 

【Swift 4】NSAttributedString ⇆ HTML の変換とUITextViewへの表示

 やりたいこと

 NSAttributedStringとUITextViewを使えばリッチなテキスト表現ができることはご存知かと思います。今回、なんらかのデータファイルからUITextViewへ表示し編集、それを保存する必要があったのでどうにかしようと思ったのです。

How to do

HTML → NSAttributedString

 let html = "<html>ほにゃらら〜</html>"

        

let encoded = html.data(using: String.Encoding.utf8)!

let attributedOptions : [NSAttributedString.DocumentReadingOptionKey : Any] = [

            .documentType : NSAttributedString.DocumentType.html,

]

let attributedTxt = try! NSAttributedString(data: encoded,

                                                              options: attributedOptions,

                                                              documentAttributes: nil)

textView.attributedText = attributedTxt

 tryを使っているので実装ではdo-catchが必須になります。

f:id:BegiGrammer:20180315033947p:plain

NSAttributedString → HTML

let attT = textView.attributedText!

let documentAttributes = [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.html]

let htmlData = try! attT.data(from: NSRange(location: 0, length: attT.length),

                                          documentAttributes: documentAttributes)

let html = String(data: htmlData, encoding: .utf8)

print(html ?? "Empty")

結果

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<meta http-equiv="Content-Style-Type" content="text/css">

<title></title>

<meta name="Generator" content="Cocoa HTML Writer">

<style type="text/css">

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 25.0px '.SF UI Display'; color: #e60012}

p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.SF UI Text'}

p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px '.SF UI Text'; color: #009944}

span.s1 {font-family: '.SFUIDisplay'; font-weight: normal; font-style: normal; font-size: 25.00pt}

span.s2 {font-family: '.SFUIText'; font-weight: normal; font-style: normal; font-size: 12.00pt}

span.s3 {font-family: '.SFUIText'; font-weight: normal; font-style: normal; font-size: 10.00pt}

</style>

</head>

<body>

<p class="p1"><span class="s1">Tomato</span></p>

<p class="p2"><span class="s2">English</span></p>

<p class="p3"><span class="s3">Royal blueberry blue and white.<span class="Apple-converted-space"> </span></span></p>

</body>

</html>

ご丁寧に全文描いてくれいています。

愚痴

 File → NSAttributedString → UITextView(編集) → なんらかのData → File

 こういうことをやりたいが為にこの一週間XMLでフォントスタイルを定義しそれを解読する奴を必死に作っていましたが、ひょんなことでこのような楽な方法を見つけてしまいました。わだじの いっじゅうかん かえじで!

参考

stackoverflow.com

stackoverflow.com

追記 2018/05/13

 上記のコードは変換する度にフォントサイズが大きくなって行きます。原因はスタイルシートのフォントサイズを指定する単位のptからpxへの変換の際にズレが生じているためです。なのでHTMLを出力する際にptをpxへreplaceする正規表現のパッチをつけて見ました。

 追記のためコードは下に移動 

 上記の出力されたHTMLを見てもらうとわかるのですがpタグのスタイルとspanタグのスタイルのフォントサイズの指定は数字こそ同じですが単位がpxとptになっています。このせいでNSAttributedString ⇄ HTMLと変換する度にサイズが大きくなっていってしまうのです。なので上記のコードではNSAttributedStringからHTMLへ出力された際にptをpxに単純に置き換えています。同様にHTMLからの変換の際にもスタイルシートのptをpxに置き換えています。なので外部からHTMLを持ってきてこれで変換した場合pt指定の箇所が崩れます。しかし、私の用途では外部から誰かの書いたHTMLを持ってくることはないのでpt-pxの数値計算を伴う変換は行なっていません。完全にApp内だけでHTMLを回すならばHTMLの出力の際に直しておくだけで良いのですが。

 あとUNIX系はHTMLのpt-pxの倍率が1になっていると聞いたのですが、iOSはどうやら違うみたいですね。

参考 -2

Swiftの正規表現はそんなに使わなくて毎回忘れてしまう orz

qiita.com

追記 2018/06/12

 改行のみの行の変換で<p>タグと<br>が同時使用され行が2倍になるのを発見したのでそれの修正コードをあげて置きます。見た感じではAttributedString -> HTMLの際のオプション NSAttributedString.DocumentAttributeKey には改行の際の不具合を治すためのものなどはなさそうなので、思い切ってCSSでbrタグを無効化しました。私はHTMLに明るくないのですがbrタグは最近嫌われているそうなので。

簡単な修正方法などがありましたら教えてください。お願いします。

 再々追記のためコードは下記

 これだけNSAttributedString ⇄ String の不具合?があるのはどうなんですかね?もしかしていい感じにHTMLを編集、描写できるTextViewライクなLibraryがあったりするのでしょうか。

追記 2018/08/10

 日本語を入力してHTMLに変換後、AttributedStringに再度変換するとLineHeightがおかしなことになっている不具合の修正をしてみました。

f:id:BegiGrammer:20180810153030p:plain

もともと入力した際はこのような間隔ですが、

AttributedString -> HTML -> AttributedString の操作をするとこうなります。

f:id:BegiGrammer:20180810153224p:plain

これは日本語を含むHTMLをAttributedStringに変換した際にLineHeightのMaximun = 0 Minimun = 23 になってしまう事が原因の一つです。これをこのようにするFixです。よくみてみるとOriginとは若干間隔が異なりますが、こっちの方が見やすいのでここで止めておきます。いくら調べても改善策が見付からなかったので放置した訳では断じてありません。()

f:id:BegiGrammer:20180810153400j:plain

【Xcode 9.2】PlaygroundでLibraryを使う

Xcode 9.4.1 現在この方法ではLibraryを追加できません。

 Playground Single View使ってますか?

 最近(それほど最近でもないけど)XcodeのPlaygroundにSingle Viewモードが追加されました。

f:id:BegiGrammer:20180104103033p:plain

いちいちテストアプリを作ってやっていくのはめんどくさいので非常に重宝していますが、Cocoapodで入れられるLibraryを使えないことが大きな欠点です。この記事ではそのSingleViewモードでLibraryを使えるようにします。

How to

 まずはPlaygroundのSingle View単体で作ります。

f:id:BegiGrammer:20180104103436p:plain

 次にCocoapodをインストールしたXcode Projectを作ります。これに必要なライブラリをよしなにインストールしておいてください。

 作成したおいたPlaygroundをXcode Projectにドラッグ&ドロップします。

f:id:BegiGrammer:20180104104548p:plain

 追加されるさいのオプションを聞かれるので、Add to targetしCopy item if neededにチェックを入れておきます。

f:id:BegiGrammer:20180104104758p:plain

 Playground追加後ビルドします。 これでプロジェクトに追加したPlaygroundの中で必要なライブラリがImportできるようになりましった。

f:id:BegiGrammer:20180104105748p:plain

Playgroundでライブラリを使うために色々とサイトを巡ったのですが、結局このような非常に簡単な方法にたどり着きました。全体的に見直して見ると、Workspaceに別に作っておいたD&DでPlaygroundを追加するだけでした。

お疲れ様でした

問題点

  • ソフトウェアキーボードが隠れて見えること
  • TextFeild等にMacのキーボード操作が効かないこと
  • アニメーションがラグいこと 
  • self.view.centerが使えないこと  (viewWillAppear内で使用可能)
  • たまにxcodeが落ちること (index out of rangeすると落ちる?)

追記

 しばらくデザイン関係のチェックのために使用していましたが、TableViewでミスるとXcodeが落ちたりして結構使いずらいことがわかりました。しかし、単純なTextLabelを作ってみたり、Libraryでデータを弄ってみたりすることに関しては非常に使いやすかったです。当方の環境がMacBook Pro Mid 2015 i7 2.2GHz iGPUなのでdGPUを搭載したものやiMacだとスムーズに作業ができるかもしれません。

参考

m.pardel.net

qiita.com

 

追記 -2018/06/29-

久しぶりにLibraryを含むPlaygroundを作成したところ、Playground内でLibraryの追加ができなくなっていました。私の環境では少し前からPlayground自体も2、3回書き直すとRunning Playground状態で動かなくなったりどうも不安定です。

【Java】EventListenerで他クラスにイベントのタイミングを伝える

 前置き

 諸事情でAndoroidではないデスクトップアプリでJavaを使用することになりました。私はSwiftしかりオブジェクト指向の言語で毎回クラス間、特に子→親の間のイベント通知に戸惑うようで今回も例に漏れず半日ほど唸っていました。

 SwiftではNotificationで比較的自由かつ簡単にクラス感のイベント送受信ができたのですが、JavaではEventListenerを作成することで大体同じような感じになりました。

 同じようにメソッドの呼び出しとしてsuperクラスによるものもありますが、これは単にメソッドを借りて実行しているため今回の用途ではうまく動きませんでした。

本文

 口で言うよりまずコードを見てもらった方が早いですね。

 

 今回は親となるReciveEvent.javaインスタンスにしてあるEventBeginning.javaからのイベントを受け取ると言うことをします。EventBeginning.javaeventListenerを実行するとのそのイベントが親のbuttonAction()を発火させると言うことです。

 この独自のEventListenerの構成を設定しているのがListenerInterfaceでこれに発火させるものを追加していくことができます。又、引数をEventListenerを指定すれば値を渡すこともできます。