planet-green.com

DxO OpticsPro用タイムラプス制作支援ツール



RAW現像ソフトのDxO OpticsPro 11でタイムラプス(微速度撮影)動画制作を支援するツールを作りました。
コマンドラインで実行するPythonのスクリプトで、GitHubで公開しています。

DxOKeyFrame.py
https://github.com/SapporoTK/DxOKeyFrame.py

作例


(上の動画ではオリジナル曲をBGMにしてみました。)


この動画では、日の出の前後の時間帯はAvモードで撮影し、当スクリプトで拡張露出補正オプションを有効にして明るさが滑らかになるようにしています。

とはいえ、まだチラつきが出てしまうので、それが今後の課題です。
ちなみに星の軌跡はFinal Cut Pro Xのエフェクトなので当スクリプトとは関係ないです。

»ç¶šãã‚’読む

コメント
planet-green.com

MacでVisual Studio + Xamarinを使ってみた感想



IT土方(by いらすとや)
アプリ開発の話。

クライアントさんに泣きつかれて頼まれてXamarinで作られたスマホアプリの修正をすることになり、少しだけ使ってみる機会がありました。

「Xamarin自体がバグだらけ。新しもの好きで人柱覚悟の人ならいいかもしれないけど、仕事ではちょっと怖くて使えない」

これが正直な感想です。

iPhoneとAndroidのアプリを共通のコードで作成できるというのが売りなのですが、実際に共通化できるのはロジック部分だけと考えた方がよさそうです。

一応、画面周りも共通化できるのですが、用意されているXamarin.Formという仕組みでは細かいレイアウトの調整が出来ないので、結局はiOSとAndroidで個別にネイティブの機能を呼び出すコードを書くことになると思います。

Xamarin.Form標準の機能だけだと、デザインの微調整に制限が多く、痒いところに全然手が届きません。

自社または個人で作るアプリならそうしたレイアウトの細部は無視することが可能かもしれませんが、クライアントさんがいる仕事だと、「ここのフォントサイズを変えてね」と言われて断るのは難しいのではないでしょうか。

»ç¶šãã‚’読む

コメント
planet-green.com

[開発/備忘録] WordPressでSchema.org用JSON-LDを出力(複数画像対応)



WordPressで構造化データ(schema.org用)のJSON-LDを<head>内に出力する関数です。function.phpに追記してください。

ネットで調べてみると似たようなコードはいくつかありましたが、複数の添付画像・複数のカテゴリーに対応したものが無かったので自作しました。

function insert_json_ld_for_schema_org()
{
	if( !is_single() || !have_posts() ) {
		return;
	}
	
  //あなたのサイトのロゴ画像をここで設定してください
  $logo = array(
		'@type' => 'ImageObject',
		'url' => 'http://*****/****.jpg',
		'width' => '240',
		'height' => '80'
	);
	
	while (have_posts()) {
		the_post();
		$category_info = get_the_category();
		if( count($category_info) > 1 ) {
			$articleSection = array();
			foreach( $category_info as $ct )
			{
				$articleSection[] = $ct->name;
			}
		} else 	{
			$articleSection = $category_info[0]->name;
		}
		
		//添付画像を取得
		$attachments = get_children( array( 'post_parent' => get_the_ID(), 'post_type' => 'attachment', 'post_mime_type' => 'image') );
		
		$images = array();
		foreach($attachments as $image) {
			$src = wp_get_attachment_image_src( $image->ID, 'medium' );
			$images[] = array(
				'@type' => 'ImageObject',
				'url' => $src[0],
				'width' => strval($src[1]),
				'height' => strval($src[2])
			);
		}
		
		//添付画像が無い場合はアイキャッチ画像を取得
		if( !count($images) ) {
			if( has_post_thumbnail() ) {
				$thumbnail_id = get_post_thumbnail_id(); 
				$src = wp_get_attachment_image_src( $thumbnail_id , 'medium' );
				$images = array(
                                	'@type' => 'ImageObject',
                                	'url' => $src[0],
                                	'width' => strval($src[1]),
                                	'height' => strval($src[2])
				);
			} else {
				//それも無い場合はロゴ画像をセット
				$images = $logo;
			}
		}
		$data = array(
			'@context' => 'http://schema.org',
			'@type' => 'Article',
			'headline' => get_the_title(),
			'author' => array(
					'@type' => 'Person',
					'name' => get_the_author(),
			),
			'datePublished' => get_the_date('Y-m-d'),
			'dateModified' => get_the_modified_time( 'Y-m-d' ),
			'articleSection' => $articleSection,
			'url' => get_permalink(),
			'mainEntityOfPage' => array(
				'@type' => 'WebPage',
				'@id' => get_permalink()
			),
			'publisher' => array(
				'@type' => 'Organization',
				'name' => get_bloginfo('name'),
				'logo' => $logo,
			),									
			'image' => $images,
		);
		
		//php5.4以前のバージョンではオプション引数(JSON_UNESCAPED〜)を削除すれば大丈夫だと思います。
		echo '<script type="application/ld+json">'
			.json_encode($data, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT)
			.'</script>'.PHP_EOL;
	}
	rewind_posts();
}
add_action('wp_head','insert_json_ld_for_schema_org');

