f:id:g998iyvj:20170211140546j:plain

 

会計事務所に実際に働いていると、「この人は性格的に向いてるだろうな。楽しそうだし」あるいは、

「この人はあんまり向いてないんだろうな…。つらそう」

というのはやっぱり出てくるのが現実です。

ここでは10年間ほど会計事務所で働いた経験から、会計事務所への転職に向いている人はどんな人なのか?ということを書いてみようと思います。

これから会計事務所で働く予定の方(転職予定の方)の参考になれば嬉しいです。

 

自分はまじめ、という自覚のある方は実は要注意

会計事務所(税理士)に向いている人、というと几帳面でまじめ、どちらかというと内気な人、というイメージがあると思います。

もちろん、1円でも誤差があるとダメな世界ですから、数字を扱う仕事に抵抗がないのは大前提です。

ですが、私の経験的にいうと「真面目すぎる人」ほど早く会計事務所からやめていってしまうという印象がありますね。

会計事務所の仕事では、適度な「いい加減さ(良い意味で)」がないと精神的なプレッシャーに耐えられなくなってしまうケースが非常に多いです。

下手をするとうつ状態みたいになってしまう人も見てきました。

仕事そのものが非常に細かい作業なので、ストレスのコントロールや息抜きが適度にできる人の方が向いていると思います。

自分はちょっと性格的に真面目すぎる…という自覚がある人は注意してくださいね。

 

かなりキャラの濃いお客さんを相手にすることになるのは知っておこう

会計事務所のお客さんは、中小企業の社長です。

中小企業の社長には、大きく分けて2種類います。

1つめは創業社長。もう1つは2代目、3代目の社長です。

創業社長の場合、かなりバイタリティが高い人が多いです。

まだ会社の規模が小さい(社長を含めて社員1人〜5人ぐらい)の場合は猛烈な仕事人、というイメージの人が多いですね。

体育会系のイケイケドンドンな兄ちゃん、という雰囲気の人が多いです。

ある程度の規模の大きい会社の創業社長というのは人間的に尊敬できる人が多いです。会計事務所に転職するなら、こういうお客さんを担当させてもらえるように頑張りましょう。


2代目、3代目の経営者となるとこれもまたいろんな種類がいますね。

世間知らずで横文字の経営理論をしゃべっているだけ(でも業績は悪い)という人もいれば、現場で従業員に仕事を教えてもらいながら頑張っている人もいます。

会計事務所に転職するということは、日常的にこういう人たちを相手に仕事をしていくということも理解しておくべきです。

コミュニケーション能力もみがくことも大切ですね。

 

 

木曜ごとにサダヲハァハァ坂口ハァハァするbotと化します

仕事で効率化の話が出た時に、短TATの話が出たのですが、ンなもん集中してやればそんなにかからねぇけど、仕事が多数平行で流れてて、集中して出来る人がいねぇよ、ひ・と・がっ!!という感じです。

とは言え、なんだかんだで何かアイデアを考える必要が出てきました。で、宿題を貰ったのですが、帰宅して午前3時に、依頼のされ方が、なんとなく無茶振りじゃね?、つか、この依頼のされ方おかしくね?って思うようになりましたが、きっと明日起きたら今日思ったことを忘れるんでしょうね。

と、それはさておき、

DeNAベイスターズでしょうもない騒動が起きていますね。
シーズン中にやる騒動じゃないというところにベイス感が満載です。

GMとノリさんが会談をしてどうにか収束の方向に持って行きそうな気もしますが、それはさておき、

http://news.goo.ne.jp/article/hochi/sports/20140509-134-OHT1T50005.html
のニュースを見たところ、監督がモチベーションが無い選手を使えない。といっていたそうで。

そらそうなんかもしれないですけど、これを会社でやったら大事ですよね。
仕事に対するモチベーションがない部下をモチベーションが無いから仕事をさせないなんてことしたら、それはそれは大変なことになります。

だもんで、モチベーション上がらねぇという部下がいれば、上司が話しをするなり場合によっては部署を替えさせたり、仕事内容を変更したりで、どうにかモチベーションをあげてもらうような動きをするのが一般的なのですが、いくらプロ野球だからといって、それをしようとする素振りも見せないのはどうなんだろうと思いました。

選手「モチベーション下がるわー、どう保てばいいかわからんわ」
監督「あっそ、じゃ、使わないね☆」

とか、今までの関係もあるんだろうけど、上司が部下を切り捨てるような真似はしちゃあかんです。
(ましては今はシーズン中。せめてシーズン終わるまで我慢しとこうや)

と言っても、プロの世界はそういうもの、と言われればそれまでですが。
(まあ、我々会社員だって、仕事の対価でお金を貰っているわけですから、その意味だとプロなんだと思いますがね。まあ、次元が違うのはそうですけど)

別にノリさんが正しいというわけでもないし、キヨシの対応が問題だとも思わないですけど、お互いにもっとうまいやり方出来なかったのでしょうかね。監督なんだから、「もっと結果出してからそういうこと言えや」位、言っても良かったと思うのですが(そうするとただの喧嘩になっちゃうかな?)

では。

音楽ニュースの絶えない2月ですが、今日はグラミー賞の授賞式です。

 

授賞式前に、主要4部門の授賞予想をしてみます。

 

 

 

Album Of The Year(最優秀アルバム賞)

