ラベル Quantum GIS の投稿を表示しています。 すべての投稿を表示
ラベル Quantum GIS の投稿を表示しています。 すべての投稿を表示

2019年10月11日金曜日

geotiff の変換あれこれ忘備録

ウィンドウズのバッチでまとめて見ました。
Windows 10 がコマンドプロンプトの utf-8 に対応したため、chcp 65001 をしてコマンドを実行した方が、トラブルが少ないです。

geotiff ファイルから png ファイルに変換する(goetiff to png)

if "%1"=="" goto err
chcp 65001
GDAL_TRANSLATE -OF PNG -B 1 -B 2 -B 3 %1.tif %1.png
goto end
:err
echo param1 [basefilename]
:end


geotiff を分割する(divide geotiff)

if "%1"=="" goto err
chcp 65001
echo divide geotiff 5000x5000
mkdir %1
call gdal_retile -ps 5000 5000 -targetDir %1 %1.tif
:err
echo param1 [basefilename]
:end


png の色を変換する

if "%1"=="" goto err
chcp 65001
convert %1.png -fill "#FEFEFE" -opaque "#FFFFFF" %1_.png
convert %1_.png -fill "#010101" -opaque "#000000" %1_dst.png
:err
echo param1 [basefilename]
:end


png を分割する(divide png)

if "%1"=="" goto err
chcp 65001
echo divide png 5000x5000
convert %1.png -crop 5000x5000 +repage +adjoin %1\%1_%%02d.png
:err
echo param1 [basefilename]
:end


World Fileを出力する(export world file(*.tfw) from geotiff)

if "%1"=="" goto err
chcp 65001
for %%s in (*.tif) do listgeo -tfw %%s
:err
echo param1 [basefilename]
:end

2015年6月29日月曜日

QGISの作るshapefileのdbf

しばしば ISO-8859-1 というコードページに解釈されるケースが多いので、そのようなファイルがどうなっているのか調べてました。

DBFファイルの先頭から 29バイト目 の0x0057 とかで入っていて、87=ISO-8859-1となってます。
日本語版のArcGISで、これを読むと、ちゃんとSJISとして解釈してくれる。もうたまりませんわ。
 ISO-8859-1が多数派なんで、自然な流れかと。

ちゃんとしてくれないツールが多くて閉口します。

2015年2月4日水曜日

QGis Plugin builder エラー備忘録

QGis Plugin Builder を使ってプラグインを作成すると、途中から
Traceback (most recent call last):
  File "C:/PROGRA~2/QGISBR~1/apps/qgis/./python\qgis\utils.py", line 208, in startPlugin
    plugins[packageName] = package.classFactory(iface)
  File "C:/Users/oki.HNS/.qgis2/python/plugins\Bar\__init__.py", line 34, in classFactory
    from .Foo import Bar
  File "C:/PROGRA~2/QGISBR~1/apps/qgis/./python\qgis\utils.py", line 460, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
  File "C:/Users/oki.HNS/.qgis2/python/plugins\Bar\Foo.py", line 26, in 
    import resources_rc
  File "C:/PROGRA~2/QGISBR~1/apps/qgis/./python\qgis\utils.py", line 460, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
ImportError: No module named resources_rc
なるエラーに遭遇
c:\work\any>"c:\Program Files (x86)\QGIS Brighton\bin\pyrcc4.exe" resources.qrc -o resources_rc.py
として、リソースのコンパイルを行う事。

2014年11月6日木曜日

GDAL-1.11.1 における ShapeDriver の日本語設定

前回「GDAL-1.10.1 の日本語環境ではまった」からの続きです。 うまく行ったり、行かなかったりは、文字コードが UTF-8 だったり SJIS だったりと、判別のしようが無い Shape が混在していたのが大きな原因でした。 それで、定説の 環境変数
set SHAPE_ENCODING=LDID/19 
ですが、そこを解釈するコードは、このようになっております。
CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage )

