Movable Typeで特定の拡張子のファイルをアップロードする方法
Movable Typeのカスタムフィールドを使って、例えば、「.3g2」という3GPP2ファイルフォーマットのファイルをアップロードしようとすると、次のようなエラーになります。

理由は、Movable Typeでは「.3g2」ファイルがアップロード可能なアイテムとして登録されていないためと思われます。
本エントリーでは、このような未登録のアイテムをMTでアップロードできるようにするカスタマイズを紹介します。
1.デフォルトでアップロード可能なフォーマット
基本情報として、Movable Typeのデフォルト状態でアップロード可能なファイルフォーマット(拡張子)は次のとおりです。
- 画像:gif/jpe/jpeg/png/bmp/tif/tiff/ico
- 音声:mp3/ogg/aif/aiff/wav/wma/aac/flac/m4a
- 動画:mov/avi/3gp/asf/mp4/qt/wmv/asx/mpg/flv/mkv/ogm
2.未登録フォーマットのファイルをアップロードする
未登録フォーマットのファイルをアップロードできるようにするには、環境変数AssetFileTypesをmt-config.cgiの末尾に追加します。
例えば、冒頭の「.3g2」という拡張子のファイルを追加するには、次の1行を追加します。
AssetFileTypes MT::Asset::Video=3g2
複数のフォーマットを追加する場合は、フォーマットをカンマ区切りで記述します。
AssetFileTypes MT::Asset::Video=3g2,m2v
画像フォーマットを追加する場合は次のフォーマットになります。「xxx」の部分に追加したい拡張子を記述します。
AssetFileTypes MT::Asset::Image=xxx
音声フォーマットを追加する場合は次のフォーマットになります。「xxx」の部分に追加したい拡張子を記述します。
AssetFileTypes MT::Asset::Audio=xxx
特定のアイテムのみをブログ記事に表示する
ブログ記事に特定のタグをつけたアイテムのみを表示するカスタマイズです。下のサンプルではブログ記事に3つのアイテムを追加していますが、変更後はアイテムを削除することなく、表示する画像を1つに絞り込んでいます。
変更前

変更後

特定のアイテムを抽出するには、アイテムにプライベートタグを設定し、そのタグを利用します。

ブログ記事に関連づけたアイテムから特定のアイテムを抽出するには、ブログ記事テンプレートに次のようなサブテンプレートを設定します。この例ではアイテムの「@foo」というプライベートタグのアイテムを抽出します。
<mt:EntryAssets>
<mt:AssetTags include_private="1">
<mt:if tag="TagName" eq="@foo">
<img src="<mt:AssetThumbnailURL width="70" square="1" />" />
</mt:if>
</mt:AssetTags>
</mt:EntryAssets>
すべてのアイテムから特定のアイテムを抽出するには、ブログ記事テンプレートに次のようなサブテンプレートを設定します。
<mt:Assets>
<mt:AssetTags include_private="1">
<mt:if tag="TagName" eq="@foo">
<mt:AssetURL />
</mt:if>
</mt:AssetTags>
</mt:Assets>
Pixenateプラグインで画像をリサイズできない不具合の対処
Movable Typeにアップロードしたアイテム画像を編集できる「Pixenateプラグイン」を以前紹介しましたが、riatwさんから「サイズ変更がアイテムに反映されません」というご連絡を頂きましたので、プラグインの対処方法を紹介します。
この問題はMovable Type 4.xでも発生しますが、ここでの対象バージョンはMovable Type 5.0xのみです。
1.問題点
編集画面を開きます。
「ZOOM OUT」をクリックして画面を縮小します。このサンプルの編集前後のサイズは、
- 編集前:640×480px
- 編集後:320×240px
です。

この状態で「Save and Quit」をクリックしても、リサイズした結果がアイテムに反映されません。再度編集すると元のサイズで表示されます。要するに編集の実績がまったくありません。

リサイズ以外でも次のように切り抜いた場合、
変更後のサイズがアイテムに反映されないので、アイテム編集画面の画像が元サイズ(=640×480px)で表示されてしまいます。Pixenateによる再編集時は元画像を原寸で表示するので問題ありませんが、実用レベルではありません。

2.原因と対処案
原因はPixenateのAPIでリサイズ後のサイズ情報を取得するAPIがなく、そもそもアイテム更新時にサイズ情報が保存されていません。アイテムはmt_asset_metaテーブルに「image_height」「image_width」というデータを保持していますが、そのデータが書き換えられていません。
また、切り抜きや回転を行わないリサイズのみの場合は、サイズ情報だけでなく、画像自体に何も変更が加えられていません。
ということでリサイズが行われた場合、編集前のサイズと編集後のサイズを比較し、変更があった場合にmt_asset_metaテーブルの書き換えと、画像データの更新を行うようにしてみました。
以下は備忘録ですので、対処を行いたい方は読み飛ばして3項に進んでください。
Pixenateプラグインでリサイズ以外の編集が行われた場合、PXN8.getUncompressedImage()というAPIでURLが取得できますが、リサイズのみの場合はそのAPIではURLが取得できず、その場合、保存のためのプラグインメソッドpixenate_save_changes()が起動されません。よってまずはここを起動するように変更します。
また、元画像のサイズはPXN8.getImageSize()で取得できますが、編集後のサイズを取得するAPIがありません。よって、編集後のサイズは画像編集画面に表示されているimg要素のwidth属性とheight属性から取得し、PXN8.getImageSize()で取得したサイズと異なる場合、プラグインメソッドpixenate_save_changes()を起動し、サイズデータはその引数として渡します。他の編集が行われておらずかつサイズ変更がない、つまり編集が何も行われていない場合のみプラグインメソッドpixenate_save_changes()を起動せず終了します。
起動されたpixenate_save_changes()では、リサイズ以外の編集が行われた場合はURLを利用してLWP::Simple::getstoreで一旦アイテムを保存します(既存処理。画像はここで更新されます)。その後、引数で渡されたサイズと、DBに保持されているアイテムのサイズを判定し、異なる場合はアイテムのサイズ情報更新と、リサイズのみの編集を考慮し、MT::ImageとMT::FileMgrを使って画像の更新を実施します。
3.対処1(テンプレートファイルの差し替え)
mt-plugin-pixenate-tmplのページからアーカイブをダウンロードし、アーカイブを展開した中にある、
- alt-tmpl/cms/edit_asset.tmpl
- alt-tmpl/cms/include/asset_table.tmpl
- plugins/Pixenate/tmpl/Editor.tmpl
を、元のプラグインの同じディレクトリにあるファイルと差し替えてください。今回の修正で差し替えが必要なファイルはEditor.tmplのみなので、すでにMT5.0で利用されている場合はその1ファイルのみを差し替えてください。
4.対処2(プラグインファイルの修正)
Pixenate.plを任意のエディタで開き、以下のsave_changes_mode()の内容を修正してください。
変更前(赤色を削除)
sub save_changes_mode {
my $app = shift;
my $imageId = $app->{query}->param('id');
my $filepath = get_filepath($imageId);
my $changedImageURL = $app->{query}->param('changedImageURL');
my $rc = LWP::Simple::getstore($changedImageURL,$filepath);
return "{filepath: \"$filepath\", rc: $rc}";
}
変更後(青色を追加)
sub save_changes_mode {
my $app = shift;
my $imageId = $app->{query}->param('id');
my $filepath = get_filepath($imageId);
my $changedImageURL = $app->{query}->param('changedImageURL');
my $rc = LWP::Simple::getstore($changedImageURL,$filepath);
my $asset = MT::Asset::Image->load($imageId);
my $width = $app->{query}->param('width');
my $height = $app->{query}->param('height');
require MT::Image;
require MT::FileMgr;
my $fmgr ||= $app->blog ? $app->blog->file_mgr : MT::FileMgr->new('Local');
my $image = new MT::Image( Filename => $asset->file_path );
my ($data, $w, $h) = $image->scale( Height => $height, Width => $width )
or return $asset->error(MT->translate( "Error scaling image: [_1]", $image->errstr ) );
(my $tmp = $asset->file_path) =~ s!(.*)/[^/]+$!$1!;
my $path = File::Spec->catfile( $tmp, $asset->file_name );
$fmgr->put_data( $data, $path, 'upload' )
or return $asset->error(
MT->translate( "Error creating file: [_1]", $fmgr->errstr ) );
$asset->meta('image_width', $width);
$asset->meta('image_height', $height);
$asset->save;
}
修正後、Pixenateでのサイズ変更が反映されるようになります。