25 — Adele
Lemonade — Beyoncé
Purpose — Justin Bieber
Views — Drake
A Sailors Guide To Earth — Sturgill Simpson

 

 

 最優秀アルバム賞は、主要部門のなかでも最も権威のある賞とされています。過去にレディオヘッド、ベック、アーケイド・ファイヤ、キングス・オブ・レオンといった優れたインディ/ロックアルバムの授賞が目立ち、特にアーケイド・ファイヤとキングス・オブ・レオンの受賞は、当時の彼等の知名度を考えるに大抜擢とも取れる意義のあるフックアップでした。グラミーの良心を感じさせる部門でもあります。しかし、昨年は多くの人に授賞を望まれていたケンドリック・ラマーを差し置き、テイラー・スウィフトにこの大賞を獲らせて物議を醸し出しました。

 

 今年は、ビヨンセとアデルの一騎打ちで間違いないでしょう。人種やジェンダーなど現在アメリカを中心に起こっている社会問題を自身のアイデンティティに絡めながらエモーショナルに語り、音楽的にも最先端かつ多くのクロスオーヴァーを実現した超大作。かたやSNS時代の人々のアナログ欲求を掻き立て国民的支持を集め、近年稀に見るメガセールスを記録した名盤。どちらが獲ってもおかしくはないです。どちらを授賞させるかで、いまのグラミーのスタンスが浮き彫りになるはずです。

 

 僕としては、間違いなくビヨンセに獲ってほしいです。作品として受賞する価値があるものだし、前年のケンドリックと並び、近年加熱している「Black Lives Matter」ムーヴメントに言及した意義のある作品です。昨年のケンドリックや多くのブラック・ミュージシャンの無念を晴らすためにも受賞してほしいです。僕はビヨンセがアルバム賞を獲ってくれれば他はどうでもいいってくらい、ここだけは期待しています。

 

予想:ビヨンセ

(希望:ビヨンセ)

 

 

 

Record Of The Year(最優秀レコード賞)

"Hello" — Adele
"Formation" — Beyoncé
"7 Years" — Lukas Graham
"Work" — Rihanna feat. Drake
"Stressed Out" — Twenty One Pilots

 

 

 リアーナが主要部門だとここしかチャンスがないのもありますが、是非とも「Work」に獲ってもらいたいです。昨年の僕の年間ベストでも触れていますが、2016年のベストアンセムの一つでした。時代の空気感を含んだ名曲という意味では「Formation」も捨て難いですけど。

というのが僕の願望ですが、これまでのグラミーのアデルへの評価と前作での無双ぶりを踏まえると、アデルが獲っちゃうような気がします。「Hello」良い曲だけどそこまで影響力のある楽曲とは思えないんですが。

 

予想:アデル

(希望:リアーナ)

 

 

 

Song Of The Year(最優秀楽曲賞)

"Formation" — Khalif Brown, Asheton Hogan, Beyoncé Knowles & Michael L. Williams II, songwriters (Beyoncé)
"Hello" — Adele Adkins & Greg Kurstin, songwriters (Adele)
"I Took A Pill In Ibiza" — Mike Posner, songwriter (Mike Posner)
"Love Yourself" — Justin Bieber, Benjamin Levin & Ed Sheeran, songwriters (Justin Bieber)
"7 Years" — Lukas Forchhammer, Stefan Forrest, Morten Pilegaard & Morten Ristorp, songwriters (Lukas Graham)

 

 これがレコード賞と違うのは、ソングライターやプロデューサーなど楽曲の制作者に与えられる賞だという点です。ノミネーションの中だと僕はビヨンセを推します。

が、なんとなく、ここもアデルが獲る気がします。ジャスティン・ビーバーのエド・シーランによるこの曲は弱いかな。マイク・ポスナーはなぜノミネートされているのかよくわかりません。

 

予想:アデル

(希望:ビヨンセ)

 

 

 

Best New Artist(最優秀新人賞)

Kelsea Ballerini
The Chainsmokers
Chance The Rapper
Maren Morris
Anderson .Paak

 

 チャンス・ザ・ラッパーに獲ってほしいです。CDリリース無し/ストリーミングオンリーのアーティストが受賞となると意義深いです。で、その話題性もあるので勢いでチャンスが獲ってしまうのでは、と予想します。

 新人賞は過去にカントリーの授賞もちらほら見受けられるので、ケルシー・バレリーニとマーレン・モリスも有力です。チェインスモーカーズとアンダーソン・パークはない気がします。

 

予想:チャンス・ザ・ラッパー

(希望:チャンス・ザ・ラッパー)

 

 

 

あと、授賞式でのパフォーマーリストも見ておきましょう。パフォーマーは以下のように発表されているのですが、

 

Adele
Kelsea Ballerini
Chance the Rapper
Katy Perry
Bruno Mars
Lady Gaga & Metallica
The Weeknd & Daft Punk
Maren Morris & Alicia Keys
Anderson .Paak & A Tribe Called Quest
Lukas Graham
Carrie Underwood & Keith Urban
Demi Lovato, Andra Day & Tori Kelly
Sturgill Simpson
John Legend & Cynthia Erivo
Little Big Town
Gary Clark Jr. & William Bell

 

 (特に主要部門に)今回ノミネートされたアーティストが不在なのが気になります。ビヨンセもリアーナもドレイクもビーバーもいない。代わりに、今回の賞レースとは無縁のポップスターが目立ちます。昨年フランク・オーシャンがグラミーのノミネーションへの拒否を表明していましたが、ブラック・ミュージシャンを中心にグラミー不信の流れがあるのでしょうか。それとも単に出演サイクルの問題か。授賞もやっぱりアデルが有利に働く気がしないでもないです。

 

 とはいえ、パフォーマンス単体で見れば楽しみなものもあります。ウィーケンド&ダフト・パンク、アンダーソン・パーク&トライブ・コールド・クエストが気になります。チャンスも楽しみ。ブルーノ・マーズやガガもパフォーマンス力が高いので安心して見られそうです。

 

 そして一番気になるのは、プリンスとジョージ・マイケルの追悼パフォーマンスの構成と誰が歌うかです。特にプリンスに関しては個人的に思い入れが強いので楽しみである反面、面子を見る限り適任がいるのかなとやや不安だったりします。

 