出力サンプル。

<script type="application/ld+json">{
    "@context": "http://schema.org",
    "@type": "Article",
    "headline": "[Photo] 幌見峠のラベンダー園",
    "author": {
        "@type": "Person",
        "name": "tomoya"
    },
    "datePublished": "2017-04-08",
    "dateModified": "2017-04-08",
    "articleSection": "Photo",
    "url": "https://planet-green.com/horomitouge-lavender/1501",
    "mainEntityOfPage": {
        "@type": "WebPage",
        "@id": "https://planet-green.com/horomitouge-lavender/1501"
    },
    "publisher": {
        "@type": "Organization",
        "name": "planet-green.com",
        "logo": {
            "@type": "ImageObject",
            "url": "https://planet-green.com/wp-content/uploads/2017/03/Twenty-Seventeen-capture-2017-03-28-.jpg",
            "width": "640",
            "height": "573"
        }
    },
    "image": [
        {
            "@type": "ImageObject",
            "url": "https://planet-green.com/wp-content/uploads/2017/04/horomitouge-7399-720x480.jpg",
            "width": "720",
            "height": "480"
        },
        {
            "@type": "ImageObject",
            "url": "https://planet-green.com/wp-content/uploads/2017/04/horomitouge-7418-720x480.jpg",
            "width": "720",
            "height": "480"
        },
        (略)
    ]
}</script>

そのSchema.orgなんですが、仕様についてネット上の情報が錯綜している上に、公式サイトの説明も曖昧で、いまいちよくわからない部分が多いのですよね。

例えば、記事タイトルはnameプロパティで指定すると書いてあるサイトもあれば、headlineプロパティで指定すると書いてあるサイトもあります。
Schema.org公式サイトでは簡素にnameはname、headlineはheadlineと書いてありますが言葉の定義についての説明が無いのです。

しかもgoogleまで錯綜していて、Search Console(webmasterツール)の 〔その他のリソース〕 にある 〔構造化データ マークアップ支援ツール〕 を使って画像タグのマークアップをしても、〔構造化データ テスト ツール〕を使ってチェックするとエラーになるという状態です。

そこで上記のPHP関数は、私が調べた範囲において最大公約数的な解釈をして実装しました。
間違いがありましたらコメントでご指摘していただけると幸いです。

コメント
planet-green.com

[開発/備忘録][PHP] 複数の画像を結合した1枚のサムネイル画像を自動作成する



複数の画像を入力すると結合された1枚のサムネイル画像を作成するPHP用のライブラリです。
SNSなどでよく見かけるタイプの結合サムネイルです。
サイズは自動計算してくれます。某SNS用に作りました。
create combine thumbnail from multiple images.

System Requirements:
PHP v5.3+
ImageMagick

【実行例】

4枚の元画像を入力 / source image files



↓↓↓↓↓↓↓↓
連結して1枚のサムネイル画像を出力 / output a thumbnail  image
combine thumbnail library for php

元画像は1〜4枚に対応。

・2枚の場合は上下に並びます。 / in case of two src images
combine thumbnail library for php.(two images)

・3枚の場合は横に。 / in case of three src images
combine thumbnail library for php.(three images images)

コードと使用例。試しにGithub Gistにコードを載せてみました。

コメント
planet-green.com

[開発/備忘録] WordPress + Custom Fields に複雑な検索機能を実装する



