Imagemagickを使った複数画像の合成

Imagemagickを使って画像を合成する方法がややこしいので整理する。

 Layering -- IM v6 Examples

 

・compositeを使う方法(→JPEGには不向き)

  convert -size 100x100 xc:skyblue comp_resize.gif
  composite -geometry 40x40+5+10  balloon.gif comp_resize.gif comp_resize.gif
  composite -geometry      +35+30 medical.gif comp_resize.gif comp_resize.gif
  composite -geometry 24x24+62+50 present.gif comp_resize.gif comp_resize.gif
  composite -geometry 16x16+10+55 shading.gif comp_resize.gif comp_resize.gif

 

このように、同じファイルを上書きして開いて保存していくことはできる。

As all input images are read in by ImageMagick BEFORE the output image is opened, you can output to one of the input images. This allows you to work on the same image over and over, as shown above, without problems.

 

ただし、この方法はロスが多いのでJPEGには使うな、と注意書きがある。

 Do not do this with a lossy image format like "JPEG" as the format errors are accumulative, and the base image will quickly degrade.

 

・convert を使う方法 (→まあまあ)

  convert -size 100x100 xc:skyblue \
          balloon.gif  -geometry 40x40+5+10   -composite \
          medical.gif  -geometry      +35+30  -composite \
          present.gif  -geometry 24x24+62+50  -composite \
          shading.gif  -geometry 16x16+10+55  -composite \
          compose_geometry.gif

 

ここで、-geometry は、所定の位置に配置するだけではなく、直前の画像を-resizeすると書かれている。

Now the "-geometry" is is a very special operator that not only sets an overlay position for the next "-composite" operation, it will also "-resize" the last image (and only the last image) in the current image sequence.

ただし、これは便利だが使うな、と書かれている。

Note it is recommended that you avoid this 'resize' side-effect of of the "-geometry", even if it is convenient.

リサイズする場合は、以下のように書け、と書かれている。

  convert -size 100x100 xc:skyblue \
          \( balloon.gif -resize 40x40 \) -geometry +5+10   -composite \
          \( medical.gif               \) -geometry +35+30  -composite \
          \( present.gif -resize 24x24 \) -geometry +62+50  -composite \
          \( shading.gif -resize 16x16 \) -geometry +10+55  -composite \
          compose_resize.gif

 

・Drawを使う方法(→画像を変形させる場合は不向き)

 convert -size 100x100 xc:skyblue \
          -draw "image over  5,10 0,0 'balloon.gif'" \
          -draw "image over 35,30 0,0 'medical.gif'" \
          -draw "image over 62,50 0,0 'present.gif'" \
          -draw "image over 10,55 0,0 'shading.gif'" \
          drawn.gif

-drawを使うと、その過程で回転や拡大もできるが、その動きは”トリッキー”だ、と書かれている。→そんなこと書かれると使えない。

 

・Layerを使う方法(→おすすめ)

基本構文は以下。

  convert -size 100x100 xc:skyblue \
          -page +5+10  balloon.gif \
          -page +62+50 present.gif \
........... -layers flatten flatten_canvas.gif

ただし、画像を変形させた後、指定位置に配置しようと思い、以下のように書くとうまくいかなかった。

(うまくいかない例)

 ---------------------------------------

exec ("convert -size 500x1000 xc:white \
-page +10+10 \( aaa.jpg -resize 50x50 \) \
-page +50+100 \( bbb.jpg -resize 50x50 \) \
-layers flatten final.jpg");

 ---------------------------------------

上記の場合、「-page」で指定している位置が、[-resize]の影響を受けるようで、

位置が思う位置に来なかった。

 

結論としては、以下のように書くとうまくいった。

---------------------------------------------

convert -size 500x1000 xc:white \
\( aaa.jpg -resize 50x50 -repage +50+100 \) \
\( bbb.jpg -resize 100x100 -repage +100+200 \) \
-layers flatten final.jpg"

---------------------------------------------

 

 [-repage]は、使用時点でリストに入っている全ての画像に影響を及ぼす。