さて、今年のグラミー、どうなるでしょうか。授賞結果発表後にまたブログ更新します。

 

幻を追って

2018/03/02

01

D7100 18-105 f3.5-5.6をD7200と間違えた?

注文の中段くらいに行って,D7100だったんだ!?と

気がつきました,途端にキャンセル,そうだよD7200の

レンズキットが639980円なわけないしさ?この一件

以来懲りましてねえ.とうとうD7200をt注文したんだ

とさ.まいるよねえ,

02

Nikon D3200はお宝です?

これはすごくいいです.朱をもう1つ買いたいくらいです.

03

Nikon D3200とD3400

それほど差を感じることはなく,D3400はシャープが強い

ですねえ,

f:id:makisakouonuma:20170730110946j:plain

下町HIPHOPと言えば我らがDJ MASに、新作の評判もなかなか良さそうなブルテンが思い浮かぶ。バトルでもお馴染みのはなびも浅草だし、戸建てを購入したことで話題になった十影も葛飾だったりする。そこに名前を並べるのがQuronn-Lab.だ。

Quronn-Lab.

クーロンラボ。wikiによると「グッチ、EL-Bonobo、N.M.P、FL CHEPACINO、Extra=Caffeineの5人」「足立区や荒川区南千住、浅草、上野、門前仲町で普通に見かけることが出来る。」とのことだが、本当に下町で見かける。と言っても全員ってわけではなくってEL-Bonoboさんだけなのだけど、まあそんな下町レペゼンなHIPHOPユニット・クーロンラボが満を持して1stアルバム「未完成交響楽」をタワレコ限定で発売した。

いや、長かった。アナログやシングルなどは小出しで発売していたけど、それだってもう5年前のこと。なんて書いちゃうとあたかも昔から知っていたような口ぶりだけど全然そんなことはなかったりする。まあ、それくらいの時間を要して念入りに作り込まれたということだ。

未完成交響楽

というわけでさっそく聴いているんだけれど、やっぱり良い。なんといっても12inchで販売されたこともあるTribe。あのミスチフの名曲、93 Til Infinityを大胆にサンプリングしているんだけど、そのまま使ってるってわけじゃなくて、スタッカートっていうのかな、曲の冒頭で跳ねるようなアレンジを加えていてとっても今風。

youtu.be

他にも「罪と罰」や、「Voyager129」など過去に発売された曲や「Beautiful Life Remix」、「East Tokyo State of Mind Remix」などコンピに収録された曲もremixされて入っていてお得感満載なんだけど、新録の曲も中々の出来。下町ジャンベ集団勝気煙などのコラボ曲なんかインストにしとくのがもったいないと思うほど。
Opus One」や「Smoke In The Space Dub」もかっこいいんだけど、なんていうか全体的に古き良きHIPHOP感が漂っていて、Soul screamなどああいうのが好きな人は持っていて損はない一枚だと思う。あと「愛と友情と」っていうイメージにそぐわない(って失礼だな)タイトルのインストが入っていてびっくりしたんだけど、これも中々良かった。

でもやっぱりEast Tokyo State of Mind Remixはいいね。下町のHIPHOPカルチャーをレペゼンしてて知ってる名前がたくさん出てくるの。ニヤニヤしちゃう。


これだけ配信が主流になっているにも関わらず、タワレコ限定発売っていうのもこだわりを感じられる。しかも17曲も入っているのに手頃な1800円。そしてアートワークも下町でお馴染みのKaT〇Pe氏。ブルテンのあべともなりのEPもKaT〇P氏が手掛けているんだけど、タッチが違うので対比するのも面白い。土佐犬すっごい似てる。


5年以上の時間をかけてじっくりと作られたQuronn-Lab.の未完成交響楽、ぜひ聴いてもらいたい。

 

tower.jp

タイトル長くてごめんなさい!w

みなさん写真撮ってますかー?

旅先で印象に残る風景や光景を写真に残したいですよね。

使ってるのはスマホ?一眼レフ?デジカメ?

最近のスマホはカメラもほんとに高性能で素晴らしいです。

その写真をスマートフォンやカメラの中だけに収めてたらもったいないです。

写ルンですやチェキみたいにその場で手渡せたらみんなに喜ばれますよ。

いろんなメーカーからフォトプリンターが出ていて、ぼくもこの前ついに購入しました。

それがCanon プリンター SELPHY CP1200WH です。

お値段新品でなんと1万円ちょっと。

Canon プリンター SELPHY CP1200WH ホワイト

 

Canon プリンター SELPHY CP1200とは?

簡単に特徴を書いておきます。(後ほどそれぞれ記述します)

1.昇華型コンパクトプリンター

2.Wi-Fi接続が簡単・スピーディーなワンタッチWi-Fiボタンを搭載

3.持ち運びができ手軽に使えるコンパクトボディー対応サイズ:Lサイズ/ポストカード/カードサイズ

4.1枚あたりのプリント代金が格安

 

f:id:shinpsonkun:20170416185326j:plain

 

1.昇華型コンパクトプリンター 

昇華型とは熱によってインクを気化させてプリントすることです。

現在の主流とも言われています。しかもこのキャノンのセルフィーにはオーバーコート仕上げされていて、綺麗で長持ちします。

光沢感のある仕上がりで写真を水や汚れから守るとともに、色にじみや色あせも防止。大切な写真をキレイなまましっかり保存できる「アルバム保存100年」を実現、という素晴らしさです。

 