先日、クライアントさんからの依頼でWordPress+カスタムフィールドで構築されたサイトに絞り込み検索機能を実装する必要が出てきました。
googleで検索すると下記のサイトに説明がありましたが、シンプルな全文検索にしか対応してないようなので、
これを参考にしつつ、もう少し複雑な検索(OR検索とAND検索の組み合わせ)に対応したものを作ってみました。

参考 http://www.deluxeblogtips.com/2012/04/search-all-custom-fields.html


global $wpdb;

//次のSQLに SQL_CACHE を含めているのは、レンタルサーバーによってはMySQLのクエリキャッシュの
//デフォルト設定を無効にしているところがあるので、明示的にクエリキャッシュを有効にするように指定している。
$sql = "SELECT SQL_CACHE DISTINCT posts.ID FROM {$wpdb->posts} posts";


//チェックボックスorセレクトボックスの検索(複数のAND検索)
//例えばcolorというフィールド名だとする。
//$_GET['color']にはカスタムフィールドの設定画面の選択肢の箇所で入力したラベルと値のうち、値の方が配列になって入ってくるとする。 
if( count($_GET['color']) )
{
	$flg_query = true;

	$sql .= " INNER JOIN {$wpdb->postmeta} tbl_color ON tbl_color.post_id=posts.ID AND tbl_color.meta_key = 'color'";

	$tmp_arr = array();
	foreach ($_GET['color'] as $item)
	{
		//シリアライズ化された文字列の中を全文検索する
		$keyword = '%' . $wpdb->esc_like( '"' . trim($item) . '"' ) . '%';
		$tmp_arr[] = "tbl_color.meta_value LIKE '{$keyword}'";
	}
	$sql .= " AND (" . implode(" AND ", $tmp_arr) . ") ";
	
	//↓ちなみにOR検索の場合はこうする
	//$sql .= " AND (" . implode(" OR ", $tmp_arr) . ") ";
}

//複数のチェックボックスorセレクトボックスがある場合は、ここに追記していく。


//注意点として、選択肢の値を 1,2,3・・や a,b,c・・のように設定すると
//他のフィールドと値が重複して正確な検索が出来ないので、全フィールドを通じてユニークな値にする必要がある。

$sql .= " WHERE posts.post_type='(※投稿タイプ名※)' AND posts.post_status='publish'";


//全文検索(AND検索)

//全文検索用キーワード
//$_GET['keyword']にはキーワードが半角スペース区切りで入っているとする。
$free_keyword = isset($_GET['keyword']) ? trim($_GET['keyword']) : "";    //「キーワード検索」

if( $free_keyword != "" )
{
	$arr_free_keyword = $free_keyword == "" ? array() : explode(" ", $free_keyword);
	$arr_free_keyword = array_unique($arr_free_keyword);

	if( count($arr_free_keyword) > 8 )
	{
		//検索キーワード数の上限をとりあえず8個までにする。
		//ここが無制限だと、意図的に膨大なキーワード数で検索を実行された時にサーバーの処理が追いつかなくなる危険性が生じるので。
		$arr_free_keyword = array_slice($arr_free_keyword, 0, 8);
	}

	$tbl_cnt = 1;
	foreach ($arr_free_keyword as $_key)
	{
		$tbl = "key" . $tbl_cnt++;
		$keyword = '%' . $wpdb->esc_like( trim($_key) ) . '%';
		
		$sql .= " AND (SELECT 1 FROM {$wpdb->postmeta} {$tbl} WHERE {$tbl}.post_id=posts.ID AND ( ({$tbl}.meta_key NOT LIKE '\_%' AND {$tbl}.meta_value LIKE '{$keyword}') OR posts.post_title LIKE '{$keyword}' OR posts.post_content LIKE '{$keyword}') LIMIT 1)";
		
		//↑DISTINCTにしてもいいのだが、LIMIT 1 の方が速度が早いと思われるので(ただし未検証)
	}
}


$post_ids = $wpdb->get_col($sql);	//検索でヒットした投稿データのIDが入る
$cnt = count($post_ids); //投稿数

if($cnt)
{
	$args = array(
		'post_type' => '(※投稿タイプ名※)',
		'post_status' => 'publish',
		'post__in' => $post_ids,
		
		//ページングする場合は次のパラメーターをお好みで
		'posts_per_page' => ****,
		'offset' => ***,
		
		//ソートする場合は	次のパラメーターをお好みで
		'meta_key' => '******',
		'order' => "ASC",	/* or DESC */
		'orderby' => "meta_value"
	);

	$posts = get_posts($args);
}
else
{
	$posts = array();
}