{
    CPLString osEncoding;
  osEncoding.Clear();

    if( pszCodePage == NULL )
        return osEncoding;

    if( EQUALN(pszCodePage,"LDID/",5) )
    {
        int nCP = -1; // windows code page. 

        //http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM
        switch( atoi(pszCodePage+5) )
        {
          case 1: nCP = 437;      break;
          case 2: nCP = 850;      break;
          case 3: nCP = 1252;     break;
          case 4: nCP = 10000;    break;
          case 8: nCP = 865;      break;
          case 10: nCP = 850;     break;
          case 11: nCP = 437;     break;
          case 13: nCP = 437;     break;
          case 14: nCP = 850;     break;
          case 15: nCP = 437;     break;
          case 16: nCP = 850;     break;
          case 17: nCP = 437;     break;
          case 18: nCP = 850;     break;
          case 19: nCP = 932;     break;
          case 20: nCP = 850;     break;
          case 21: nCP = 437;     break;
          case 22: nCP = 850;     break;
          case 23: nCP = 865;     break;
          case 24: nCP = 437;     break;
          case 25: nCP = 437;     break;
          case 26: nCP = 850;     break;
          case 27: nCP = 437;     break;
          case 28: nCP = 863;     break;
          case 29: nCP = 850;     break;
          case 31: nCP = 852;     break;
          case 34: nCP = 852;     break;
          case 35: nCP = 852;     break;
          case 36: nCP = 860;     break;
          case 37: nCP = 850;     break;
          case 38: nCP = 866;     break;
          case 55: nCP = 850;     break;
          case 64: nCP = 852;     break;
          case 77: nCP = 936;     break;
          case 78: nCP = 949;     break;
          case 79: nCP = 950;     break;
          case 80: nCP = 874;     break;
          case 87: return CPL_ENC_ISO8859_1;
          case 88: nCP = 1252;     break;
          case 89: nCP = 1252;     break;
          case 100: nCP = 852;     break;
          case 101: nCP = 866;     break;
          case 102: nCP = 865;     break;
          case 103: nCP = 861;     break;
          case 104: nCP = 895;     break;
          case 105: nCP = 620;     break;
          case 106: nCP = 737;     break;
          case 107: nCP = 857;     break;
          case 108: nCP = 863;     break;
          case 120: nCP = 950;     break;
          case 121: nCP = 949;     break;
          case 122: nCP = 936;     break;
          case 123: nCP = 932;     break;
          case 124: nCP = 874;     break;
          case 134: nCP = 737;     break;
          case 135: nCP = 852;     break;
          case 136: nCP = 857;     break;
          case 150: nCP = 10007;   break;
          case 151: nCP = 10029;   break;
          case 200: nCP = 1250;    break;
          case 201: nCP = 1251;    break;
          case 202: nCP = 1254;    break;
          case 203: nCP = 1253;    break;
          case 204: nCP = 1257;    break;
          default: break;
        }

        if( nCP != -1 )
        {
            osEncoding.Printf( "CP%d", nCP );
            return osEncoding;
        }
    }

    // From the CPG file
    // http://resources.arcgis.com/fr/content/kbase?fa=articleShow&d=21106
    
    if( (atoi(pszCodePage) >= 437 && atoi(pszCodePage) <= 950)
        || (atoi(pszCodePage) >= 1250 && atoi(pszCodePage) <= 1258) )
    {
        osEncoding.Printf( "CP%d", atoi(pszCodePage) );
        return osEncoding;
    }
    if( EQUALN(pszCodePage,"8859",4) )
    {
        if( pszCodePage[4] == '-' )
            osEncoding.Printf( "ISO-8859-%s", pszCodePage + 5 );
        else
            osEncoding.Printf( "ISO-8859-%s", pszCodePage + 4 );
        return osEncoding;
    }
    if( EQUALN(pszCodePage,"UTF-8",5) )
        return CPL_ENC_UTF8;

    // try just using the CPG value directly.  Works for stuff like Big5.
    return pszCodePage;
}
これのディスカッションは、ESRI社のフォーラムで話題になっていました。
コード中の解説ページhttp://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTMが詳しいです。
CP932 に相当するケース文の値は、0x7B でなければなりませんから、10進数にしますと、123になります。上記コードと照らしあわせても整合がとれていますよね? という事で、LDID/19 でもOKなのですが、
set SHAPE_ENCODING=LDID/123 
を設定すると、CP932 に変換してくれる。
もしくは、最初から CP932 を指定していれば、LDID/の変換をパスして、上記関数を通った後の値が評価されるので
set SHAPE_ENCODING=CP932 
でもOKだったという事になるのでしょうか? 拡張子 DBF ファイルの 29バイト目に、case 文の値か、UTF-8なら -1 == 65535 == 0xFFFF を設定するように改善していけば良さそうですよね?
と、思ったら、-1 は CPACP 扱い? int は 32bit 以上で、65535 == 0xFFFF の解釈で考えればOKでしょうか? 同日追記:  実は SHAPE_ENCODING= を設定しない方が、うまく動く場合もあるようです。どうも、前回DBFファイルに設定があった場合は、SHAPE_ENCODINGは使用されないような事を書きましたが、その記述が間違いだったみたいです。そして、SHAPE_ENCODING=UTF-8 と設定してみましたが、挙動が違うような・・・。もうちょい、突っ込んで調べてみます・・・