よって、特定の画像のみに適用させる場合は、括弧を使う。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Acrobat pro Xで、二重トンボのつけ方

1.ページボックス設定

  上 13mm

  下 13mm

  左 10mm

  右 10mm

2.トンボを追加

  センター&コーナートンボ設定

  線種:InDesignJ2

 

3.ページボックス設定

  上 10mm

  下 10mm

  左 13mm

  右 13mm

4.トンボを追加

  コーナートンボのみ設定

  線種:InDesignJ2

 

以上

wordpressのSQL文 忘備録

<1列のみ取得する場合>

global $wpdb;

$query = "SELECT user_login, display_name FROM $wpdb->users WHERE ID = '".$value."' AND user_status=0";


$user_info = $wpdb->get_row($query);

 

(値を取り出す時)

$user_login = $user_info->user_login

$display_name $user_info->display_name

 

 

<値を1つのみ取得する場合>

global $wpdb;

$query = "SELECT user_email FROM $wpdb->users WHERE ID = '".$userid."' AND user_status=0";
$user_email = $wpdb->get_var($query);

 

<複数行を取得する場合>

global $wpdb;

$query = SELECT user_id FROM wp1_bp_xprofile_data WHERE field_id = '89' AND value LIKE '%".$val."%' AND user_id != '".$userid."'";

$results = $wpdb->get_results($query);

foreach ($results as $value) {

    $user_id = $value->user_id

}

 

BuddyPress+bbpress で プロフィールページにリダイレクトされる件

BuddyPressとbbpressを入れていると、

ログイン後に再度ログインページなどにアクセスすると、

BuddyPressのプロフィールページにリダイレクトされることがあった。

 

調べると、

bbp_logged_in_redirect()

という関数が、デフォルトでプロフィールページにリダイレクトさせるようになっていることがわかった。

hookr.io

引数にリダイレクト先を指定できるようなので、指定することで解決した。

 

と思ったけど、解決してなかった。

どうも、theme-by-login という別のプラグインが原因のようだ。

調べるのも面倒くさいので、/profile に入ったらhomeにリダイレクトさせるようにした。

header.php

<?php 

$nowurl = get_the_permalink();
if (strstr($nowurl, '/profile')) {
wp_safe_redirect( 'http://www.soranowa.org/home' );
exit;
}

?>

 

 

 

BuddyPress 友達でない人にプライベートメッセージが送信できないようにする

BuddyPressの検証していてわかったことだが、友達になっていない人にも、プライベートメッセージ送ることができてしまうようだ。

 

そこで、友達でない人には、プライベートメッセージを送れなくする。

 

function.phpに以下を追記すればよい。

---------------------------

add_filter( 'bp_get_send_message_button', function( $array ) {
if ( friends_check_friendship( bp_loggedin_user_id(), bp_displayed_user_id() ) ) {
  return $array;
} else {
  return '';
}
} );

---------------------------

 

以上

 

ページとファイルの忘備録

(自分用のメモ)

・新規会員登録画面→register-form.php

 

・/archive/ → 大枠はpage.php、中は /template-parts/content-page.php

 

・掲示板一覧→archive-forum.php

 

・個別の掲示板のカテゴリー&

各カテゴリーのトピック一覧 →single-forum.php

 

・個別のトピック→single_topic.php & /bbpress/content-single-topic.php

(この中で色々なパーツを読みだしているので、詳しくはcontent-single-topic.phpの中を見ること)

 

 

BuddyPressに便利なプラグイン 2016年

BuddyPressを使って、ここひと月ほど、とあるサイトを構築してきたが、ようやく完成に近づいてきた。

最近、BuddyPressでこのブログに来る方が多いので、

最終的に私がBuddyPressと一緒に使って便利だと思うプラグインをまとめておく。

 

f:id:aquashine:20161127174032p:plain

f:id:aquashine:20161127174048p:plain

 

<bbPress>
掲示板機能をBuddyPressに追加したい場合に必要となります。
有名なので私が説明するまでもないでしょう。

 