以下略

尚、テーブル wp_postmeta にインデックスを追加するとセレクトボックス・チェックボックスでの検索速度が向上すると思われます(ただしキーワードによる全文検索にはインデックスは効果ありません)。

例) ALTER TABLE wp_postmeta ADD INDEX idx_custom1 (post_id, meta_key(16), meta_value(16));

と、ここまで書いておいて言うのもなんですが、今回の記事で書いた方法は、小規模〜中規模のサイトまでしか通用しないということにご留意ください。

カスタムフィールドを追加していくとテーブル wp_postmeta の行数が等比級数的に増えていきます。
(私の知ってるクライアントでの例だとカスタムフィールド数が約60、登録ページ数が約30で wp_postmeta が約40万行でした。)

これだけ膨大なデータの中から検索を実行するわけなので、かなりの負荷になります。

最近、なんでもかんでもWordPress+カスタムフィールドで実装すようとするIT屋さんが少なくないようですが、データ数やアクセス数(PV)がある程度まで増えると負荷が増大して破綻するのは火を見るよりも明らかです。

データ数やアクセス数が大規模になりそうなサイトはWordPressに頼らずフルスクラッチで開発するべきです。

 

コメント
planet-green.com

[開発/備忘録] さくらのレンタルサーバーにPHPカレンダー関数をインストール



前回の記事で書いたように、仕事でさくらのレンタルサーバーの共用プラン(ビジネスプロ)を使っているのですが、PHPのカレンダー関数 が入ってないので、手動でインストールしてみました。

ちなみにカレンダー関数というのは、なかなか便利なもので、例えば 「2月1日から5月15日までを日次ループ処理したい」というような場合には、開始日と終了日をユリウス積算日に変換して単純なfor文のループに落とし込むことが出来ますし、ループの中では必要に応じてユリウス積算日からY-m-dやUnixタイムスタンプに変換して処理を行えます。しかも紀元前4713年以降であるなら、期間が数日でも数百年でも処理できるという優れものです。