画像編集画面でもサイズが反映されます。

Movable Typeのブログ記事で未使用のアイテム一覧を表示する(本文未挿入版)
Movable Typeのテンプレートを使って、ブログ記事で未使用のアイテムを表示するTipsです。この記事は「Movable Typeのブログ記事で未使用のアイテム一覧を表示する」に対し、「記事のアイテムとして登録されていて、本文の埋め込みコードを削除したものの一覧は表示できないでしょうか」という質問がありましたので、その回答です。
1.サンプル
あるブログに次のように4つのアイテム(画像)を登録しているものとします。

このアイテムのうち、2つのアイテムをブログ記事で使用しています。

が、そのうちひとつしか本文に埋め込んでいません。

この状態で、2項に示すサブテンプレートを利用すれば、記事本文に埋め込まれていないアイテム一覧をリストすることができます。
![]()
2.サブテンプレート
利用するサブテンプレートは次のようになります。
<mt:Entries lastn="0">
<mt:EntryAssets type="image">
<mt:AssetID setvar="key" />
<mt:AssetLabel setvar="value" />
<mt:SetVar name="asset_list{$key}" value="$value" />
</mt:EntryAssets>
</mt:Entries>
<mt:Entries lastn="0">
<mt:EntryAssets type="image">
<mt:AssetURL setvar="asset_url" />
<mt:AssetID setvar="asset_id" />
<mt:if tag="EntryBody" like="$asset_url">
<mt:GetVar name="delete(asset_list)" key="$asset_id" setvar="tmp" />
</mt:if>
</mt:EntryAssets>
</mt:Entries>
<mt:loop name="asset_list">
<mt:if name="__first__">
<ul>
</mt:if>
<li><mt:GetVar name="__value__" /></li>
<mt:if name="__last__">
</ul>
</mt:if>
</mt:loop>
以下、サブテンプレートの解説です。
まず、最初のMTEntriesタグで、ブログ記事で使っている画像のアイテム一覧のハッシュを生成します。MTEntriesタグブロック内部で、アイテム情報をハッシュ変数asset_listに保存します。ハッシュのキーがアイテムID、ハッシュの値がアイテムの名前になります。
<mt:Entries lastn="0">
<mt:EntryAssets type="image">
<mt:AssetID setvar="key" />
<mt:AssetLabel setvar="value" />
<mt:SetVar name="asset_list{$key}" value="$value" />
</mt:EntryAssets>
</mt:Entries>
次のMTEntriesタグで、ブログ記事本文で使っているアイテムを、先程作成したハッシュから削除します。ブログ記事本文でアイテムが使われていることの判断は、MTIfタグにtagモディファイアを与え、MTEntryBodyタグにアイテムのURLが含まれているかどうかでチェックしています。ハッシュから削除するには、MTGetVarタグとnameモディファイアにdelete関数を使って対象のハッシュ変数を指定し、keyモディファイアに削除対象のハッシュキーを設定しますが、deleteした時点で削除対象のハッシュの値が出力されるので、setvarモディファイアで変数tmpにおいやり、画面に表示しないようにします。
<mt:Entries lastn="0">
<mt:EntryAssets type="image">
<mt:AssetURL setvar="asset_url" />
<mt:AssetID setvar="asset_id" />
<mt:if tag="EntryBody" like="$asset_url">
<mt:GetVar name="delete(asset_list)" key="$asset_id" setvar="tmp" />
</mt:if>
</mt:EntryAssets>
</mt:Entries>
最後のMTLoopタグで、ハッシュの一覧を出力します。ここで出力されたアイテムがブログ記事で使われなかったものになります。この部分は前のエントリーと変わっていません。
<mt:loop name="asset_list">
<mt:if name="__first__">
<ul>
</mt:if>
<li><mt:GetVar name="__value__" /></li>
<mt:if name="__last__">
</ul>
</mt:if>
</mt:loop>
Movable Typeの管理サイトでFTPが使えないときにファイルをアップロードする裏ワザ
Movable Typeの管理サイトでFTPが使えないときでもファイルがアップロードできる裏ワザです。
たとえば、緊急でプラグインをインストールしたいけど何らかの事情でFTPが使えないとか、FTPの情報が手元にないといった場合があるかもしれません。そのような場合、任意のウェブサイトまたはブログのアイテム機能を利用してファイルをアップロードします。
以下、手順の一例を示します。
1.ブログまたはウェブサイトのサイトパスを変更する
ブログまたはウェブサイトのサイトパスを、ファイルをアップロードしたいパス(またはそれより上位のパス)に一時的に変更します。プラグインファイルをアップロードしたい場合は、アプリケーションディレクトリなど、pluginsディレクトリより上位のパスを指定します。
変更前

変更後(アプリケーションディレクトリを指定)

なお次のように、ウェブサイトやブログのサイトパスがアプリケーションディレクトリより上位のパスになっているのであれば、サイトパスは変更する必要はありません。
ブログのサイトパス

アプリケーションディレクトリ

注意点は、サイトパスを変更しているときに、記事やコメント投稿が行われないことが前提になります。サイトパス変更中に記事やコメント投稿が行われると、変更したサイトパスを基準にファイルが生成されてしまうためです。
どうしてもサイトパスが変更できない場合、新たにブログまたはウェブサイトを作成し、そのサイトパスを利用するという手もあります。
2.ファイルをアップロードする
サイトパス変更後、ファイルをアップロードします。プラグイン用のディレクトリなどは直接入力します。通常のアイテムのアップロードと同様、ファイルは1つずつしかアップロードできません。
次の例は、サイトパスをアプリケーションディレクトリに変更し、TwitCommentプラグインのconfig.yamlをアップロードする場合の指定です。

アップロード後のアイテム一覧

必要なファイルのアップロードが完了したら、サイトパスを元に戻します。あるいは一時的に作成したブログまたはウェブサイトを削除します。
3.アップロードしたファイルをアイテムの管理対象外にする
アップロードしたファイルをアイテムの管理対象外にしたい場合、サイトパスを元に戻せば、アイテムに登録されたファイルは参照できなくなるので、該当のアイテムを削除すれば、アップロードしたファイルを残したままアイテムの管理対象外にすることができます。
サイトパスを変更した後のアイテム一覧