2.Wi-Fi接続が簡単・スピーディーなワンタッチWi-Fiボタンを搭載

スマートフォンやカメラにWi-Fi機能があれば、そこから直接ワンタッチでプリントできます。

専用アプリから写真を選んで、本体の印刷ボタンを押すだけ。

f:id:shinpsonkun:20170416190940j:plain

 

f:id:shinpsonkun:20170416191346j:plain

L版でプリント速度は40秒ほどです。

Wi-Fi設定がわからなくてもSDカードやUSBでパソコンと繋いでプリントも可能です。

 

f:id:shinpsonkun:20170416193558j:plain

3.持ち運びができ手軽に使えるコンパクトボディー対応サイズ:Lサイズ/ポストカード/カードサイズ

大きさは180.6(幅)×135.9(奥行き)×63.3(高さ)mmです。

重さは860gあり、若干重いけれど持ち運びは簡単です!

ぼくは保護目的もありケースも購入しました。

外出時にプリントしたいときは専用のバッテリーも必要です。

まあまあ高いけど。

でもこのバッテリーがないと屋内でしかプリントできません。

ちなみに本体の電圧は世界対応なので変圧器は必要ありません。

専用紙のプリント対応サイズも豊富なので気分で簡単に用紙の交換ができます。

 

4.1枚あたりのプリント代金が格安

1枚あたり30円もしません。街のプリント屋さんやコンビニだとさらに安いけど、旅先ですぐに渡せないですよね?

ぼくは旅で知り合った人にその場で写真を撮ってプリントしてあげたいと思ったので、この値段で満足です!

一眼レフのボカした写真を撮って、その人にプレゼントする。すっごい喜ばれますよ。

とくに家族連れだったり、赤ちゃんの写真をプレゼントするの最高です!

f:id:shinpsonkun:20170416193415j:plain

 

デメリットもある 

少し重いのと、バックパックなどに入れるとかさばる。

あと、専用紙にしかプリントできない。

例えばこのプリンターを年賀状印刷に考えてるなら不可能です。

修理代が高い。どんな故障でも一律8,100円。。。もう少しで新品が買えそうな値段。。

 

 

まとめ

デメリットもあるけれど、これだけの高品質なプリントがその場でできるのはかなり魅力的です。

1枚あたりの単価も安いですからね。 

写るんですやチェキなんかよりはるかに綺麗な写真が渡せますからね。

一眼レフやスマホの写真をぜひプリントしてみましょう。

もしバックパックに入れたい、より小さなフォトプリンターが欲しい人にはエレコムが販売している eprieがあります!

エレコム スマートフォン用プリンター モバイルフォトプリンター eprie本体 フォトシール【1カートリッジ 10枚】 写真用紙【1カートリッジ10枚】 初回フルセット ホワイト

EPR-PP01WWH

ぼくはこのエレコムのフォトプリンターと購入したキャノンのセルフィーと迷ったんですけどね。

こっちはほんとコンパクトですよ。写真は若干小さいのと、コストがキャノンのセルフィーより少し高いのがデメリットですが、より手軽さを求めるならこっちでも良いと思います!

一人旅でもすぐに友達ができるおすすめガジェットの紹介でした。

可愛さ求めるならチェキのフォトプリンターもありますよ!

 

揃えるものまとめ

本体

Canon プリンター SELPHY CP1200WH ホワイト

持ち運び用バッテリー 

専用紙(108枚入り・インク込み) 

ケース

これだけあれば大丈夫です!

 

にほんブログ村 海外生活ブログ カンボジア情報へ
にほんブログ村

正午の調布を、

 

人力車を引き颯爽と走るタクヤの姿、

 

一瞬だけ、4時台にV流れました●~*

 

あっ、調布駅前、拓也でーーーす!

 

本日最終始まるな!

 

・・・・・

 

「お子さんが多いですね~」

 

言い方。

 

なーんか、アナウンサー過ぎるなぁーーー(アナウンサーかっ)

 

明日は、

 

関東圏晴れ!

 

カラッとして、洗濯日和でーーーす●~*

 

 

それでは、せーーーの!

 

木村拓也の・・・・(ー_ー)!!

 

皆さん、バラバラやん(/_;)

 

ちょこちょこ拓也の様子を知りたい方は~

 

是非こちらへ●~*