インストール方法ですが、実は私、FreeBSDを触るのは今回が初めてでして、正直、ここから先は正しいかどうかを保証できませんのでご了承ください(笑

portコマンドが使えれば一発でインストールできるようですが、さくらの共用プランなのでroot権限がありません。
そこでまずは下記ページからダウンロードします。(PHP5.3の場合)

http://portsmon.freebsd.org/portoverview.py?category=misc&portname#misc/php53-calendar
ちなみにPHP5.x系最新版用はこちら。
http://portsmon.freebsd.org/portoverview.py?category=misc&portname=php5-calendar

一覧表の build environment のところに 84amd64-default 、84i386-default、91amd64-defaultと並んでいますが、どれを選択するべきなのか・・
私の使っているサーバーの情報をみると FreeBSD 9.1-RELEASE-p15 (中略) amd64と書いてあるので、91amd64-default をダウンロードすることにしました。

%
uname -a
FreeBSD *****.sakura.ne.jp 9.1-RELEASE-p15 FreeBSD 9.1-RELEASE-p15 #1: Wed Jun 11 02:25:45 JST 2014     admin@*****.sakura.ne.jp:/usr/obj/home/pkg/src/sys/SAKURA17  amd64

では、インストール。

% cd ~/src
% wget http://pkg.freebsd.org/freebsd:9:x86:64/latest/All/php53-calendar-5.3.28_3.txz
% tar Jxvf php53-calendar-5.3.28_3.txz
(※ ディレクトリ階層を保ったまま解凍される)
%  cp usr/local/lib/php/20090626/calendar.so ~/modules/

尚、modulesディレクトリについては前回の記事を参照してください。

そして、さくらのレンタルサーバーのコントロールパネルから、php.iniに下記を追記します。

;Calendar
extension_dir = /home/*****/modules
extension=calendar.so

ここに書いてあることはイレギュラーな方法だと思いますので、各自の自己責任で行ってください。
どのような結果になろうと当サイトは一切の責任を負いかねます。

コメント
planet-green.com

[開発/備忘録] さくらのレンタルサーバーにAPCをインストール



仕事でさくらのレンタルサーバーをビジネスプロという共用プランで借りているのですが、そこのPHPにAPCをインストールした時の備忘録。
基本的には下記のサイトを参考にさせていただきました。

 [PHP] さくらインターネット 共用鯖にAPCインストール
さくらのレンタルサーバにPHPの拡張モジュールAPCをインストールする

互換性の関係でPHPは5.3で動かしたかったのですが、APCの最新stable版である3.1.9はPHP5.3で動作しない模様。
PHP5.3で動作する最新stableは3.1.6になるのですが、これはさすがに古いのでbeta最新版の3.1.13を使うことにしました。

ついでに検証した動作結果。

× PHP5.3 + APC-3.1.9
○ PHP5.3 + APC-3.1.13
○ PHP5.4 + APC-3.1.13
× PHP5.3 + APC-3.1.8
○ PHP5.3 + APC-3.1.6

上記では○と×でしか区分けしてませんが、実際には、APCが認識されないだけだったり、PHP実行時にエラーメッセージが出たりと様々。
尚、サーバー側の環境は FreeBSD *****.sakura.ne.jp 9.1-RELEASE-p15 FreeBSD 9.1-RELEASE-p15 #1: Wed Jun 11 02:25:45 JST 2014     admin@*****.sakura.ne.jp:/usr/obj/home/pkg/src/sys/SAKURA17  amd64
( uname -a コマンドで確認したもの。)

インストール作業では、まずmodulesというディレクトリを作成し、PHP用モジュールのデフォルトの場所をそこに置き換えるようにしています。
phpinfo()で元のextension_dirの場所を確認して、中のファイルを新しいmodulesフォルダにリンク。
私の借りてるサーバーだと下記のようになりました。

% mkdir ~/modules/
% ln -s /usr/local/php/5.3/lib/php/extensions/no-debug-non-zts-20090626/* ~/modules/

続いてAPCのインストール。
ソースのURLは http://pecl.php.net/package/APC から取得する。

% cd ~/src
% wget http://pecl.php.net/get/APC-3.1.13.tgz
% tar xzvf APC-3.1.13.tgz
% cd APC-3.1.13
% /usr/local/php/5.3/bin/phpize
% ./configure --with-php-config=/usr/local/php/5.3/bin/php-config
% gmake

テストを実行し、問題なければOK。
うちのPHP5.3+APC3.1.13だと、Tests skippedが30もあるので気になるところではありますが・・・

gmake test

モジュール用ディレクトリにコピー。

% cp ~/src/APC-3.1.13/modules/apc.so ~/modules/

さくらのコントロールパネルからphp.iniの設定を追加。
メモリ使用量はお好みで。

;APC
extension_dir = /home/****/modules
extension=apc.so
apc.shm_size=48M
apc.max_file_size=4M
apc.write_lock = 1

ちなみにソースファイル一式にはapc.phpも含まれているので、パスワードを設定しWEBディレクトリに設置するとAPCの効き具合を確認できます。

最後になりますが、ここに書いてあることはイレギュラーな方法だと思いますので、各自の自己責任で行ってください。
どのような結果になろうと当サイトは一切の責任を負いかねます。

コメント
planet-green.com

NetBeans + OS X Mavericks + JDK-7u45での不具合



うちの環境だけかもしれませんが・・
OS X Mavericks + Java(JDK-7u45) + NetBeans7.4 の環境だとNetBeansが頻繁にフリーズします。

試行錯誤してみると、どうやらJDK-7u45(Java™ SE Development Kit 7, Update 45)が原因のようで、NetBeans7.3.1でもフリーズします。
ファイルの切り替え時や、検査機能を使おうとした時に高頻度で固まります。
OS X Lionでは7u45で問題なかったと記憶しているので、Mavericksとの相性問題かもしれません。

やむを得ず、こちらのページの“Uninstalling the JDK“を参考に7u45をアンインストールして、こちらからアップル製のJava SE 6をダウンロードしてインストールしなおしました。

AppleのJavaはバージョンが6ですがセキュリティパッチ対応済みなので、問題はないはず。
7u45のアンインストール時、私の場合は /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk も削除しました。

本当はNetBeansの7.4を使いたいのですが、インストール時・起動時に7u45が無いと動かないので残念です。

余談になりますが、OSをLionからMavericksに上書きアップデートした状態で使用していた時はNetBeansがデュアルディスプレイ環境で表示の不具合を起こしていたのですが、Mavericksをクリーンインストールしたら解消しました。
Mavericksはクリーンインストールがいいようです。

コメント