2012年8月30日木曜日

QGis Python Plugin と日本語の周辺3

 前回、UTF8で保存したバッチファイルを実行すればOKです。なんて書きましたが、問題がありました。 ウィンドウズのコマンドプロンプトが、コマンドラインの一部の文字コードの値を変更してしまうのです。そのため、使う文字コードによっては、まともに動作しません。  とりあえず、判明したのは「先」という漢字です。バイナリで表現すると、0xE5,0x85,0x88 の組みになります。もしかしたら、ANSI.SYS とかが組み込まれてて悪さしてるのかな?というのが頭を過ぎったのですが、Windows7 あたりでは、config.nt ファイルや、autoexec.nt ファイルなんて、ありませんでした。  コマンドプロンプトで chcp 65001(=UTF8) とか指定できますが、コンソールを通過すると文字化けするので、現時点では、まともに動作しません。よって、コマンドラインから入力される文字列は、MBCS (日本の場合 CP932=SJIS=ShiftJIS)に限定され、選択肢はありません。ウィンドウズだけのために、UNICODE文字セットを標準としてコンパイルするのは、問題があると思いますので、最小限の対処法は、入力値を MBCS から UTF8 に変換してやる事になります。  では、これを国際的に実装しようと思ったら、MultiByteToWideChar API を使って CPACP (= CP0) から、UNICODE に変換し、WideCharToMultiByte で UTF8 (=CP65001) にする以外に方法がありません。そうです、CPLWin32Recode 関数に "CP0" , "CP65001" という変換を促してやればいいのです。リポジトリに取り込まれたコードでは、CP0 は使わないだろうと思って、入力条件として コードページ > 0 としてしまったので、この条件を >= 0 とするよりありません。後、内部でUNICODEに相互変換する関数の実装があるのですが、変に複雑なんでウィンドウズの場合は MultiByteToWideChar と WideCharToMultiByte の関数に置き換えてあげた方が良いと考えてます。これらの変更を加えた上で、ogr2ogr 等の全てのコマンドプログラムに対して、コマンドの引数の文字コード変換を行うコードを挿入する必要があります。CPLArgumentConvert とかいう関数を設置してあげて、コーディング・ガイドラインを提示してあげた方が良いのかもしれません。という辺りを GDAL/OGR Develpment ML に投げてみようかと考えてます。 追記:GDAL_FILENAME_IS_UTF8 というのは、ウィンドウズの場合必須になります。ここを NO に設定すると、英語圏以外の文字コードは動作しません。  

2012年7月19日木曜日

QGis Python Plugin と日本語の周辺2

環境

  • Windows 7 x64
  • Quantum GIS Lisboa 1.8
  • GDAL/OGR 1.9.1

   いろいろと思考錯誤していて、GDAL/OGR がどのように多言語に対応しようとしているのか、わかってきました。