開拓-kai・taku-日記 (木村拓也)- フジテレビ

 

 ★木村拓也アナ上を向いて歩こう!最新記事は、ブログ内カテゴリータっクヤぁーー!上を向いて歩こう!」でご確認できます。お手数かけますm(_ _"m)

typescriptlogo.png

※ 『[TypeScript] ImageData によるピクセル単位の描画』の続き。

前回は、HTML5 の Canvas に ImageData を作成してランダムなピクセルを描画した。

今回も同様にピクセル単位の描画を行ってみよう。少しだけ応用してマンデルブロ集合を描画してみる。

マンデルブロ集合

マンデルブロ集合は、フラクタルとして有名な図形だ。

詳しくは、次の場所が参考になる:

  • マンデルブロ集合の不思議な世界

HTML5 の Canvas にマンデルブロ集合を描画する

HTML5 の Canvas にピクセル単位の描画を行う方法については、前回を参考にしてほしい。

今回は、TypeScript の特長である「クラス設計のやり易さ」を活かすこととし、前回よりもきちんとクラス分けを行ってみたい。

先ず、前回同様の mandelbrot.html という HTML ファイルを用意する。 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Mandelbrot Sample</title>
    <script src="graph.js"></script>
    <script src="mandelbrot.js"></script>
</head>
<body onload="MandelbrotSample.MainProgram.run()">
    <canvas width="800" height="800"></canvas>
</body>
</html>
<!--
Usage:
    mandelbrot.html		                  : position = (-2.8, 2.0), scale = 4.0
    mandelbrot.html?posy=1&scale=2        : position = (-2.8, 1.0), scale = 2.0
    mandelbrot.html?posx=0&posy=0&scale=1 : position = ( 0.0, 0.0), scale = 1.0

    - This HTML can work with mandelbrot.js and graph.js online or offline.
-->

この HTML ファイルでは、graph.js と mandelbrot.js という2つの JavaScript ファイルを組み込んでいる。 それぞれ graph.ts と mandelbrot.ts いう TypeScript ファイルから生成されることになる。

onload="MandelbrotSample.MainProgram.run()" という記述があるが、このメソッドは mandelbrot.ts 内に用意する。

graph.ts

graph.ts は、Canvas にピクセル単位の描画を行うモジュールだ。

今回は、Canvas もクラス化してみよう。ピクセル毎に描画を行う部分もクラス化する。

また、座標、大きさ、矩形、色などの基本的なクラスもここに置くことにする。

module Graph {
    // 色
    export class Color {
        constructor(public red: number = 0x00, public green: number = 0x00, public blue: number = 0x00, public alpha: number = 0xff) { }
    }

    // 二次元ベクトル
    export class Vector {
        constructor(public x: number = 0.0, public y: number = 0.0) {}

        add(vector: Vector): Vector {
            return new Vector(this.x + vector.x, this.y + vector.y);
        }

        multiply(vector: Vector): Vector {
            return new Vector(this.x * vector.x, this.y * vector.y);
        }

        multiplyBy(value: number): Vector {
            return new Vector(this.x * value, this.y * value);
        }
    }

    // 二次元の大きさ
    export class Size {
        constructor(public width: number, public height: number) {}
    }

    // 矩形
    export class Rectangle {
        constructor(public position: Vector, public size: Size) {}
    }

    // ImageData への描画用
    class ImageDataHelper {
        // ImageData の指定した座標の 1 ピクセルを指定した色にする
        static setPixel(imageData: ImageData, position: Vector, color: Color) {
            // ImageData のサイズ
            var imageDataSize         = new Size(imageData.width, imageData.height);
            // 指定したピクセルの座標が有効でなかったら
            if (!ImageDataHelper.isValid(imageDataSize, position))
                return;

            // 指定した座標のピクセルが ImageData の data のどの位置にあるかを計算
            var index                 = ImageDataHelper.toIndex(imageDataSize, position);
            // その位置から、赤、緑、青、アルファ値の順で1バイトずつ書き込むことで、ピクセルがその色になる
            imageData.data[index + 0] = color.red  ;
            imageData.data[index + 1] = color.green;
            imageData.data[index + 2] = color.blue ;
            imageData.data[index + 3] = color.alpha;
        }

        // 指定したピクセルの座標が有効かどうか
        private static isValid(imageDataSize: Size, position: Vector): boolean {
            return position.x >= 0.0 && position.x <= imageDataSize.width  &&
                   position.y >= 0.0 && position.y <= imageDataSize.height;
        }

        // 指定した座標のピクセルが ImageData の data のどの位置にあるかを計算
        private static toIndex(imageDataSize: Size, position: Vector): number {
            return (position.x + position.y * imageDataSize.width) * 4;
        }
    }

    // Canvas に ImageData を置きピクセル毎に描画を行う
    export class Sheet {
        private context_  : CanvasRenderingContext2D;
        private imageData_: ImageData;

        get context() {
            return this.context_;
        }

        constructor(context: CanvasRenderingContext2D, size: Size) {
            this.context_   = context;
            this.imageData_ = context.createImageData(size.width, size.height);
        }

        // ImageData の指定した座標の 1 ピクセルを指定した色にする
        setPixel(position: Vector, color: Color) {
            ImageDataHelper.setPixel(this.imageData_, position, color);
        }

        // 指定した位置に ImageData を描画
        draw(position: Vector = new Vector()) {
            this.context.putImageData(this.imageData_, position.x, position.y);
        }
    }

    // キャンバス
    export class Canvas {
        private canvas_ : HTMLCanvasElement;
        private context_: CanvasRenderingContext2D;

        constructor() {
            this.canvas_  = <HTMLCanvasElement>document.querySelector("canvas");
            this.context_ = this.canvas_.getContext("2d");
        }

        get size(): Graph.Size {
            return Canvas.getCanvasSize(this.canvas_);
        }

        get position(): Graph.Rectangle {
            return new Graph.Rectangle(new Graph.Vector(), this.size);
        }

        get context(): CanvasRenderingContext2D {
            return this.context_;
        }

        private static getCanvasSize(canvas: HTMLCanvasElement): Graph.Size {
            return new Graph.Size(canvas.width, canvas.height);
        }
    }
}

mandelbrot.ts

mandelbrot.ts は、Canvas にマンデルブロ集合を描画する行うモジュールだ。

メイン プログラム、マンデルブロ集合、マンデルブロ集合を描画するときのパラメーター、そしてパラメーターをクエリ文字列から取得するためのユーティリティの各クラスからなる。

/// <reference path="graph.ts"/>

module MandelbrotSample {
    class Utility {
        // クエリ文字列から数を取得
        static getNumberFromQueryString(key: string): number {
            var queryString = Utility.getQueryString(key);
            if (queryString != "") {
                try {
                    return parseInt(queryString);
                } catch (ex) {}
            }
            return null;
        }
        
        // クエリ文字列の取得
        static getQueryString(key: string, default_: string = null): string {
            if (default_ == null)
                default_ = "";
            key             = key.replace(/[/, "[").replace(/[]]/, "]");
            var regex       = new RegExp("[?&]" + key + "=([^&#]*)");
            var queryString = regex.exec(window.location.href);
            return queryString == null ? default_ : queryString[1];
        }
    }

    // パラメーター
    class Parameter {
        position      : Graph.Vector = new Graph.Vector(-2.8, 2.0);
        maximum       : number       = 32;
        private scale_: number       = 4.0;

        get ratio(): number {
            return this.scale_ / this.size.width;
        }

        constructor(public size: Graph.Size) {
            this.setPositionX();
            this.setPositionY();
            this.setScale    ();
            this.setMaximum  ();
        }

        private setPositionX() {
            var positionX = Utility.getNumberFromQueryString("posx");
            if (positionX != null)
                this.position.x = positionX;
        }

        private setPositionY() {
            var positionY = Utility.getNumberFromQueryString("posy");
            if (positionY != null)
                this.position.y = positionY;
        }

        private setScale() {
            var scale = Utility.getNumberFromQueryString("scale");
            if (scale != null)
                this.scale_ = scale;
        }

        private setMaximum() {
            var maximum = Utility.getNumberFromQueryString("max");
            if (maximum != null)
                this.maximum = maximum;
        }
    }

    class Mandelbrot {
        private position_ : Graph.Vector;
        private sheet_    : Graph.Sheet;
        private parameter_: Parameter;

        constructor(context: CanvasRenderingContext2D, position: Graph.Rectangle, size: Graph.Size) {
            this.position_  = position.position;
            this.sheet_     = new Graph.Sheet(context, size);
            this.parameter_ = new Parameter(size);
        }

        draw(palette: Graph.Color) {
            var point = new Graph.Vector();
            for (point.y = 0; point.y < this.parameter_.size.height; point.y++) {
                for (point.x = 0; point.x < this.parameter_.size.width; point.x++) {
                    var a = this.parameter_.position.add(new Graph.Vector(point.x, -point.y).multiplyBy(this.parameter_.ratio));
                    this.setPixel(point, this.getCount(a), palette);
                }
            }
            this.sheet_.draw(this.position_);
        }

        private getCount(a: Graph.Vector): number {
            var squareBorder = 25.0;
            var square       = new Graph.Vector();
            var point        = new Graph.Vector();
            var count        = 0;
            do {
                point  = new Graph.Vector(square.x - square.y + a.x, 2.0 * point.x * point.y + a.y);
                square = point.multiply(point);
                count++;
            } while (square.x + square.y < squareBorder && count <= this.parameter_.maximum);
            return count < this.parameter_.maximum ? count : 0;
        }

        private setPixel(point: Graph.Vector, count: number, palette: Graph.Color) {
            this.sheet_.setPixel(point, palette[Mandelbrot.toColorIndex(count, palette.length)]);
        }

        private static toColorIndex(colorNumber: number, paletteSize: number): number {
            var colorIndexNumber = paletteSize * 2 - 2;
            var colorIndex       = colorNumber % colorIndexNumber;
            if (colorIndex >= paletteSize)
                colorIndex = colorIndexNumber - colorIndex;
            return colorIndex;
        }
    }

    export class MainProgram {
        static run() {
            var canvas     = new Graph.Canvas();
            var mandelbrot = new Mandelbrot(canvas.context, canvas.position, canvas.size);
            mandelbrot.draw(MainProgram.getPalette());
        }

        // パレット (予め色を格納しておき、パレット番号で色を参照)
        private static getPalette(): Graph.Color {
            return [
                new Graph.Color(0x02, 0x08, 0x80),
                new Graph.Color(0x10, 0x10, 0x70),
                new Graph.Color(0x20, 0x18, 0x60),
                new Graph.Color(0x30, 0x20, 0x50),
                new Graph.Color(0x40, 0x28, 0x40),
                new Graph.Color(0x50, 0x30, 0x30),
                new Graph.Color(0x60, 0x38, 0x20),
                new Graph.Color(0x70, 0x40, 0x10),
                new Graph.Color(0x80, 0x48, 0x0e),
                new Graph.Color(0x90, 0x50, 0x0c),
                new Graph.Color(0xa0, 0x58, 0x0a),
                new Graph.Color(0xb0, 0x60, 0x08),
                new Graph.Color(0xc0, 0x68, 0x06),
                new Graph.Color(0xd0, 0x70, 0x04),
                new Graph.Color(0xe8, 0x78, 0x02),
                new Graph.Color(0xff, 0x80, 0x01)
            ];
        }
    }
}

クラス図

以上のクラス構成を、クラス図で見てみよう。次のようになる。

クラス図
クラス図

TypeScript を使っている為に、このようなクラス設計は比較的容易だ。

実行例

では、実行してみよう。

コンパイルすると、graph.js と mandelbrot.js が生成される。

mandelbrot.html を Internet Explorer 9 以降等の HTML5 対応の Web ブラウザーで表示してみると、次のようにマンデルブロ集合が描画される。

mandelbrot.html
mandelbrot.html

実際のサンプルを次の場所に用意した。

  • mandelbrot.html

マンデルブロ集合のどこを描画するかを指定するパラメーターがクエリ文字列で渡せるようになっているので、次のようにして描画位置を変えることができる。

  • mandelbrot.html?posy=1&scale=2
  • mandelbrot.html?posx=0&posy=0&scale=1

C# で作成した例

比較の為に、同様のものを C# (Windows ストア アプリ) で作成してみよう。

Visual Studio でメニュー「新規作成」 - 「プロジェクト」から「Visual C#」 - 「Windows ストア」 - 「新しいアプリケーション (XAML)」で Windows ストア アプリを新規作成する。

App.xaml と App.xaml.cs には特に変更を加えない。

MainPage.xaml と MainPage.xaml.cs

謂わば mandelbrot.html にあたる部分。 TypeScript の場合同様、こちらも Canvas にイメージのオブジェクトを置き、描画する。

<Page
    x:Class="MandelbrotSample.WindowsStore.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MandelbrotSample.WindowsStore"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Loaded="Page_Loaded">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Canvas x:Name="canvas">
            <Image x:Name="image" />
        </Canvas>
        <ProgressRing x:Name="progress" Width="50" Height="50" Foreground="Blue" />
    </Grid>
</Page>
using MandelbrotSample.WindowsStore.Graph;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace MandelbrotSample.WindowsStore
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();
        }

        async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            await Run();
        }

        async Task Run()
        {
            var canvasPosition = new IntRectangle { Position = new IntVector(),
                                                    Size     = new IntSize { Width  = (int)canvas.ActualWidth ,
                                                                             Height = (int)canvas.ActualHeight } };

            progress.IsActive  = true ;
            await MainProgram.RunAsync(canvasPosition, image);
            progress.IsActive  = false;
        }
    }
}
Graph.cs