<BP Avatar Suggestions>
事前にアバターを登録しておけば、
ユーザーがそのアバターを選択できるようになります。
ユーザーのアバターのみでなく、グループのアバターも登録できます。

 

<BP Profile Search>
各メンバーの検索機能が大幅に強化されます。
検索の設定も管理画面から簡単にでき、よく出来たプラグインです。

 

<BuddyPress Activity Plus>
アクティビティから、画像や動画を投稿できるようになります。
アイコンもデフォルトでカワイイのが入っています。

 

<BuddyPress Avatar Bubble>
各メンバーのアイコンにカーソルを合わせると、
その人のプロフィールがポップアップで確認できるようになります。
表示させるプロフィールは管理画面で設定できます。

 

<Theme My Login>
ログインページをカスタマイズするために入れました。
ログイン時やパスワードの再発行時に送信されるメールの文面のカスタマイズが
簡単にできるようになります。

 

<WP Better Emails>
BuddyPressから送信されるメールのテンプレートが気に入らない場合、
試すといいです。
ヘッダーとフッターを予め設定しておけば、後は本文が中に挿入されて、
送信されるようになります。

 

以上、ご参考まで。

BuddyPressのメールのテンプレートについて

BuddyPressでは、事あるごとに利用者にメールが飛んで便利だが、

どうも体裁が悪い。

どこかにメールのテンプレートファイルがあるのかと思ったが、どうもそのようなものはないようだ。

そこで私は、「WP Better Email」というプラグインをまず入れた。

ja.wordpress.org

これをいれると、

https://s.w.org/plugins/wp-better-emails/screenshot-1.png?r=1541254

のようなちょっとカッコいいメールが送れるようになり、管理画面からHTMLタグで修正も容易である。

 

しかし、ここでハマった。

送られてくるメールの本文が英語のままであり、poファイルで翻訳しても一向に反映されない。

前の記事のようにPOTファイルが悪いのかと思ってPOTファイルを修正したり、最終的に、プラグインファイルを直接翻訳しても、一向にメールでは英語のままである。

調べたところ、DBの『wp_posts』というテーブルに、メールのタイトルと本文が記録されてあり、これを「WP Better Email」が読みだして、メール送信していることがわかった。

よって、「WP Better Email」を使って翻訳が反映されない方は、DBの『wp_posts』というテーブルを修正する、ということを覚えておかれた方がいい。

 

以上

 

Buddypress で友達申請の通知、グループへの招待の通知、プライベートメッセージの通知をサイトに出す方法

f:id:aquashine:20161126104513p:plain

 

BuddyPressを使っている方は、上記のような通知をサイト上に出したいはず。

プラグインがあればよかったがなかった。(標準であってもいいと思うのになぁ・・・)

 

BuddyPressの関数を調べたところ、幸い、豊富な関数が用意されていたので、

簡単に実現できた。

 

以下のソースを、表示させたいテンプレートファイルに貼ればいい。

 

<プライベートメッセージの件数>

<?php if (bp_get_total_unread_messages_count()>0) : ?>
<a href="/member/<?php echo bp_loggedin_user_username();?>/messages/">あなた宛ての未読のプライベートメッセージが、<?php echo bp_get_total_unread_messages_count();?>件あります。</a><br>
<?php endif; ?>

 

<アクティビティのメンション数> 

※下ではメンションのことを「あなた宛てのつぶやき」と表現している

<?php if (bp_get_total_mention_count_for_user( bp_loggedin_user_id() ) >0): ?>
あなた宛ての新規のつぶやきが、<a href="/member/<?php echo bp_loggedin_user_username();?>/activity/mentions/"><?php echo bp_get_total_mention_count_for_user( bp_loggedin_user_id() );?>件</a>あります。<br>
<?php endif ?>

 

<グループへの招待状>