サイトパスを変更していない場合、アップロードファイルはアイテムと紐づいたままになっているので、以下のいずれかの方法で対処します。1つめの方法は事後にFTPが可能になることが前提です。
- アップロードしたファイル名を一時的に変更してアイテムを削除する
- サイトパスを一時的に変更してアイテムを削除する
Movable Typeのブログ記事で未使用のアイテム一覧を表示する
Movable Typeのテンプレートを使って、ブログ記事で未使用のアイテムを表示するTipsです。
1.サンプル
あるブログに次のように4つのアイテム(画像)を登録しているものとします。

このアイテムのうち、2つのアイテムをブログ記事で使用しています。

この状態で、2項に示すサブテンプレートを利用すれば、ブログ記事で使っていないアイテム一覧をリストすることができます。

2.サブテンプレート
利用するサブテンプレートは次のようになります。
<mt:Assets type="image">
<mt:AssetID setvar="key" />
<mt:AssetLabel setvar="value" />
<mt:SetVar name="asset_list{$key}" value="$value" />
</mt:Assets>
<mt:Entries>
<mt:EntryAssets type="image">
<mt:AssetID setvar="asset_id" />
<mt:GetVar name="delete(asset_list)" key="$asset_id" setvar="tmp" />
</mt:EntryAssets>
</mt:Entries>
<mt:loop name="asset_list">
<mt:if name="__first__">
<ul>
</mt:if>
<li><mt:GetVar name="__value__" /></li>
<mt:if name="__last__">
</ul>
</mt:if>
</mt:loop>
以下、サブテンプレートの解説です。
まず、最初のMTAssetsタグに「type="image"」を設定し、画像のアイテム一覧のハッシュを生成します。MTAssetsタグブロック内部で、アイテム情報をハッシュ変数asset_listに保存します。ハッシュのキーがアイテムID、ハッシュの値がアイテムの名前になります。
<mt:Assets type="image">
<mt:AssetID setvar="key" />
<mt:AssetLabel setvar="value" />
<mt:SetVar name="asset_list{$key}" value="$value" />
</mt:Assets>
次のMTEntriesタグで、ブログ記事で使っているアイテムを、先程作成したハッシュから削除します。ハッシュから削除するには、MTGetVarタグとnameモディファイアにdelete関数を使って対象のハッシュ変数を指定し、keyモディファイアに削除対象のハッシュキーを設定しますが、deleteした時点で削除対象のハッシュの値が出力されるので、setvarモディファイアで変数tmpにおいやり、画面に表示しないようにします。
<mt:Entries>
<mt:EntryAssets type="image">
<mt:AssetID setvar="asset_id" />
<mt:GetVar name="delete(asset_list)" key="$asset_id" setvar="tmp" />
</mt:EntryAssets>
</mt:Entries>
最後のMTLoopタグで、ハッシュの一覧を出力します。ここで出力されたアイテムがブログ記事で使われなかったものになります。
<mt:loop name="asset_list">
<mt:if name="__first__">
<ul>
</mt:if>
<li><mt:GetVar name="__value__" /></li>
<mt:if name="__last__">
</ul>
</mt:if>
</mt:loop>
もっと簡単に振り分ける方法があると思いますし、本来は管理画面で実現すべきなのですが、とりあえず1アイデアとして展開しておきます。
サムネイルリストから不要な右マージンを除去する
Movable Typeでサムネイルリストを横並びに表示する際、(X)HTMLマークアップに順不同リストを使って、次のようにサムネイルとサムネイルの間に余白を設定することがあると思います。
![]()
余白を設定する方法のひとつとして、スタイルシートのliセレクタに右マージンの設定を行います。
ul {
list-style: none;
}
li {
margin-right: 10px;
float: left;
}
ただし、この設定だけでは、一番最後のサムネイルの右側にもマージンが設定されてしまいます。
ということで、本エントリーでは一番最後のサムネイルの右側にマージンを設定しないカスタマイズを紹介します。CSSやjQueryでも実現可能かもしれませんが、テンプレートタグを駆使します。
サムネイルを5つ並べるサブテンプレートは、ブログ記事に追加したサムネイルを5つ並べるケースを想定しています。
<mt:SetVar name="counter" value="1" />
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<mt:EntryAssets type="image">
<mt:if name="counter" le="5">
<li><a href="<mt:AssetURL />"><img src="<mt:AssetThumbnailURL width="75" square="1" />" alt="<mt:AssetLabel />" title="<mt:AssetLabel />" /></a></li>
<mt:SetVar name="counter" op="++" />
</mt:if>
</mt:EntryAssets>
<mt:EntriesFooter>
<ul>
</mt:EntriesFooter
</mt:Entries>
修正方法は簡単で、まずサブテンプレートのli要素部分に、青色で示すMTIfタグを追加します。
<mt:SetVar name="counter" value="1" />
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<mt:EntryAssets type="image">
<mt:if name="counter" le="5">
<li<mt:if name="counter" eq="5"> class="end"</mt:if>><a href="<mt:AssetURL />"><img src="<mt:AssetThumbnailURL width="75" square="1" />" alt="<mt:AssetLabel />" title="<mt:AssetLabel />" /></a></li>
<mt:SetVar name="counter" op="++" />
</mt:if>
</mt:EntryAssets>
<mt:EntriesFooter>
<ul>
</mt:EntriesFooter
</mt:Entries>
そして、スタイルシートに次のセレクタを追加します。
li.end {
margin-right: 0;
}
全体のソースコードは次のようになります。
<html>
<head>
<style type="text/css">
ul {
list-style: none;
}
li {
margin-right: 10px;
float: left;
}
li.end {
margin-right: 0;
}
</style>
</head>
<body>
<mt:SetVar name="counter" value="1" />
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<mt:EntryAssets type="image">
<mt:if name="counter" le="5">
<li<mt:if name="counter" eq="5"> class="end"</mt:if>><a href="<mt:AssetURL />"><img src="<mt:AssetThumbnailURL width="75" square="1" />" alt="<mt:AssetLabel />" title="<mt:AssetLabel />" /></a></li>
<mt:SetVar name="counter" op="++" />
</mt:if>
</mt:EntryAssets>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
</body>
</html>
Movable Type 5 でスライドショーを実現する(その2:応用)
「Movable Type 4.3 でスライドショーを実現する(その1:基本動作)」で紹介したスライドショーは、メインページや、ブログ記事リストなど、1ページに複数記事がある場合に正常に動作しません。
本エントリーではその対処方法を紹介します。以下のサンプルでは、2つの記事にスライドショーを設定しており、それぞれが独立して動作します。
対処方法は、メインページやブログ記事リストのMTEntiesタグの中に、以下の青色部分を追加します。やっつけ仕事なのでエレガントなコードでありません。予めご了承ください。
<mt:Entries>
<$mt:Include module="ブログ記事の概要"$>
<script type="text/javascript">
//<![CDATA[
var entryAssets<mt:EntryID /> = new Array(<mt:EntryAssets>'<mt:AssetThumbnailURL width="500">'<mt:Unless name="__last__">,</mt:Unless></mt:EntryAssets>);
if ( entryAssets<mt:EntryID />.length != 0) {
var entrySlideshow<mt:EntryID /> = document.getElementById('entry-gallery<mt:EntryID />');
var imgIndex<mt:EntryID /> = 0
function viewImage<mt:EntryID />(direc) {
if (direc == 'next') imgIndex<mt:EntryID />++;
if (direc == 'prev') imgIndex<mt:EntryID />--;
if (imgIndex<mt:EntryID /> >= entryAssets<mt:EntryID />.length) imgIndex<mt:EntryID /> = 0;
if (imgIndex<mt:EntryID /> < 0 ) imgIndex<mt:EntryID /> = (entryAssets<mt:EntryID />.length - 1);
slideshowImage<mt:EntryID />.setAttribute('src',entryAssets<mt:EntryID />[imgIndex<mt:EntryID />]);
return false;
}
var slideshowImage<mt:EntryID /> = document.createElement('img');
slideshowImage<mt:EntryID />.setAttribute('src',entryAssets<mt:EntryID />[imgIndex<mt:EntryID />]);
slideshowImage<mt:EntryID />.setAttribute('alt','Slideshow Image');
entrySlideshow<mt:EntryID />.appendChild(slideshowImage<mt:EntryID />);
var slideshowNav<mt:EntryID /> = document.createElement('p');
var slideshowPrev<mt:EntryID /> = document.createElement('a');
slideshowPrev<mt:EntryID />.setAttribute('id','slideshow-prev');
slideshowPrev<mt:EntryID />.innerHTML = '« Previous';
slideshowPrev<mt:EntryID />.setAttribute('href','javascript:void(0)');
slideshowPrev<mt:EntryID />.setAttribute('onclick','viewImage<mt:EntryID />("prev")');
slideshowNav<mt:EntryID />.appendChild(slideshowPrev<mt:EntryID />);
var slideshowNext<mt:EntryID /> = document.createElement('a');
slideshowNext<mt:EntryID />.setAttribute('id','slideshow-next');
slideshowNext<mt:EntryID />.setAttribute('href','javascript:void(0)');
slideshowNext<mt:EntryID />.innerHTML = 'Next »';
slideshowNext<mt:EntryID />.setAttribute('onclick','viewImage<mt:EntryID />("next")');
slideshowNav<mt:EntryID />.appendChild(slideshowNext<mt:EntryID />);
entrySlideshow<mt:EntryID />.appendChild(slideshowNav<mt:EntryID />);
}
//]]>
</script>
</mt:Entries>
MTAssetThumbnailLinkタグとMTAssetThumbnailURLタグのsquareモディファイアの動作
MTAssetThumbnailLinkタグとMTAssetThumbnailURLタグのsquareモディファイアの動作について調べてみました。調査の発端はriatwさんのツイートです。
1.squareモディファイアについて
squareモディファイアは、サムネイルの縦横比を1:1で出力するためのものです。辺のサイズは widthモディファイア, heightモディファイアまたはscale モディファイアで決定します。
冒頭に記したとおり、このモディファイアはMTAssetThumbnailLinkタグ、MTAssetThumbnailURLタグで利用できます。
2.サンプル
上がsquareモディファイアで整形した画像、下が元画像です。どの部分を切り取っているかは次項で解説します。
![]()
3.squareモディファイアで切り取られる部分
squareモディファイアでは、まず次の2つの値を元に、1辺のサイズ(縮小したサイズではなく、縦横比を1:1にするためのサイズ)とx方向およびy方向の切り取り開始位置を決定します。
- 元画像の幅(px):w
- 元画像の高さ(px):h
wがhより大きい場合は次のように計算します。
- 1辺のサイズ:h
- x方向の切り取り開始位置:w-h/2(1辺が画像の中心になるようにxを設定)
- y方向の切り取り開始位置:0
wがhより小さい場合(またはwとhが等しい場合)は次のように計算します。
- 1辺のサイズ:w
- x方向の切り取り開始位置:0
- y方向の切り取り開始位置:h-w/2(1辺が画像の中心になるようにyを設定)
その後、正方形に切り取った画像を、widthモディファイア、heightモディファイア、scaleモディファイアで指定されたサイズに縮小します。拡大はできません。
4.処理の流れ
おまけで、トレース結果を残しておきます。
MTAssetThumbnailURLタグはMT::Template::Tags::Asset::_hdlr_asset_thumbnail_urlを実行します。
sub _hdlr_asset_thumbnail_url {
my ($ctx, $args) = @_;
my $a = $ctx->stash('asset')
or return $ctx->_no_asset_error();
return '' unless $a->has_thumbnail;
my %arg;
foreach (keys %$args) {
$arg{$_} = $args->{$_};
}
$arg{Width} = $args->{width} if $args->{width};
$arg{Height} = $args->{height} if $args->{height};
$arg{Scale} = $args->{scale} if $args->{scale};
$arg{Square} = $args->{square} if $args->{square};
my ($url, $w, $h) = $a->thumbnail_url(%arg);
return $url || '';
}
MTAssetThumbnailLinkタグはMT::Template::Tags::Asset::_hdlr_asset_thumbnail_linkを実行します。いずれも、後は青色で示す関数を順次実行します(多分)。
sub _hdlr_asset_thumbnail_link {
my ($ctx, $args) = @_;
my $a = $ctx->stash('asset')
or return $ctx->_no_asset_error();
my $class = ref($a);
return '' unless UNIVERSAL::isa($a, 'MT::Asset::Image');
# # Load MT::Image
# require MT::Image;
# my $img = new MT::Image(Filename => $a->file_path)
# or return $ctx->error(MT->translate(MT::Image->errstr));
# Get dimensions
my %arg;
$arg{Width} = $args->{width} if $args->{width};
$arg{Height} = $args->{height} if $args->{height};
$arg{Scale} = $args->{scale} if $args->{scale};
$arg{Square} = $args->{square} if $args->{square};
my ($url, $w, $h) = $a->thumbnail_url(%arg);
my $ret = sprintf qq(<a href="%s"), $a->url;
if ($args->{new_window}) {
$ret .= qq( target="_blank");
}
$ret .= sprintf qq(><img src="%s" width="%d" height="%d" alt="" /></a>), $url, $w, $h;
$ret;
}
MT::Asset::thumbnail_urlを実行します。
sub thumbnail_url {
my $asset = shift;
my (%param) = @_;
require File::Basename;
if (my ($thumbnail_file, $w, $h) = $asset->thumbnail_file(@_)) {
return $asset->stock_icon_url(@_) if !defined $thumbnail_file;
my $file = File::Basename::basename($thumbnail_file);
my $asset_file_path = $asset->SUPER::file_path();
my $site_url;
my $blog = $asset->blog;
if (!$blog) {
$site_url = $param{Pseudo} ? '%s' : MT->instance->support_directory_url;
}
elsif ( $asset_file_path =~ m/^%a/ ) {
$site_url = $param{Pseudo} ? '%a' : $blog->archive_url;
}
else {
$site_url = $param{Pseudo} ? '%r' : $blog->site_url;
}
if ($file && $site_url) {
require MT::Util;
my $path = $param{Path};
if (!defined $path) {
$path = MT::Util::caturl(MT->config('AssetCacheDir'), unpack('A4A2', $asset->created_on));
} else {
require File::Spec;
my @path = File::Spec->splitdir($path);
$path = '';
for my $p (@path) {
$path = MT::Util::caturl($path, $p);
}
}
$file = MT::Util::encode_url($file);
$site_url = MT::Util::caturl($site_url, $path, $file);
return ($site_url, $w, $h);
}
}
# Use a stock icon
return $asset->stock_icon_url(@_);
}
MT::Asset::Image::thumbnail_file(MT::Assetを継承)を実行します。
sub thumbnail_file {
my $asset = shift;
my (%param) = @_;
my $fmgr;
my $blog = $param{Blog} || $asset->blog;
require MT::FileMgr;
$fmgr ||= $blog ? $blog->file_mgr : MT::FileMgr->new('Local');
return undef unless $fmgr;
my $file_path = $asset->file_path;
return undef unless $fmgr->exists( $file_path );
require MT::Util;
my $asset_cache_path = $asset->_make_cache_path($param{Path});
my ( $i_h, $i_w ) = ( $asset->image_height, $asset->image_width );
return undef unless $i_h && $i_w;
# Pretend the image is already square, for calculation purposes.
if ($param{Square}) {
require MT::Image;
my %square = MT::Image->inscribe_square(
Width => $i_w, Height => $i_h );
($i_h, $i_w) = @square{qw( Size Size )};
if ( $param{Width} && !$param{Height} ) {
$param{Height} = $param{Width};
}
elsif ( !$param{Width} && $param{Height} ) {
$param{Width} = $param{Height};
}
}
if ( my $scale = $param{Scale} ) {
$param{Width} = int( ( $i_w * $scale ) / 100 );
$param{Height} = int( ( $i_h * $scale ) / 100 );
}
if ( !exists $param{Width} && !exists $param{Height} ) {
$param{Width} = $i_w;
$param{Height} = $i_h;
}
# find the longest dimension of the image:
my ( $n_h, $n_w ) =
_get_dimension( $i_h, $i_w, $param{Height}, $param{Width} );
my $file = $asset->thumbnail_filename(%param) or return;
my $thumbnail = File::Spec->catfile( $asset_cache_path, $file );
# thumbnail file exists and is dated on or later than source image
if ( $fmgr->exists($thumbnail)
&& ( $fmgr->file_mod_time($thumbnail) >= $fmgr->file_mod_time($file_path))) {
return ( $thumbnail, $n_w, $n_h );
}
# stale or non-existent thumbnail. let's create one!
return undef unless $fmgr->can_write($asset_cache_path);
my $data;
if ( ( $n_w == $i_w ) && ( $n_h == $i_h ) && !$param{Square}
&& !$param{Type} ) {
$data = $fmgr->get_data( $file_path, 'upload' );
}
else {
# create a thumbnail for this file
require MT::Image;
my $img = new MT::Image( Filename => $file_path )
or return $asset->error( MT::Image->errstr );
# Really make the image square, so our scale calculation works out.
if ($param{Square}) {
($data) = $img->make_square()
or return $asset->error(
MT->translate( "Error cropping image: [_1]", $img->errstr ) );
}
($data) = $img->scale( Height => $n_h, Width => $n_w )
or return $asset->error(
MT->translate( "Error scaling image: [_1]", $img->errstr ) );
if (my $type = $param{Type}) {
($data) = $img->convert( Type => $type )
or return $asset->error(
MT->translate( "Error converting image: [_1]", $img->errstr ) );
}
}
$fmgr->put_data( $data, $thumbnail, 'upload' )
or return $asset->error(
MT->translate( "Error creating thumbnail file: [_1]", $fmgr->errstr ) );
return ( $thumbnail, $n_w, $n_h );
}
MT::Image::inscribe_squareを実行します。
sub inscribe_square {
my $class = shift;
my %params = @_;
my ($w, $h) = @params{qw( Width Height )};
my ($dim, $x, $y);
if ($w > $h) {
$dim = $h;
$x = int(($w - $dim) / 2);
$y = 0;
}
else {
$dim = $w;
$x = 0;
$y = int(($h - $dim) / 2);
}
return ( Size => $dim, X => $x, Y => $y );
}
MT::Image::make_squareを実行します。
sub make_square {
my $image = shift;
my %square = $image->inscribe_square(
Width => $image->{width},
Height => $image->{height},
);
$image->crop(%square);
}
このあとは利用している画像ライブラリによって、実行関数が異なります。
ImageMagickを利用している場合、MT::Image::ImageMagick::cropを実行します。
sub crop {
my $image = shift;
my %param = @_;
my ($size, $x, $y) = @param{qw( Size X Y )};
my $magick = $image->{magick};
my $err = $magick->Crop(width => $size, height => $size, x => $x, y => $y);
return $image->error(MT->translate(
"Cropping a [_1]x[_1] square at [_2],[_3] failed: [_4]", $size, $x,
$y, $err)) if $err;
## Remove page offsets from the original image, per this thread:
## http://studio.imagemagick.org/pipermail/magick-users/2003-September/010803.html
$magick->Set( page => '+0+0' );
($image->{width}, $image->{height}) = ($size, $size);
wantarray ? ($magick->ImageToBlob, $size, $size) : $magick->ImageToBlob;
}
NetPBMを利用している場合、MT::Image::NetPBM::cropを実行します。
sub crop {
my $image = shift;
my %param = @_;
my ($size, $x, $y) = @param{qw( Size X Y )};
my($w, $h) = $image->get_dimensions(@_);
my $type = $image->{type};
my($out, $err);
my $pbm = $image->_find_pbm or return;
my @in = ("$pbm${type}topnm", ($image->{data} ? () : $image->{file} ? $image->{file} : ()));
my @crop = ("${pbm}pnmcut", $x, $y, $size, $size);
my @out;
for my $try (qw( ppm pnm )) {
my $prog = "${pbm}${try}to$type";
@out = ($prog), last if -x $prog;
}
my(@quant);
if ($type eq 'gif') {
push @quant, ([ "${pbm}ppmquant", 256 ], '|');
}
IPC::Run::run(\@in, '<', ($image->{data} ? \$image->{data} : \undef), '|',
\@crop, '|',
@quant,
\@out, \$out, \$err)
or return $image->error(MT->translate(
"Cropping to [_1]x[_1] failed: [_2]", $size, $err));
($image->{width}, $image->{height}, $image->{data}) = ($w, $h, $out);
wantarray ? ($out, $w, $h) : $out;
}
GDを利用している場合、MT::Image::GD::cropを実行します。
sub crop {
my $image = shift;
my %param = @_;
my ($size, $x, $y) = @param{qw( Size X Y )};
my $src = $image->{gd};
my $gd = GD::Image->new($size, $size, 1); # True color image (24 bit)
$gd->copy($src, 0, 0, $x, $y, $size, $size);
($image->{gd}, $image->{width}, $image->{height}) = ($gd, $size, $size);
wantarray ? ($image->blob, $size, $size) : $image->blob;
}
以上です。
Movable Type のブログ記事に表示する画像のサイズを制御する
Movable Type のブログ記事に挿入した画像の表示サイズを制御するカスタマイズです。
ここでは次のようなサンプルを提供します。
- 元画像の幅が 200px 以上であれば、200px のサムネイルを表示
- 元画像の幅が 200px 未満であれば元画像を表示
完成イメージ

