JW_CAD Viewer DXFに対応してたり

そういえば、JW_CAD ViewerのDXF対応完了してました。やればなんとかなるものです。

ですが、DXFのレイヤーの表示設定はJW_CADのもののままなので、わかりずらいかもしれません。

機能の追加で、寸法計測機能を付けました。

機能を増やしてなにげにボタンが多くなったので、そこを改良しました。

そんな感じで少しづつ改善していきます。

電話に応答するプログラムができない件

AmazfitButtonControllerで電話に応答することができないかという要望がありました。
なんとなく難しそうな予感はしましたが、MacroDroidというアプリで試したらできたので、いろいろ調べて実装しました。
しかし、うまくいかない。

よくよく考えたら、勝手に応答するプログラムを作られると、知らない間に課金が発生して危ないので禁止されているのではないだろうか?
きっとそういうことだ。そういうことにしてあきらめよう。

JCodecでh.264ファイルからAndroidのBitmapを取得(最初のフレーム)


DSGViewer を作るためにh.264を扱う必要がありました。h.264なんてMediaCodecで簡単!と思っていたら全然うまくいかず挫折しました。h.264でもmp4なら簡単にできたのですが、h264のrawデータ(というのか?最初が00 00 00 01で始まるやつ)がうまくいかない。

悩んでいても仕方がないので、javaだけでデコードできるライブラリを探したところ、JCodecを見つけて試行錯誤しながら使うことができました。使って分かったことを記録します。JCodecはjavaですが、kotlinでいきます。エラー処理やnullチェックは抜かしています。

まず、使うためにここのGetting startedを参照し、build.gradleを編集します。

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    //追加 compileをimplementationに置き換え
    implementation 'org.jcodec:jcodec:0.2.3'
    implementation 'org.jcodec:jcodec-android:0.2.3'
}

追加の部分は、そのままコピーするとcompileの部分で警告が出るので implementation に置き換えました。
あと、Bitmapの確認用にMainActivityにはImageViewを置いておきます。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <ImageView
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:srcCompat="@android:color/holo_blue_dark"
            android:id="@+id/imageView"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    
</android.support.constraint.ConstraintLayout>

h264から最初のフレームを取り出して表示してみます。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        imageView.setImageBitmap(getFirstFrame())
    }
    fun getFirstFrame() : Bitmap{
        val file = File("/sdcard/000.h264")
        val buf = NIOUtils.fetchFromFile(file)
        val es = BufferH264ES(buf)
        val nextFrame  =  es!!.nextFrame()
        val decoder = H264Decoder()
        val pic = Picture.create(1280, 1024, ColorSpace.YUV420)
        val op = decoder.decodeFrame(nextFrame.data, pic.data).cropped()
        return AndroidUtil.toBitmap(op)
    }
}

pic = Picture.create(1280, 1024, ColorSpace.YUV420)は、デコードする画像のバッファーが必要ということで、画面サイズとかは仮です。 ColorSpace.YUV420 は、RGBにしたらダメでした。デコードした後にcropped()とやると画像サイズをちゃんと合わせてくれるみたいです。

ひとまずこんな感じ。ディスクから読むのでManifestのパーミッションの設定は忘れずに。次は任意のフレーム取得へ続く。

kotlinのenumをIntに

enumをintentで使いたくて、Intに相互変換できないか調べた。結果は、以下のようにしたらできた(これが正解かはわからない)。

    enum class ListHeight {
        SMALL,
        MID,
        LARGE
    }

    var listHeight1 = ListHeight.LARGE
    var i = listHeight1.ordinal                 //i==2
    var listHeight2 = ListHeight.values()[i]     //listHeight2 == ListHeight.LARGE

ordinalで順番(?)で、values()でenum値の配列が取れる。