<?php if (groups_get_invite_count_for_user( bp_loggedin_user_id() ) > 0 ) :?>
<a href="/member/<?php echo bp_loggedin_user_username();?>/groups/invites/">グループへの招待状が<?php echo groups_get_invite_count_for_user( bp_loggedin_user_id() );?>件届いています。</a><br>
<?php endif; ?>

 

<友達申請>
<?php if (bp_friend_get_total_requests_count() > 0 ) :?>
<a href="/member/<?php echo bp_loggedin_user_username();?>/friends/requests/">友達申請が<?php echo (bp_friend_get_total_requests_count());?>件届いています。</a>
<?php endif; ?>

 

※アクティビティへのコメント数は、標準では用意されていないので、結構大変。

以下の記事を読めば1,2時間くらいでできます。

fushigi.hatenadiary.com

言語ファイル(.po, .mo)の更新方法

BuddypressやBBpressでpoファイルが古いため、翻訳が反映されない場合がある。

その場合、以下の手順でpoファイルを最新に更新する。

 

<言語ファイル(.po, .mo)の更新方法>

1.最新版のプラグインをダウンロードする

2.xxxx.pot ファイルがある場所に、今使っている.poファイルをコピーする

(buddypress(ver.2.7.2)の場合、buddypress.2.7.2\buddypressの直下)

3.poeditを立ち上げ、2のpoファイルを開く

4.「カタログ」ー「POTファイルを元に更新します」を実行

5.これで最新版になるので、足りない部分を翻訳する

6.保存すると2の場所に、XXX.moファイルができるので、サーバーの

/wp-content/languages/plugins 等、プラグインのmoファイルがある場所にアップする

 

以上

 

(2016.11.27 追記)

BuddypressのVer.2.7.2でわかったのだが、例えば、「or press esc to cancel.」という翻訳が、poファイルを開いても見つからなかった。

 どうも、poファイルの元になっているPOTファイル(buddypress.2.7.2\buddypress\buddypress.pot)に、いくつかの”抜け”があるようだ。

 poファイルに見つからない場合は、buddypress.potをエディタで開いて、

他と同じように、

-------------------------------

#: activity/entry.php:143
msgctxt ""
msgid "or press esc to cancel."
msgstr ""

-------------------------------

のように追記した後、再度、4の手順「4.「カタログ」ー「POTファイルを元に更新します」を実行」をすると、poeditに表示されるようになった。

 以上

 

 

 

Buddypress で「activity」タブの時、サブメニューを非表示にする方法

f:id:aquashine:20161116102724p:plain

 

/wp-content/themes/自分のテーマ/buddypress/members/single/activity.php

に以下を追加する。