QGis Python Plugin と日本語の周辺1 に書いていたコードは、実はベストプラクティスでは無い事が判明いたしました。

  まずは、基本的なおさらいから…
Linux, mac 等の環境では、UTF8 で文字コードを取り扱うのが基本になります。それに対して Windows では MBCS がベースで、プログラム内部の文字コードは、MBCS か UNICODE(UCS2) を選択します。Visual C++ のコンパイルオプションで、どちらを選択するか可能なのですが、もう少し中身を説明すると、Windows API には、MBCS 系の文字コードを引数にとる HogeA という大文字 A をサフィックスにとるものと、UNICODEの文字コードを引数にとる HogeW という大文字 W をサフィックスにとるものが対になって存在します。C言語では、単に
#ifdef _UNICODE
#define Hoge HogeW
#else
#define Hoge HogeA
#endif
というように、マクロで切り替えているだけなのです。   ですので、MBCS系の文字コードでコンパイルをしていても、UNICODE系のAPIをコールする事は可能となっています。

  ここから、本題に入ります。QGIS では、GDAL_FILENAME_IS_UTF8 = YES を前提としています。それは、どのようなトリックかというと、ogr2ogr.exe 等の実行ファイルのパスは MBCS でないと実行できません。ところが、コマンドラインのオプション引数は MBCS である必要は、ありません。極端な話、UTF8 の文字コードをコマンドラインのオプション引数に渡しても問題ありません。   GDAL/OGR の shape ドライバでは、Windows 環境かつ、GDAL_FILENAME_IS_UTF8 = YES であれば、UTF8で引き渡された文字コードを内部で UNICODEに変換して、ファイル操作を行うように書かれていました。この手法でいけば、windows 付属の iconv.dll では、UTF8 と UNICODE 間の変換さえ、うまく行けば、IO(入出力回り)の文字化けに対応できる事になります。

  では、どうすれば日本語のファイルをコマンドラインから扱う事ができるか?
GDAL_FILENAME_IS_UTF8 = NO というような設定は、実は一切不要でして、サクラエディタなどのUTF8が扱えるエディタを使って、バッチファイルを作成し、ファイルを保存する時に、文字コードを「UTF8」にして保存してやればOKでした。QGISのインストール先を日本語の混じったフォルダ下にしなければ、これで、問題なく動くはずです。
UTF-8で書かれたバッチファイルを実行する事です。

問題は、Python で、どうやって UTF-8 な文字コードを subprocess.call に引き渡す事ができるのか。ここが、わかりませんorz...。decode encode('utf-8') してやっても、文字化けします。どうも、スクリプトは自由度が低くて相性の悪さを感じます(>_<)。 2012/07/24 追記:"日本語" の "語" が python の文字コード変換で文字化けするので、自前で DLL を作成して、その中で文字コード変換するようにした。 2012/08/30 追記:その3に続く

2012年7月12日木曜日

QGis Python Plugin と日本語の周辺1