1.基本
画像の幅は MTAssetProperty タグに property="image_width" を与えることで取得できます。ここでは取得した値を変数 width に保存し、MTIf タグで判定します。
元画像の表示は、img 要素の src 属性に MTAssetURL タグを与えます。サムネイル画像の場合は、img 要素の src 属性に MTAssetThumbnailURL タグを与えます。サムネイルは事前に作成する必要はなく、このサブテンプレートが実行された時点で自動的に作成します。
なお、サムネイルを生成するには ImageMagick の利用が必要です。
<mt:SetVar name="size" value="200" />
<mt:Entries>
<mt:EntryAssets>
<mt:AssetProperty property="image_width" setvar="width" />
<mt:If name="width" lt="$size">
<p><img src="<mt:AssetURL />" alt="<mt:AssetFileName />" /></p>
<mt:Else>
<p><img src="<mt:AssetThumbnailURL width="$size" />" alt="<mt:AssetFileName />" /></p>
</mt:If>
</mt:EntryAssets>
</mt:Entries>
2.サムネイルの場合は元画像へのリンクを表示する場合
サムネイルに元画像へのリンクを表示する場合は、1項の MTAssetThumbnailURL タグ(と img 要素)の代わりに、MTAssetThumbnailLink タグを利用します(青色部分)。MTAssetThumbnailLink タグを使わずに、MTAssetThumbnailURL タグと MTAssetURL タグを組み合わせても構いません。
<mt:SetVar name="size" value="200" />
<mt:Entries>
<mt:EntryAssets>
<mt:AssetProperty property="image_width" setvar="width" />
<mt:If name="width" lt="$size">
<p><img src="<mt:AssetURL />" alt="<mt:AssetFileName />" /></p>
<mt:Else>
<p><mt:AssetThumbnailLink width="$size" alt="<mt:AssetFileName />" /></p>
</mt:If>
</mt:EntryAssets>
</mt:Entries>
いずれも、赤字の値を変更すれば、表示する画像の幅を変更できます。また、(X)HTML のマークアップは適宜変更してください。
Movable Type + Windows で日本語ファイル名を扱う方法
Movable Type を Windows で運用し、日本語ファイル名を扱うための方法です。ここでは Movable Type 4.25 を使ったカスタマイズを紹介します。
1.概要
Movable Type デフォルトの状態では、Window 上に構築した Movalbe Type で日本語ファイル名を扱うことはできません(仕様です)。
例えば、「コーヒーカップ.jpg」というファイルをアップロードすると、アップロード自体はできますが、アイテム一覧は次のように、アップロードした画像が表示されません(同じ画像のcoffee.jpgと比較)。画像のリンクをクリックしても 404 Not Found になります。
![]()
半角英数ファイル名の画像をクリックすると拡大画像を次のように表示できますが、
![]()
日本語ファイルでは表示されません。
![]()
サムネイルも正常に表示されません。
![]()
ブログ記事への挿入は、半角英数ファイル名であれば正常に挿入できますが、
![]()
日本語ファイルでは正常に挿入できません。
![]()
アップロードしたファイルをエクスプローラーで参照すると、次のように文字化けしています。