graph.ts にあたる部分は次のような感じ。

こちらでは、Palette はクラスにした。

また、TypeScript では number という型だったものは、int と double に分けた。

using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.UI;
using Windows.UI.Xaml.Media.Imaging;

namespace MandelbrotSample.WindowsStore.Graph
{
    public class Palette
    {
        readonly Color colors;

        public int Size
        {
            get { return colors.Length; }
        }

        public Palette(int size)
        { colors = new Color[size]; }

        public Color this[int index]
        {
            get
            {
                return index >= 0 && index < Size ? colors[index] : new Color();
            }
            set
            {
                if (index >= 0 && index < Size)
                    colors[index] = value;
            }
        }
    }

    public class Vector
    {
        public double X { get; set; }
        public double Y { get; set; }

        public static Vector operator +(Vector vector1, Vector vector2)
        {
            return new Vector { X = vector1.X + vector2.X, Y = vector1.Y + vector2.Y };
        }

        public static Vector operator -(Vector vector1, Vector vector2)
        {
            return new Vector { X = vector1.X - vector2.X, Y = vector1.Y - vector2.Y };
        }

        public static Vector operator *(Vector vector1, Vector vector2)
        {
            return new Vector { X = vector1.X * vector2.X, Y = vector1.Y * vector2.Y };
        }

