Sマウントとは
「Sマウント」と言っても、戦後から1950年代ごろまで製造されたニコンのレンズマウントのことではありません。そっちはそっちで面白そうですが、脱線は我慢。工業用とか、監視カメラ用の小型の規格です。「M12マウント」(内径が12mm)とも呼ばれるようです。

Sマウントのカメラで撮影する

矢野です。小石川オフィスに引っ越してきて、1か月あまりが経ちました。小石川や、それに近い西片・本郷界隈は起伏が激しくて入り組んだ道が多く、引っ越し直後はランチの後にちょっと散歩するとすぐに迷子になっていたものです。それでもだんだんと脳内の地図が整理されてきて、かなり歩きやすくなってきました。
ちょっとググってみると、「ドリフト走行などで路面にできるタイヤの黒い跡」とか「汚点」とか、今年公開のそういうアクション映画があるとか、色々出てきます。ですが、私たちが扱っているブラックマークとは、「印刷用紙の裏側の黒い印」のことです。
ブラックマークの例。用紙を横切るような帯状のものや、紙面の中央に四角く描かれたものなど。
生産管理に使用する小さなラベルや完成品をお届けするための配送伝票などのシールの台紙となる剥離紙の裏側に印刷されている黒い印や帯のことです。シールとして貼る際に捨てられてしまうので、お客様の目に触れることはありません。いわば縁の下の力持ちですね。
私たちが取り扱うラベルプリンターには印字ヘッドの近くに光学式のセンサーが内蔵されていて、それで台紙の裏側をスキャンできます。ブラックマークを検知するまでは用紙を送り出して、検知したところで位置合わせ。そこから印刷を始めて、1枚分印刷できたら台紙ごとカットする(これもプリンターに内蔵されたカッターがやってくれます)。1枚ごとの長さが決まっているロール式のラベルを正確に取り扱うための、重要なマークです。
と、ある程度取り扱えるようになってから言うのは簡単ですが、プリンターと用紙がそれぞれ専用の組み合わせでない場合は、用紙の向き、サイズ、光学センサーの位置、検知の方式(透過式? 反射式?)、マークからの相対的な位置の設定などなど、いろいろな苦闘がありました。用紙のフィードがいつまでも止まらなかったり、おかしなところでちょん切られたり……。
形のないソフトウェアの世界と、プリンターやRFIDリーダーなどのハードウェア、印刷メディアなどの間を行ったり来たりしながら、私たちは開発の仕事をしています。
こんにちは、イメージ・マジックの矢野です。入社から2か月が経過し、順調に机の上がゴチャゴチャしてきました。カメラが2台、バーコードプリンターが2台、小さなスピーカーが1台、さらにカードリーダーが1台、デスクの上に転がっています。
当社が印刷しているのは、Tシャツやパーカー、マグカップ、カーペットなどの製品そのものももちろんですが、それだけではお客様のお手元に製品を届けることはできません。生産工程でそれらを管理するためのラベルシールや、納品書、配送業者さんにお願いする送り状なども自社のシステムで印刷しています。当然といえば当然なのですが。
ラベルシールの印刷には、専用のプリンターを使用しています。私は転職してきて初めて触りました。ずんぐりむっくりでかわいい形ですが、言うことを聞かせるのはなかなか難しいです。プリンター専用のツールやライブラリを使ってバーコードや文字列や画像を出力するように指示することもできますが、プリンターの制御用コマンドを直接(「直接」とは言っても、通り抜けなければならないレイヤーは多数あります)送信することもできます。
ところで、「プリンターで何かを印刷する」というのはどういうことなのでしょう? それは文字列や画像、バーコードを印刷しなさいというコマンドの積み重ねです。ラベルシールにバーコードを印刷する場合には、最終的にたくさんのしましまが紙面に出力されるようなコマンドをアプリケーションで生成して、それをプリンターに送信する必要があるわけです。
たくさんのしましまを、どうやってプリンターに送信しましょうか?
1も2も3も正解ですが、1は特に厳しい。バーコードの仕様に従って、1本1本のしましまの太さと間隔をどうにかこうにかしなければなりません。2は割とよくあると思います。バーコード画像を生成するライブラリを使用すれば、割とサクっとできるでしょう。でも、せっかく専用のプリンターを使っているのですから、彼(彼女?)に任せてしまってみましょう。
Windowsで、Win32 APIを使って実装してみます。プリンターによろしくやってもらう代わりに、プリンター固有のお作法に従わなくてはなりません。ここでは、Zebra Technologies社のプリンタ向け言語、ZPL(Zebra Programming Language)のコマンドを実行しています。
int PrintRawCommand() { HANDLE hPrinter; if (!OpenPrinter((LPSTR)"Printer Name", &hPrinter, NULL)) { // エラー処理 return FALSE; } DOC_INFO_1 docInfo; docInfo.pDocName = (LPSTR)"Barcode sample"; docInfo.pOutputFile = NULL; docInfo.pDatatype = (LPSTR)"RAW"; LPSTR command = (LPSTR)"^XA^FO40,40^BY3^BEN,40,Y,N^FD123456789012^FS^XZ"; if (StartDocPrinter(hPrinter, 1, (LPBYTE)&docInfo)) { if (StartPagePrinter(hPrinter)) { DWORD writtenBytes; if (WritePrinter(hPrinter, command, strlen(command), &writtenBytes)) { // 印刷成功時の処理 } else { // エラー処理 return FALSE; } } else { // エラー処理 return FALSE; } } else { // エラー処理 return FALSE; } EndPagePrinter(hPrinter); EndDocPrinter(hPrinter); ClosePrinter(hPrinter); return TRUE; }
15行目で、プリンタへ送信するデータの形式をRAW(生=Zebraのプリンターが解するコマンドを直接送信する)に指定します。17行目の文字列が実際にプリンタへ送信されるZPLのコマンドです。レイアウト、フィールド、バーコードの表現形式(EAN-13)、バーコード化したいデータ(123456789012)などを、 ^
で始まるコマンドで指定します。
これの出力結果がこうなります。
EAN-13の詳細な仕様を隅々まで探らなくても、難しい画像操作系のAPIを駆使しなくても、美しいバーコードを得ることができました。
こんにちは。イメージ・マジックの矢野です。入社からもうすぐ1か月です。
Node.jsのアドオンを、何らかの理由でネイティブのコードで書かなければならないことがあります。Node.jsのエンジンであるV8のお作法に則って書くことになりますが、V8がバージョンアップして仕様が変われば、そのお作法も変わります。お作法が変わればアドオンの書き方も変えなければならず、毎度毎度書き直すのは大変。そこで、Node.jsのネイティブなアドオンの実装をイイ感じにラップして抽象化してくれる、NAN(Native Abstractions for Node.js)というものがつくられたとのこと(READMEの冒頭を読むと、クスリとさせられます)。もちろんNANを使わなくてむ作れるわけですが、せっかく便利なものがあるのですから、使わない手はありません。
Node.jsのアドオンをつくるのですから、当然Node.jsはインストールされていないといけません。
NANはnode-gypでビルドするため、node-gypもインストールしておかなければいけません。さらにgypはPythonスクリプトなので、Pythonが入っていなければインストールしておかなければなりません。
ネイティブコードをビルドするために、コンパイラなども必要です。今回はWindowsを使って開発しているので、Visual Studio 2017をインストールしておきます。
準備ができたところで、作業用のディレクトリを作成します。
mkdir hoge cd hoge
NANをインストールします。
npm install --save nan
binding.gyp
を作成します。このテキストファイルには、アドオンの構成を記述します。ネイティブならではのアドオンをばっちり作り込むのはそれなりに大変なので、今回はOSのバージョンを取得するだけの簡単なものにしようと思います。
{ "targets": [ { "target_name": "getosversion", "sources": [ "src/addon.cpp", ], "include_dirs": [ "<!(node -e \"require('nan')\")", ], } ] }
ソースファイルを格納するディレクトリ(src)をつくり、ソースファイルを形だけでも(空ファイルでOK)つくっておきます(src/addon.cpp)。
node-gyp
でconfigure
すると、上記の構成に従ってVisual StudioのC++プロジェクトやソリューションを生成してくれます。
node-gyp configure
build
ディレクトリの下にいろいろファイルができています。
│ binding.gyp │ ├─build │ binding.sln │ config.gypi │ getosversion.vcxproj │ getosversion.vcxproj.filters │ └─src addon.cpp
binding.sln
を開くと、Visual Studioが起動しますので、addon.cppの中身を書いていきます。NANの恩恵を受けるには、ヘッダファイルnan.h
をincludeしておく必要があります。
Win32 APIのGetVersion()
を呼び出して、OSのバージョン情報を取得してみます。ちなみにこの関数は現在「非推奨」になっていますが、Win32がメインの記事ではないので、そのまま使ってしまいます(業務ではこんなことしませんよ)。
#include <sstream> #include <nan.h> NAN_METHOD(GetOsVersion) { DWORD dwVersion = GetVersion(); DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); DWORD dwBuild = 0; if (dwVersion < 0x80000000) { dwBuild = (DWORD)(HIWORD(dwVersion)); } std::stringstream ss; ss << dwMajorVersion << "." << dwMinorVersion << "." << dwBuild; info.GetReturnValue().Set(Nan::New<v8::String>(ss.str()).ToLocalChecked()); } NAN_MODULE_INIT(init) { Nan::SetMethod(target, "GetOsVersion", GetOsVersion); } NODE_MODULE(getosversion, init)
ビルドします。
node-gyp build
もろもろビルドされます。肝心のアドオンは、build/Release/getosversion.node
として生成されます。
│ binding.gyp │ ├─build │ │ binding.sln │ │ config.gypi │ │ getosversion.vcxproj │ │ getosversion.vcxproj.filters │ │ │ └─Release │ │ getosversion.exp │ │ getosversion.iobj │ │ getosversion.ipdb │ │ getosversion.lib │ │ getosversion.map │ │ getosversion.node │ │ getosversion.pdb │ │ │ └─obj │ └─getosversion │ │ addon.obj │ │ vc141.pdb │ │ win_delay_load_hook.obj │ │ │ └─getosversion.tlog │ ... (省略) ... │ └─src addon.cpp
これを実際に動かしてみましょう。テスト用コードをこんな感じで書いてみます(test.js
)。
var addon = require('./build/Release/getosversion'); var version = addon.GetOsVersion(); console.log(result);
node
コマンドから実行してみると、それらしい値が取れました。
node test.js 10.0.16299