(※テンプレートファイルをpluginディレクトリから移動させていない場合は、

/wp-content/plugins/buddypress/bp-templates/bp-legacy/buddypress/memberssingle/activity.php

 

--------------------------

<?php
$bp_displayed_user_id = bp_displayed_user_id();/*表示されているメンバーのID*/
$bp_loggedin_user_id = bp_loggedin_user_id();/*ログインしているメンバーのID*/
if ($bp_displayed_user_id != $bp_loggedin_user_id):
?>
<script type='text/javascript'>
jq(function(){
/*活動履歴タブの場合、他人のサブナビは非表示にする*/
if (jq.cookie('bp-activity-scope') == 'all'){
jq('#subnav').css('display', 'none');
}
})
</script>
<?php endif; ?>

--------------------------

 

 

以上

wordpressのデバッグの方法

$log_file = dirname(__FILE__) . '/debug.log';
$fp = fopen( $log_file , 'a' );
fwrite( $fp , print_r($hoge) );
fclose( $fp );

 

BuddyPressにアクティビティへのコメントの新着コメント数を出す方法

<完成画像>

f:id:aquashine:20161114112846j:plain

 

<考え方>

1.コメントがあるとDBのusermetaにコメントがあったレコードを追加する

2.コメントをみると、そのメタデータを削除する

 

<方法>

まずは、コメントが入った際に、メタデータに記録する。

 

/wp-content/plugins/buddypress/bp-activity/bp-activity-functions.php に、

function bp_update_user_meta( )があるので、DBに書き込むには、

この関数を使えばよさそう。

 

コメントが入ったときに実行されるフィルターを探すと、以下が見つかった。

 bp_activity_secondary_item_id_before_save

 

(※フィルターを探す方法はよくわからなかた。

以下のサイトでとにかく探しまくった。

http://hookr.io/plugins/buddypress/2.6.2/filters/#index=a

 

<プログラム>

以下の関数をテーマ内のfunction.phpに書く。

------------------

/*つぶやきへのコメントが入った際に、usermetaに書き込む*/

/* bp_activity_secondary_item_id_before_save()が実行される際、comment_record()を実行する */

add_filter('bp_activity_secondary_item_id_before_save', 'comment_record', 10, 1);

function comment_record ($array) {

//$arrayは、'bp_activity_secondary_item_id_before_save'から「secondary_item_id」が渡される


 //「secondary_item_id」から元ツイートのuser_idを出す

global $wpdb;
$results = $wpdb->get_results("SELECT id, user_id, item_id FROM wp1_bp_activity WHERE id = '".$array."' ORDER BY id DESC LIMIT 1" );
foreach ($results as $value) {
    $user_id = $value->user_id;
    $id = $value->id; //直接コメントしたコメントのid
    $item_id = $value->item_id;//大元のid
    if ($item_id==0) { //大元のスレッドのitemp_idは0になっている
        $item_id = $id;
    }
}

$new_comment_count = (int) bp_get_user_meta( $user_id, 'bp_new_comment_count', true );
$new_comments = bp_get_user_meta( $user_id, 'bp_new_comments', true );

// bp_new_commentsには以下のように記録する
//Array(
// [$id] => array(コメント数, 大元のid)
// [$id] => array(コメント数, 大元のid)
// ・・・・
//)

// Make sure new mentions is an array.
if ( empty( $new_comments ) ) {
     $new_comments = array();
}

if (array_key_exists($id, $new_comments)) { /*その$activity_idが既に存在している場合はインクリメント*/

     $new_comment_count = $new_comments[$id][0] + 1;
     $new_comments[$id] = array($new_comment_count, $item_id);
} else {
     $new_comments[$id] = array(1, $item_id);
}

//usermetaに書き込む関数

bp_update_user_meta( $user_id, 'bp_new_comments', $new_comments);

return $array;
}

------------------

 

上記をfunctionに書くと、DBのusermetaに

 Array(
   [$id] => array(コメント数, 大元のid)
   [$id] => array(コメント数, 大元のid)
 ・・・・
)

の形で書き込まれる。

 

<トップページへの表示>

次に、トップページへ表示させる。

 まず、function.phpに以下を書く。

-------------------------------

/*トップページのお知らせにつぶやきへのコメント数を表示させる*/

function comment_view () {

    global $wpdb;

    $user_id = bp_loggedin_user_id();

    $comment = bp_get_user_meta( $user_id, 'bp_new_comments', true );

    return $comment;

}

-------------------------------

 

 

そして、トップページ(または別のページ)のテンプレートファイルの表示させたい部分に以下を書く。

-------------------------------

 <?php
    $comment = comment_view();
    foreach ($comment as $key => $value){
        // $commentの構造=array(コメント数, 大元のスレッドid)
        echo "<a href='/activity/p/".$value[1]."?del_com=1&id=".$key."'>あなたのつぶやき(id:".$key.")への新規のコメントが、".$value[0]."件あります。</a><br>";
    }
?>

-------------------------------

 

<お知らせを押すと、お知らせを消す>

function.phpに以下を書く。

------------------------------------

/*トップページのお知らせにつぶやきへのコメント数を消す*/

function comment_del($id) {
    $user_id = bp_loggedin_user_id();
    $new_comments = bp_get_user_meta( $user_id, 'bp_new_comments', true );

    unset( $new_comments[$id] );

    //更新後のデータでusermetaを登録
    bp_update_user_meta( $user_id, 'bp_new_comments', $new_comments);
}

------------------------------------

 

上述のように、トップページに書くお知らせのリンク先URLを以下のようにする。

------------------------------------

<?php

foreach ($comment as $key => $value){

    echo "<a href='/activity/p/".$value[1]."?del_com=1&id=".$key."'>あなたのつぶやき(id:".$key.")への新規のコメントが、".$value[0]."件あります。</a><br>";

}

?>

 

------------------------------------

 

 

リンクを押したときに開くテンプレートファイルに以下を書く。

(私の場合、/wp-content/themes/twentysixteen/template-parts/content-page.php

------------------------------------

<?php
if (isset($_GET['del_com']) && isset($_GET['id']) && $_GET['del_com']==1){
    $id = htmlspecialchars($_GET['id'], ENT_QUOTES);
    comment_del($id);
}
?>

------------------------------------

 

以上。

めでたしめでたし(笑 

 

 

 

 

BuddyPressで、マイページのナビで、他人のアクティビティを見えなくする方法

<結論>

/wp-content/plugins/buddypress/bp-activity/classes/class-bp-activity-component.php

$main_navに以下のように追加。

 

 

$main_nav = array(

'name' => _x( 'Activity', 'Profile activity screen nav', 'buddypress' ), 
'slug' => $slug,
'position' => 10,
'screen_function' => 'bp_activity_screen_my_activity',
'default_subnav_slug' => 'just-me',
'item_css_id' => $this->id,
'show_for_displayed_user' => '' /*自分にしか見れないようにするにはこれを追加する*/
);

 

<以下、思考過程の忘備録>

bp_get_displayed_user_nav()でナビ部を作成

foreach ( $bp->members->nav->get_primary() as $user_nav_item ) {で作成

プロパティ:show_for_displayed_userで、表示/非表示を決定

'show_for_displayed_user' => $r['show_for_displayed_user'],

$r = wp_parse_args( $args, $defaults );

//wp_parse_args は、引数の配列とデフォルト値の配列を結合するための汎用の関数です。

($rの一例)

Array ( [name] => プロフィール
[slug] => profile
[item_css_id] => xprofile
[show_for_displayed_user] => 1
[site_admin_only] =>
[position] => 20
[screen_function] => xprofile_screen_display_profile
[default_subnav_slug] => public )

Array ( [name] => トップ
[slug] => activity
[item_css_id] => activity
[show_for_displayed_user] => 1
[site_admin_only] =>
[position] => 10
[screen_function] => bp_activity_screen_my_activity
[default_subnav_slug] => just-me )

Array ( [name] => 友達 0
[slug] => friends
[item_css_id] => friends
[show_for_displayed_user] => 1
[site_admin_only] =>
[position] => 60
[screen_function] => friends_screen_my_friends
[default_subnav_slug] => my-friends )

Array ( [name] => グループ 1
[slug] => groups
[item_css_id] => groups
[show_for_displayed_user] => 1
[site_admin_only] =>
[position] => 70
[screen_function] => groups_screen_my_groups
[default_subnav_slug] => my-groups )

Array ( [name] => メッセージ
[slug] => messages
[item_css_id] => messages
[show_for_displayed_user] =>
[site_admin_only] =>
[position] => 50
[screen_function] => messages_screen_inbox
[default_subnav_slug] => inbox )

Array ( [name] => 通知
[slug] => notifications
[item_css_id] => notifications
[show_for_displayed_user] =>
[site_admin_only] =>
[position] => 30
[screen_function] => bp_notifications_screen_unread
[default_subnav_slug] => unread )

Array ( [name] => 設定
[slug] => settings
[item_css_id] =>
[show_for_displayed_user] =>
[site_admin_only] =>
[position] => 100
[screen_function] => bp_settings_screen_general
[default_subnav_slug] => general )

Array ( [name] => フォーラム
[slug] => forums
[item_css_id] => forums
[show_for_displayed_user] => 1
[site_admin_only] =>
[position] => 80
[screen_function] => bbp_member_forums_screen_topics
[default_subnav_slug] => topics )