asset_c 配下のサムネイルやキャッシュファイルも文字化けしています。

ということで、本エントリーでは、ファイルのアップロード時にファイル名を Shift_JIS で保存し、アイテム一覧などでのファイル名操作での文字コードを修正して、日本語ファイル名を正常に処理できるようにカスタマイズする方法を以下に紹介します。
2.カスタマイズ
カスタマイズは、パッチを利用して、lib/MT 配下の4つのファイルを修正します。パッチが分からない方は、手修正できる方法も併せて掲載しています。なお、修正対象のファイルは、修正前に必ずバックアップを保存してください。
lib/MT/FileMgr/Local.pm
lib/MT/FileMgr/Local.pm を修正します。修正目的は次の通りです。
- ファイルアップロード時の元ファイル名の文字コード変更
- 元ファイルの削除時のファイル名の文字コード変更
--- lib/MT/FileMgr/Local.pm.bak Fri May 22 01:48:47 2009
+++ lib/MT/FileMgr/Local.pm Fri May 22 01:49:05 2009
@@ -12,6 +12,7 @@
use Symbol;
use Fcntl qw( :DEFAULT :flock );
+use Jcode;
sub get_data {
my $fmgr = shift;
@@ -68,6 +69,7 @@
$perms = $cfg->HTMLPerms;
}
my $old = umask(oct $umask);
+ $to = jcode($to)->sjis;
sysopen FH, $to, O_RDWR|O_CREAT|O_TRUNC, oct $perms
or return $fmgr->error(MT->translate(
"Opening local file '[_1]' failed: [_2]", $to, "$!"));
@@ -165,7 +167,7 @@
sub delete {
my $fmgr = shift;
my ($file) = @_;
-
+ $file = jcode($file)->sjis;
return 1 unless -e $file or -l $file;
unlink $file
or return $fmgr->error(MT->translate(
パッチが分からない方は下記の青色部分を追加してください。
...前略...
use Symbol;
use Fcntl qw( :DEFAULT :flock );
use Jcode;
...中略...
sub _write_file {
my $fmgr = shift;
my($from, $to, $type) = @_;
local *FH;
my($umask, $perms);
my $cfg = MT->config;
if ($type && $type eq 'upload') {
$umask = $cfg->UploadUmask;
$perms = $cfg->UploadPerms;
} else {
$umask = $cfg->HTMLUmask;
$perms = $cfg->HTMLPerms;
}
my $old = umask(oct $umask);
$to = jcode($to)->sjis;
sysopen FH, $to, O_RDWR|O_CREAT|O_TRUNC, oct $perms
or return $fmgr->error(MT->translate(
"Opening local file '[_1]' failed: [_2]", $to, "$!"));
...中略...
sub delete {
my $fmgr = shift;
my ($file) = @_;
$file = jcode($file)->sjis;
return 1 unless -e $file or -l $file;
...後略...
lib/MT/Asset/Image.pm
lib/MT/Asset/Image.pm を修正します。修正目的は次の通りです。
- アイテムが画像の場合、オプションでサムネイルを指定した場合など、サムネイルのファイル名の文字コード変更
--- lib/MT/Asset/Image.pm.bak Fri May 22 01:48:42 2009
+++ lib/MT/Asset/Image.pm Fri May 22 01:49:10 2009
@@ -8,6 +8,7 @@
use strict;
use base qw( MT::Asset );
+use Jcode;
__PACKAGE__->install_properties( {
class_type => 'image',
@@ -91,7 +92,8 @@
my $asset = shift;
my (%param) = @_;
my $file_path = $asset->file_path;
- my @imginfo = stat($file_path);
+ my $file_path2 = jcode($file_path)->sjis;
+ my @imginfo = stat($file_path2);
return undef unless @imginfo;
my $blog = $param{Blog} || $asset->blog;
@@ -153,7 +155,7 @@
# create a thumbnail for this file
require MT::Image;
- my $img = new MT::Image( Filename => $file_path )
+ my $img = new MT::Image( Filename => $file_path2 )
or return $asset->error( MT::Image->errstr );
# Really make the image square, so our scale calculation works out.
パッチが分からない方は下記の赤色部分を削除し、青色部分を追加してください。
...前略...
use strict;
use base qw( MT::Asset );
use Jcode;
...中略...
sub thumbnail_file {
my $asset = shift;
my (%param) = @_;
my $file_path = $asset->file_path;
my @imginfo = stat($file_path);
my $file_path2 = jcode($file_path)->sjis;
my @imginfo = stat($file_path2);
return undef unless @imginfo;
...中略...
else {
# create a thumbnail for this file
require MT::Image;
my $img = new MT::Image( Filename => $file_path )
my $img = new MT::Image( Filename => $file_path2 )
or return $asset->error( MT::Image->errstr );
...後略...
lib/MT/Asset.pm
lib/MT/Asset.pm を修正します。修正目的は次の通りです。
- キャッシュファイル(asset_c 配下のサムネイル画像)の削除時のファイル名の文字コード変更
--- lib/MT/Asset.pm.bak Thu Mar 12 05:41:04 2009
+++ lib/MT/Asset.pm Fri May 22 01:43:30 2009
@@ -9,6 +9,7 @@
use strict;
use MT::Tag; # Holds MT::Taggable
use base qw( MT::Object MT::Taggable MT::Scorable );
+use Jcode;
__PACKAGE__->install_properties({
column_defs => {
@@ -182,6 +183,7 @@
my $basename = $asset->file_name;
my $ext = '.'.$asset->file_ext;
$basename =~ s/$ext$//;
+ $basename = jcode($basename)->sjis;
my $cache_glob = File::Spec->catfile($cache_dir,
$basename . '-thumb-*' . $ext);
my @files = glob($cache_glob);
パッチが分からない方は下記の青色部分を追加してください。
...前略...
use strict;
use MT::Tag; # Holds MT::Taggable
use base qw( MT::Object MT::Taggable MT::Scorable );
use Jcode;
...中略...
sub remove_cached_files {
my $asset = shift;
# remove any asset cache files that exist for this asset
my $blog = $asset->blog;
if ($asset->id && $blog) {
my $cache_dir = $asset->_make_cache_path;
if ($cache_dir) {
require MT::FileMgr;
my $fmgr = $blog->file_mgr || MT::FileMgr->new('Local');
if ($fmgr) {
my $basename = $asset->file_name;
my $ext = '.'.$asset->file_ext;
$basename =~ s/$ext$//;
$basename = jcode($basename)->sjis;
my $cache_glob = File::Spec->catfile($cache_dir,
$basename . '-thumb-*' . $ext);
...後略...
lib/MT/CMS/Asset.pm
lib/MT/CMS/Asset.pm を修正します。修正目的は次の通りです。
- アイテム一覧でアイテムを正常に取得・表示するための文字コード変更
- title属性に日本語を適正に表示するため、文字コードをUTF-8に戻す
--- lib/MT/CMS/Asset.pm.bak Thu Feb 05 18:49:50 2009
+++ lib/MT/CMS/Asset.pm Fri May 22 01:44:48 2009
@@ -3,6 +3,7 @@
use strict;
use Symbol;
use MT::Util qw( epoch2ts encode_url format_ts relative_date );
+use Jcode;
sub edit {
my $cb = shift;
@@ -590,10 +591,12 @@
$row->{asset_type} = $obj->class_type;
$row->{asset_class_label} = $obj->class_label;
my $file_path = $obj->file_path; # has to be called to calculate
+ $file_path = jcode($file_path)->sjis;
my $meta = $obj->metadata;
if ( $file_path && ( -f $file_path ) ) {
$row->{file_path} = $file_path;
$row->{file_name} = File::Basename::basename( $file_path );
+ $row->{file_name} = jcode($row->{file_name})->utf8;
my @stat = stat( $file_path );
my $size = $stat[7];
$row->{file_size} = $size;
パッチが分からない方は下記の青色部分を追加してください。
...前略...
use strict;
use Symbol;
use MT::Util qw( epoch2ts encode_url format_ts relative_date );
use Jcode;
...中略...
sub build_asset_hasher {
my $app = shift;
my (%param) = @_;
my ($default_thumb_width, $default_thumb_height, $default_preview_width,
$default_preview_height) =
@param{qw( ThumbWidth ThumbHeight PreviewWidth PreviewHeight )};
require File::Basename;
require JSON;
my %blogs;
return sub {
my ( $obj, $row, %param ) = @_;
my ($thumb_width, $thumb_height) = @param{qw( ThumbWidth ThumbHeight )};
$row->{id} = $obj->id;
my $blog = $blogs{ $obj->blog_id } ||= $obj->blog;
$row->{blog_name} = $blog ? $blog->name : '-';
$row->{url} = $obj->url; # this has to be called to calculate
$row->{asset_type} = $obj->class_type;
$row->{asset_class_label} = $obj->class_label;
my $file_path = $obj->file_path; # has to be called to calculate
$file_path = jcode($file_path)->sjis;
my $meta = $obj->metadata;
if ( $file_path && ( -f $file_path ) ) {
$row->{file_path} = $file_path;
$row->{file_name} = File::Basename::basename( $file_path );
$row->{file_name} = jcode($row->{file_name})->utf8;
my @stat = stat( $file_path );
...後略...
3.修正後の動作
アイテム一覧で画像が正常に表示されます。

拡大画像も正常に表示されます。

アップロードしたファイルをエクスプローラーで参照すると、次のように日本語が適正に表示されます。

asset_c 配下のサムネイルやキャッシュファイルも適正に表示されています。

ブログ記事への挿入もOKです。

サムネイルも表示されます。

4.注意事項
- サムネイルの拡大画像が表示されません(分かり次第追記します)。
- 確認しているのは、テキストファイルと画像ファイルのみです。音声・動画ファイルの動作は未確認です。
- FastCGI を利用していると正常に動作しません。
Movable Type 4 におけるアイテムのアップロード動作(その2)
「Movable Type 4 におけるアイテムのアップロード動作(その1)」に続いて、画像アップロード時などにサムネイルを作成するときの動作を紹介します。
1.基本動作
ご存知の方も多いと思いますが、Movable Type 4.x では画像のアップロード時の「ファイルオプション」画面で、サムネイルを同時に作成することができます(下)。

オプション画面でサムネイル作成を指定すると、アップロード後、ブログ記事の作成画面に移動し、本文フィールドにサムネイルが表示されます。

なお、サムネイルを作成するには、ImageMagick などの画像作成用ソフトと、それに対応する Perl モジュールがインストールされている必要があります。
2.サムネイルのパスとファイル名
1項で作成したサムネイルは、オプション画面の「完了」クリック時に、
- ブログディレクトリ/assets_c/yyyy/mm
配下にサムネイルファイルが生成されます。サムネイルのファイル名付与規則は次のようになっています。
[画像ファイル名(拡張子を除く)]-thumb-[サムネイルサイズ(幅*高さ)]-[asset-id].[拡張子]
例えば、2009年5月20日に、coffee.jpg というファイルで、200px 幅(高さは自動計算で 133px)のサムネイルを指定してアップロードを行なうと、サムネイルファイルのパスとファイル名は、
- ブログディレクトリ/assets_c/2009/05/coffee-thumb-200x133-1.jpg
という風になります。
3.ポップアップ指定時のファイル
サムネイル作成時にポップアップを指定すると、2項と同じディレクトリにポップアップ用のHTMLが生成されます。ポップアップ用のHTMLのファイル名付与規則は次のようになっています。
[画像ファイル名(拡張子を除く)]-[asset-id].html
アイテムの一覧には次のように「××のポップアップページ」が表示されます。

4.サムネイルを後でブログ記事などに使いたい時
テンプレートタグを使わずに、サムネイルをページに表示させたい時は、アイテム一覧に、元画像と一緒にサムネイルも表示されるので、画像のリンクまたは「~のサムネール画像」をクリックします。

アイテムの編集画面の「アイテムの埋め込み」をクリックします。

このようにアイテムのURLが表示されるので、それを利用すると良いでしょう。

元画像やポップアップページの URL も、同じ方法で取得できます。
5.管理画面で利用されるサムネイル
管理画面のアイテムの一覧を表示すると、アップロードした画像のサムネイルの有無にかかわらず、
- ブログディレクトリ/assets_c/yyyy/mm
に次のサムネイルが作成されます。これはアイテム一覧に表示するためのサムネイルで、ここでは便宜上、「管理画面サムネイル」と呼びます。
管理画面に「管理画面サムネイル」を表示する日付が変わっても、最初に表示したときに生成した管理画面サムネイルが使われるので、冗長に作成されることはありません。
管理画面サムネイルのファイル名付与規則は次のようになっています。
| 対象 | ファイル名 | 用途 | |
|---|---|---|---|
| 元の画像ファイル | [画像ファイル名(拡張子を除く)]-thumb-75x75-[asset-id].[拡張子] | アイテム一覧表示用 | ① |
| [画像ファイル名(拡張子を除く)]-thumb-240x240-[asset-id].[拡張子] | アイテム一覧の画像の右下にある虫眼鏡アイコンをクリックしたときやアイテム編集画面で表示 | ② | |
| サムネイル | [画像ファイル名(拡張子を除く)]-thumb-[サムネイルサイズ]-[元ファイルのasset-id]-thumb-75x75-[asset-id].[拡張子] | アイテム一覧表示用 | ③ |
| [画像ファイル名(拡張子を除く)]-thumb-[サムネイルサイズ]-[元ファイルのasset-id]-thumb-240x240-[asset-id].[拡張子] | アイテム一覧の画像の右下にある虫眼鏡アイコンをクリックしたときやアイテム編集画面で表示 | ④ | |
つまり、ある画像ファイルについて、サムネイルを作成してアップロードした後、アイテム一覧を表示すると、asset_c ディレクトリに計5つの画像ファイルが生成されることになります。例えば、coffee.jpg のサムネイル(幅200px)を作成した場合、次のようなファイルが生成されます。
- coffee-thumb-75x75-1.jpg(①)
- coffee-thumb-200x133-1.jpg(サムネイル)
- coffee-thumb-200x133-1-thumb-75x75-2.jpg(③)
- coffee-thumb-200x133-1-thumb-240x240-2.jpg(④)
- coffee-thumb-240x240-1.jpg(②)
4.アイテムの削除
元の画像ファイルをアイテム一覧から削除すれば、サムネイルや管理画面サムネイルも自動的に削除されます。
Movable Type 4 におけるアイテムのアップロード動作(その1)
Movable Type 4.x での、アイテムのアップロードについて簡単にまとめました。ひとつのエントリーで色々書こうと思いましたが、書く暇がなかったため小出しでエントリーします。
1.ファイルのアップロード
「新規作成」→「ファイルアップロード」で、ファイルをアップロードすると、指定したディレクトリにアップロードされます。「アップロード」をクリックするとアップロードが開始します。
2.プルダウンメニューでアップロード先の指定
アーカイブパスを利用していない場合、アップロード先を選択するプルダウンメニューには「サイトパス」と「サイトパス+日付」が選択できます(下)。

アーカイブパスを利用しているい場合、アップロード先を選択するプルダウンメニューには「サイトパス」、「アーカイブパス」、「アーカイブパス+日付」が選択できます(下)。

デフォルトの状態では、プルダウンメニューにはこれ以外の選択肢はないようです(見落としていたらすいません)。
3.フォルダによるアップロード先の指定
アップロード先のフォルダを予め作成しておき、ファイルアップロード画面にある「フォルダの選択」をクリックすることで、フォルダ機能を使ったアップロード先の選択ができます(下)。

フォルダ名の編集で「フォルダの名前」を日本語にすれば、上のように日本語を表示できます(実際のフォルダ名は半角英数です)。
4.プラグインによるアップロード先の選択
アップロードするファイルの拡張子によって、アップロード先を振り分ける便利なプラグインもあります。
ブログ記事に挿入したアイテムだけのサムネイル画像一覧を表示する(その2)
以前エントリーした「ブログ記事に挿入したアイテムだけのサムネイル画像一覧を表示する」の別の方法です。
Movable Type 4.x のデフォルトテンプレートのアイテム一覧は、アップロードしたアイテムがすべて表示されます。ブログ記事に挿入した画像だけを表示したくても、ブログ記事と無関係にアップロードしたアイテムが含まれてしまいます。
ブログ記事に挿入した画像のサムネイル画像だけを表示したい場合には、次のように MTAsset タグに tag モディファイアを付与し、プライベートタグを与えます(青色部分)。
<mt:If tag="AssetCount">
<mt:Assets type="image" lastn="10" tag="@entry">
<mt:AssetsHeader>
<div class="widget-recent-assets widget">
<h3 class="widget-header">アイテム</h3>
<div class="widget-content">
<ul>
</mt:AssetsHeader>
<li class="item"><a class="asset-image" href="<$mt:AssetURL$>"><img src="<$mt:AssetThumbnailURL height="70"$>" class="asset-img-thumb" alt="<$mt:AssetLabel$>" title="<$mt:AssetLabel$>" /></a></li>
<mt:AssetsFooter>
</ul>
</div>
</div>
</mt:AssetsFooter>
</mt:Assets>
</mt:If>
あとは、ファイルのアップロード時などで、表示させたい画像のタグフィールドに「@entry」を設定すれば OK です。

「ブログ記事に挿入したアイテムだけのサムネイル画像一覧を表示する」のように全自動ではありませんが、タグを付与しない限り、間違って表示されることはありません。また、プライベートタグを使用するのでタグクラウドにも表示されません。
ブログ記事に挿入したアイテムだけのサムネイル画像一覧を表示する
Movable Type 4.x のデフォルトテンプレートのアイテム一覧は、アップロードしたアイテムがすべて表示されます。ブログ記事に挿入した画像だけを表示したくても、ブログ記事と無関係にアップロードしたアイテムが含まれてしまいます。
ブログ記事に挿入した画像のサムネイル画像だけを表示したい場合には、次のように「アイテム」ウィジェットを改変する必要があります。
<mt:ignore>ブログにアイテムがあれば実行</mt:ignore>
<mt:if tag="AssetCount">
<mt:ignore>変数初期化</mt:ignore>
<mt:setVar name="counter" value="0" />
<mt:setVar name="flag" value="0" />
<mt:blogEntryCount setvar="entry_count" />
<mt:entries lastn="$entry_count">
<mt:entryAssets type="image">
<mt:assetsHeader>
<mt:ignore>フラグが設定されていなければヘッダーを出力</mt:ignore>
<mt:unless name="flag">
<div class="widget-recent-assets widget">
<h3 class="widget-header">アイテム</h3>
<div class="widget-content">
<ul class="widget-list">
<mt:ignore>フラグ設定してこのunless文が実行されないようにする</mt:ignore>
<mt:setVar name="flag" value="1" />
</mt:unless>
</mt:assetsHeader>
<mt:ignore>10アイテムまで表示</mt:ignore>
<mt:if name="counter" lt="10">
<li class="item"><a class="asset-image" href="<$mt:assetURL$>"><img src="<$mt:assetThumbnailURL height="70"$>" class="asset-img-thumb" alt="<$mt:assetLabel$>" title="<$mt:assetLabel$>" /></a></li>
<mt:ignore>カウンタインクリメント</mt:ignore>
<mt:setVar name="counter" op="++" />
</mt:if>
</mt:entryAssets>
</mt:entries>
<mt:ignore>フラグが立っていたらフッターを出力</mt:ignore>
<mt:if name="flag">
</ul>
</div>
</div>
</mt:if>
</mt:if>
赤色部分の数字を変更すれば、表示件数を変更することができます。
2009.08.20
サブテンプレートを一部修正しました。