QGIS の python plugin を書いていて、やはり日本語の処理に四苦八苦したので、判明した事をチビチビと書いていこうと思います。ノウハウが溜まる度に書き足すつもりなので、その1としました。どれぐらいの頻度で続くのかは、書いてる本人にもわかりません。

 文字コードの国際化に関する状況は、刻々と変化する可能性が高いので、環境を明記しときます。
  • Windows 7 (x64)
  • GDAL 1.9.1
  • Quatom GIS Lisboa 1.8.0

 Windows 環境において、GDAL/OGR あたりで、日本語のファイル名を使おうと思ったら、環境変数「GDAL_FILENAME_IS_UTF8」に「NO」と設定しないと、ogr2ogr 等のコマンドでファイル名が不正だとエラーにされてしまう現状があります。

 それなら、思い切ってコントロールパネルの「システム環境設定」に、GDAL_FILENAME_IS_UTF8 = NO と設定してしまえば良いじゃないか?と設定したら、ものの見事に嵌りました。なんと、QGISでshapefileを開こうとするとエラーになってしまいます。なんてこったい!QGIS内部では、UTF8でファイル名を扱っている雰囲気が漂ってます。これに関しては、現段階では確認できていません。

 プラグインのコードで、QFileDialog からファイル名を取得するコードを見てみましょう

    fileName = QFileDialog.getSaveFileName(None,QString.fromLocal8Bit("Select a file:"), "", "*.tapgis")
    if fileName.isNull():
      return
    fname = unicode(fileName.toLocal8Bit(),'mbcs')
  はい、ウィンドウズでは、ファイル名はOEMの文字コードセットになりますので、multi byte char set  つまり、SJIS(CP932)になっております。python なんて、ほとんど知らねぇよだったので、unicode という名前の関数が、文字コード・セットを指定して文字列を初期化する関数だと判るまでに丸一日費やしました。
  さて、こいつを ogr2ogr のコマンドに引き渡すとします。

  実はファイル名に半角スペースが混じっている場合には、”path" というようにダブルクォーテーションでパスを括ってやらなければなりません。逆に半角スペースが混じっていない場合には、path というようにダブルクォーテーションで囲ってはいけません(何この仕様・・・くたばれ)。という事情は、すっ飛ばします。
  # ogrvars には "-overwrite" 等のオプション文字列が渡される
  def CallRWTools(self, infile, outfile, ogrvars):
    import os
    try:
      import subprocess
      path = str(QgsApplication.prefixPath()).rsplit('/', 2)[0]
      pcmd = path + '\\bin\\ogr2ogr';
      fmt = '%s -f "tapgis" %s %s %s'
      cmd = fmt % (pcmd, outfile, infile, ogrvars)
      # ファイル名がUTF8ではないという状態に変更
      os.environ["GDAL_FILENAME_IS_UTF8"] = "NO"
      subprocess.call(cmd.encode('mbcs'), shell=True)
      #cmd3 = "echo " + cmd + " > " + outfile + ".txt"
      #subprocess.call(cmd3.encode('mbcs'), shell=True)
      #cmd2 = "notepad " + outfile + ".txt"
      #subprocess.call(cmd2.encode('mbcs'), shell=True)
    finally:
      # ファイル名がUTF8であるという状態に戻す
      os.environ["GDAL_FILENAME_IS_UTF8"] = "YES"
  はい、QGIS 内部では、GDAL_FILENAME_IS_UTF8 = YES を前提としているので、コマンドを呼び出す間だけ、GDAL_FILENAME_IS_UTF8 = NO に変えてコールします。あと、WIndows シェルでは mbcs なので、encode('mbcs') してやらないと、正しいコマンド引数になりません。

  ここまで書いても、日本語の問題は残ります。今度は、ogr2ogr のオプション文字列が mbcs のままドライバに渡されるためです。自分の書いたドライバでは、sqlite3_open という関数をコールしているので、OGRDriver の OGRDataSource::Open, OGRDataSource::Create という関数内で渡されたファイル名が mbcs なので utf8 へ文字コード変換してやる必要がありました。   また、OGRDataSource::CreateLayer に渡されるレイヤ名は、変換元のデータソースのOGRDriver の実装に依存している状態なので、どんな文字コードが渡されるのか、未知数です。shape driver の実装では、-nln オプションでレイヤ名を指定しない場合には、ファイル名からレイヤ名を生成しているので、mbcs の文字コードが来ました。注意しなければならないのは、これは Windows の日本語OS 独特の状況においてのみ発生します。Windows の Laten1なOSの環境では、おそらく Laten1の文字コードが来るという結果になるでしょう。-nln オプションも生の文字コードが渡されるので、同様の結果になります。

  このように、locale でなんとかしようという発想は、破綻するので utf8 で統一的に扱う必要性が高いと思います。いちいちロケール指定してたら大変です。ウィンドウズの場合は、CPACP を有効活用する方向が望ましいと思います。 2012/07/19 追記: その2に続く 2012/09/05 追記:結局、ウィンドウズ環境では、GDAL_FILENAME_IS_UTF8 = YES を前提にコードが書かれてあるので、その1のアプローチはダメダメでした。