        public static Vector operator *(Vector vector, double value)
        {
            return new Vector { X = vector.X * value, Y = vector.Y * value };
        }

        public static Vector operator /(Vector vector, double value)
        {
            return new Vector { X = vector.X / value, Y = vector.Y / value };
        }
    }

    public class IntVector
    {
        public int X { get; set; }
        public int Y { get; set; }

        public static IntVector operator -(IntVector vector, IntSize size)
        {
            return new IntVector { X = vector.X - size.Width, Y = vector.Y - size.Height };
        }
    }
    
    public class IntSize
    {
        public int Width  { get; set; }
        public int Height { get; set; }

        public static IntSize operator +(IntSize size1, IntSize size2)
        {
            return new IntSize { Width = size1.Width + size2.Width, Height = size1.Height + size2.Height };
        }

        public static IntSize operator *(IntSize size, IntVector vector)
        {
            return new IntSize { Width = size.Width * vector.X, Height = size.Height * vector.Y };
        }
    }

    public class IntRectangle
    {
        public IntVector Position { get; set; }
        public IntSize   Size     { get; set; }
    }

    public static class WriteableBitmapExtension
    {
        public static void Clear(this WriteableBitmap bitmap, Color color)
        {
            var arraySize = bitmap.PixelBuffer.Capacity;
            var array     = new byte[arraySize];
            for (var index = 0; index < arraySize; index += 4) {
                array[index    ] = color.B;
                array[index + 1] = color.G;
                array[index + 2] = color.R;
                array[index + 3] = color.A;
            }
            using (var pixelStream = bitmap.PixelBuffer.AsStream()) {
                pixelStream.Seek(0, SeekOrigin.Begin);
                pixelStream.Write(array, 0, array.Length);
            }
        }

        public static void SetPixel(this WriteableBitmap bitmap, int x, int y, Color color)
        {
            var bitmapWidth  = bitmap.PixelWidth;
            var bitmapHeight = bitmap.PixelHeight;
            if (!IsValid(bitmapWidth, bitmapHeight, x, y))
                return;
            var index = ToIndex(bitmapWidth, x, y);
            Debug.Assert(index >= 0 && index < bitmap.PixelBuffer.Capacity);

            using (var pixelStream = bitmap.PixelBuffer.AsStream()) {
                var array = new byte { color.B, color.G, color.R, color.A };
                pixelStream.Seek(index, SeekOrigin.Begin);
                pixelStream.Write(array, 0, array.Length);
            }
        }

        static int ToIndex(int bitmapWidth, int x, int y)
        {
            return (x + y * bitmapWidth) * 4;
        }

        static bool IsValid(int width, int height, int x, int y)
        {
            return x >= 0 && x < width  &&
                   y >= 0 && y < height;
        }
    }

    public class Sheet
    {
        public WriteableBitmap Bitmap { get; set; }

        public Sheet(IntSize size, Color backgroundColor = new Color())
        {
            Bitmap = new WriteableBitmap(size.Width, size.Height);
            Bitmap.Clear(backgroundColor);
        }

        public void SetPixel(IntVector position, Color color)
        { Bitmap.SetPixel(position.X, position.Y, color); }
    }
}
Mandelbrot.cs

mandelbrot.ts にあたる部分は次のような感じ。

TypeScript の run メソッドは、非同期の RunAsync とした。

using MandelbrotSample.WindowsStore.Graph;
using System;
using System.Threading.Tasks;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;

namespace MandelbrotSample.WindowsStore
{
    public class Mandelbrot
    {
        public class Parameter {
            public Vector    Position { get; private set; }
            public int       Maximum  { get; private set; }
            public IntSize   Size     { get; private set; }
            public double    Ratio    { get; private set; }

            public Parameter(IntSize size) : this(position: new Vector { X = -2.8, Y = 1.5 }, scale: 5.0, maximum: 32, size: size)
            {}

            public Parameter(Vector position, double scale, int maximum, IntSize size)
            {
                Position = position;
                Maximum  = maximum;
                Size     = size;
                Ratio    = scale / size.Width;
            }
        }

        const double       squareBorder = 25.0;

        readonly Sheet     sheet;
        readonly Parameter parameter;

        public WriteableBitmap Bitmap
        {
            get { return sheet.Bitmap; }
        }

        public Mandelbrot(IntRectangle position, Color backgroundColor = new Color())
        {
            sheet          = new Sheet(position.Size, backgroundColor);
            this.parameter = new Parameter(size: position.Size);
        }

        public Mandelbrot(IntRectangle position, Parameter parameter, Color backgroundColor = new Color())
        {
            sheet          = new Sheet(position.Size, backgroundColor);
            this.parameter = parameter;
        }

        public void Draw(Palette palette)
        {
            var point = new Graph.IntVector();
            for (point.Y = 0; point.Y < parameter.Size.Height; point.Y++) {
                for (point.X = 0; point.X < this.parameter.Size.Width; point.X++) {
                    var a = parameter.Position + new Vector { X = point.X, Y = -point.Y } * parameter.Ratio;
                    SetPixel(point, GetCount(a), palette);
                }
            }
        }

        int GetCount(Vector a)
        {
            var square = new Vector();
            var point  = new Vector();
            var count  = 0;
            do {
                point  = new Vector { X = square.X - square.Y + a.X, Y = 2.0 * point.X * point.Y + a.Y };
                square = point * point;
                count++;
            } while (square.X + square.Y < squareBorder && count <= parameter.Maximum);
            return count < parameter.Maximum ? count : 0;
        }

        void SetPixel(IntVector point, int count, Palette palette)
        {
            sheet.SetPixel(point, palette[ToColorIndex(count, palette.Size)]);
        }

        static int ToColorIndex(int colorNumber,  int paletteSize)
        {
            var colorIndexNumber = paletteSize * 2 - 2;
            var colorIndex       = colorNumber % colorIndexNumber;
            if (colorIndex >= paletteSize)
                colorIndex = colorIndexNumber - colorIndex;
            return colorIndex;
        }
    }

    class MainProgram
    {
        public static async Task RunAsync(IntRectangle canvasPosition, Image image)
        {
            await Window.Current.Dispatcher.RunIdleAsync(e => image.Source = DrawMandelbrot(canvasPosition));
        }

        static Palette GetPalette()
        {
            var palette = new Graph.Palette(16);
            palette[ 0] = new Color { R = 0x02, G = 0x08, B = 0x80 };
            palette[ 1] = new Color { R = 0x10, G = 0x10, B = 0x70 };
            palette[ 2] = new Color { R = 0x20, G = 0x18, B = 0x60 };
            palette[ 3] = new Color { R = 0x30, G = 0x20, B = 0x50 };
            palette[ 4] = new Color { R = 0x40, G = 0x28, B = 0x40 };
            palette[ 5] = new Color { R = 0x50, G = 0x30, B = 0x30 };
            palette[ 6] = new Color { R = 0x60, G = 0x38, B = 0x20 };
            palette[ 7] = new Color { R = 0x70, G = 0x40, B = 0x10 };
            palette[ 8] = new Color { R = 0x80, G = 0x48, B = 0x0e };
            palette[ 9] = new Color { R = 0x90, G = 0x50, B = 0x0c };
            palette[10] = new Color { R = 0xa0, G = 0x58, B = 0x0a };
            palette[11] = new Color { R = 0xb0, G = 0x60, B = 0x08 };
            palette[12] = new Color { R = 0xc0, G = 0x68, B = 0x06 };
            palette[13] = new Color { R = 0xd0, G = 0x70, B = 0x04 };
            palette[14] = new Color { R = 0xe8, G = 0x78, B = 0x02 };
            palette[15] = new Color { R = 0xff, G = 0x80, B = 0x01 };
            return palette;
        }

        static WriteableBitmap DrawMandelbrot(IntRectangle canvasPosition)
        {
            var mandelbrot = new Mandelbrot(position: canvasPosition, backgroundColor: Colors.MidnightBlue);
            mandelbrot.Draw(GetPalette());
            return mandelbrot.Bitmap;
        }
    }
}

実行結果もほぼ変わらない。

MandelbrotSample.WindowsStore
MandelbrotSample.WindowsStore

 


SP水曜劇場・SPナイトシアターで一週間にわたって放送させて頂いた小松利昌ソロコントライブ「コマツマツリ2006」のナイトシアター版のOP&ENDムービーをYou tubeにUP致しました!
放送をご覧になった方もご覧になってない方も是非御覧くださいませ。
この舞台映像はナイトシアターでは初めての自分の撮影編集の舞台映像だったので解説書きながら撮影当時のこととか色々思い出しました。
当時の舞台の熱気が少しでも伝われば幸いです♪

Tweet