1st version
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
build/
|
||||
|
||||
*.o
|
||||
*.a
|
||||
ptouch-print
|
||||
*.so
|
||||
*.dylib
|
||||
47
CMakeLists.txt
Normal file
47
CMakeLists.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
# ptouch_label — build (libptouch, ptouch-print)
|
||||
#
|
||||
# Author: knb
|
||||
# Email: knb@artif.org
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(ptouch_label VERSION 1.0.0 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBUSB REQUIRED IMPORTED_TARGET libusb-1.0)
|
||||
find_package(PNG REQUIRED)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/libptouch_version.h.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/libptouch_version.h"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
add_library(ptouch STATIC src/libptouch.c)
|
||||
target_include_directories(ptouch PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
)
|
||||
target_link_libraries(ptouch PRIVATE PkgConfig::LIBUSB PNG::PNG)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(ptouch PRIVATE -Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
add_executable(ptouch-print src/cli/main.c)
|
||||
target_include_directories(ptouch-print PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(ptouch-print PRIVATE ptouch PkgConfig::LIBUSB)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(ptouch-print PRIVATE -Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
install(TARGETS ptouch ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
install(TARGETS ptouch-print RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/libptouch.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/libptouch_version.h"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 ptouch_label contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
96
README.md
96
README.md
@@ -0,0 +1,96 @@
|
||||
# ptouch_label
|
||||
|
||||
**バージョン 1.0.0**(初回リリース)
|
||||
|
||||
Brother P-touch シリーズ向けのラベル印刷用 **C コアライブラリ(libptouch)** と、動作確認用 **CLI(`ptouch-print`)** のリポジトリです。
|
||||
|
||||
保有機種: **PT-P900W**(USB・ラスターコマンド)。
|
||||
|
||||
## レイアウト
|
||||
|
||||
| パス | 内容 |
|
||||
|------|------|
|
||||
| `include/libptouch.h` | 公開 API |
|
||||
| `src/libptouch.c` | ライブラリ本体(スタブ) |
|
||||
| `src/cli/main.c` | `ptouch-print` エントリ |
|
||||
| `samples/` | 試験用サンプル画像の置き場(PNG 等) |
|
||||
| `reference/` | 仕様・参考資料(例: ラスター PDF) |
|
||||
|
||||
## ビルド
|
||||
|
||||
依存: **CMake 3.16+**、**libusb-1.0**、**libpng**(開発パッケージ例: `libusb-1.0-0-dev`、`libpng-dev`)。
|
||||
|
||||
```bash
|
||||
cmake -S . -B build
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
成果物(`build/` 以下):
|
||||
|
||||
- `libptouch.a` — 静的ライブラリ
|
||||
- `ptouch-print` — CLI
|
||||
|
||||
## CLI の使い方(雛形)
|
||||
|
||||
**PNG**(拡張子 `.png` または PNG シグネチャ)の場合は幅・高さは画像から取得します。任意で `-t`(0–255)で二値化しきい値を指定できます。
|
||||
|
||||
**1bit packed ラスター**(行優先、行あたり `ceil(width/8)` バイト × 行数)の場合は `-f` に加え `-w` / `-H` が必須です。
|
||||
|
||||
印刷時、`libptouch_print_raster` は内部でラスターを**転置**してから送ります(`-T` / `-M` などのオプションはありません。鏡像のみの変換は行いません)。
|
||||
|
||||
```bash
|
||||
# PNG — 検証のみ(USB 不要)
|
||||
./build/ptouch-print -n -f label.png
|
||||
|
||||
# PNG — しきい値を指定
|
||||
./build/ptouch-print -n -f label.png -t 160
|
||||
|
||||
# 1bit ラスター — 検証のみ
|
||||
./build/ptouch-print -n -f sample.raster -w 128 -H 64
|
||||
|
||||
# プリンタステータス(テープ幅・種類・色・エラービット等、PDF の 32 バイト応答)
|
||||
./build/ptouch-print --status
|
||||
|
||||
# USB 接続時
|
||||
./build/ptouch-print -f label.png
|
||||
./build/ptouch-print -f sample.raster -w 128 -H 64
|
||||
```
|
||||
|
||||
`-n`(`--dry-run`)では読み込みと `libptouch_check_raster` まで実行します。
|
||||
|
||||
## libptouch API(概要)
|
||||
|
||||
- バージョン — `LIBPTOUCH_VERSION_MAJOR` / `MINOR` / `PATCH` / `LIBPTOUCH_VERSION_STRING`(`libptouch_version.h`、CMake の `project(VERSION …)` と同期)
|
||||
- `libptouch_create` / `libptouch_destroy` — コンテキスト
|
||||
- `libptouch_open_usb` / `libptouch_open_usb_vid_pid` / `libptouch_close` — USB(libusb・VID/PID)
|
||||
- `libptouch_get_status` / `libptouch_status_fprint` — ステータス情報リクエスト(ESC i S)の応答
|
||||
- `libptouch_check_raster` — ラスターバッファの検証のみ
|
||||
- `libptouch_png_file_to_raster` / `libptouch_free_raster` — PNG を 1bit ラスターに変換(libpng)
|
||||
- `libptouch_print_raster` — ラスター印刷(USB・PDF のコマンド列、内部で転置)
|
||||
- `libptouch_strerror` / `libptouch_last_error` — エラー情報
|
||||
|
||||
ラスター形式は `include/libptouch.h` のコメントに合わせてください。
|
||||
|
||||
## PT-P900W / Linux でのメモ
|
||||
|
||||
- 接続は **libusb-1.0** のみ。機種ごとに **VID/PID**(`lsusb` 等)を調べ、`libptouch_open_usb_vid_pid` に渡すか、既定の PT-P900W なら `libptouch_open_usb` を使います。
|
||||
- ラスターコマンドの詳細は **`reference/` の PDF** および Brother 公開資料に沿って `src/libptouch.c` に実装してください。
|
||||
|
||||
### Ubuntu で sudo なしで USB を開く(udev)
|
||||
|
||||
既定の **04f9:2085**(PT-P900W)向けルールを `udev/99-ptouch-label-brother.rules` に置いています。
|
||||
|
||||
```bash
|
||||
sudo cp udev/99-ptouch-label-brother.rules /etc/udev/rules.d/
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger
|
||||
sudo usermod -aG plugdev "$USER"
|
||||
```
|
||||
|
||||
**再ログイン**するか、端末で `newgrp plugdev` のあと試すか、USB を**抜き差し**してください。`groups` に `plugdev` が含まれていれば、`./build/ptouch-print --status` などを sudo なしで実行できます。
|
||||
|
||||
別の Brother 機種(別 PID)のときは、`lsusb` の ID に合わせて同ファイルに行を追加してください。
|
||||
|
||||
## ライセンス
|
||||
|
||||
[MIT License](LICENSE)(`LICENSE` ファイルを参照)。
|
||||
|
||||
128
include/libptouch.h
Normal file
128
include/libptouch.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* libptouch.h — public C API
|
||||
*
|
||||
* Author: knb
|
||||
* Email: knb@artif.org
|
||||
*/
|
||||
|
||||
/**
|
||||
* libptouch — Brother P-touch ラスター印刷 (USB) 用 C API
|
||||
*
|
||||
* 対象例: PT-P900W(ラスターコマンド)。実装は src/libptouch.c を参照。
|
||||
*/
|
||||
|
||||
#ifndef LIBPTOUCH_H
|
||||
#define LIBPTOUCH_H
|
||||
|
||||
#include "libptouch_version.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** 不透明コンテキスト(接続状態・最終エラー文字列を保持) */
|
||||
typedef struct libptouch_ctx libptouch_ctx;
|
||||
|
||||
typedef enum {
|
||||
LIBPTOUCH_OK = 0,
|
||||
LIBPTOUCH_ERR_NOMEM = 1,
|
||||
LIBPTOUCH_ERR_ARG = 2,
|
||||
LIBPTOUCH_ERR_USB = 3,
|
||||
LIBPTOUCH_ERR_IO = 4,
|
||||
LIBPTOUCH_ERR_UNSUPPORTED = 5,
|
||||
LIBPTOUCH_ERR_NOT_FOUND = 6,
|
||||
LIBPTOUCH_ERR_IMAGE = 7,
|
||||
} libptouch_err_t;
|
||||
|
||||
/** lsusb 例: PT-P900W — Brother Industries, Ltd (04f9:2085) */
|
||||
#define LIBPTOUCH_USB_VID_BROTHER 0x04f9u
|
||||
#define LIBPTOUCH_USB_PID_PTP900W 0x2085u
|
||||
|
||||
libptouch_ctx *libptouch_create(void);
|
||||
void libptouch_destroy(libptouch_ctx *ctx);
|
||||
|
||||
/** 人が読める英語メッセージ(スレッド非安全: ctx ごと) */
|
||||
const char *libptouch_strerror(const libptouch_ctx *ctx);
|
||||
libptouch_err_t libptouch_last_error(const libptouch_ctx *ctx);
|
||||
|
||||
/**
|
||||
* USB でプリンタを開く(VID/PID で先頭の一致デバイスを開く。libusb のみ)。
|
||||
*/
|
||||
libptouch_err_t libptouch_open_usb_vid_pid(libptouch_ctx *ctx, uint16_t vid,
|
||||
uint16_t pid);
|
||||
|
||||
/**
|
||||
* 既定機種(@ref LIBPTOUCH_USB_VID_BROTHER / @ref LIBPTOUCH_USB_PID_PTP900W)を開く。
|
||||
* 別機種は @ref libptouch_open_usb_vid_pid に機種ごとの VID/PID を渡す。
|
||||
*/
|
||||
libptouch_err_t libptouch_open_usb(libptouch_ctx *ctx);
|
||||
|
||||
void libptouch_close(libptouch_ctx *ctx);
|
||||
|
||||
typedef struct {
|
||||
uint32_t width_dots; /**< ラスター幅(ドット) */
|
||||
uint32_t height_dots; /**< ラスター高さ(ドット・走査方向は実装と機種に依存) */
|
||||
uint8_t margin_mm; /**< 余白など(機種・仕様に合わせて使用) */
|
||||
} libptouch_raster_params_t;
|
||||
|
||||
/**
|
||||
* バッファサイズとパラメータの整合性のみ検査(USB 不要)。--dry-run 用。
|
||||
*/
|
||||
libptouch_err_t libptouch_check_raster(libptouch_ctx *ctx,
|
||||
const uint8_t *data, size_t data_len,
|
||||
const libptouch_raster_params_t *params);
|
||||
|
||||
/**
|
||||
* 1 ビット packed ラスターを USB で印刷(cv_ptp900_jpn_raster_102.pdf 準拠)。
|
||||
* 印字前にステータスでテープ幅を読み、印刷可能ドット内に画像を中央配置する。
|
||||
* width_dots は装着テープの印刷可能幅以下であること。360dpi 相当のドット列を想定。
|
||||
* @param margin_mm 余白(フィード)量。0 のとき PDF の最小 1mm(14 ドット)相当を送る。
|
||||
* 印刷時は内部でドット列を転置する(テープ幅方向とバッファの縦横の対応)。
|
||||
* @param data 1 行あたり width_dots ビットを ceil(width_dots/8) バイトで並べた連続領域
|
||||
* @param data_len 期待値: height * row_bytes, row_bytes = (width_dots + 7) / 8
|
||||
*/
|
||||
libptouch_err_t libptouch_print_raster(libptouch_ctx *ctx,
|
||||
const uint8_t *data, size_t data_len,
|
||||
const libptouch_raster_params_t *params);
|
||||
|
||||
/** 二値化の既定しきい値(輝度 0–255、これ未満を黒ドット) */
|
||||
#define LIBPTOUCH_PNG_DEFAULT_THRESHOLD 128u
|
||||
|
||||
typedef struct {
|
||||
uint8_t threshold; /**< 輝度がこれ未満なら黒(1)、以上なら白(0) */
|
||||
} libptouch_png_options_t;
|
||||
|
||||
/**
|
||||
* PNG ファイルを読み、1bit packed ラスターに変換する(libpng)。
|
||||
* @param out_raster malloc 済みバッファのポインタを返す。不要時は @ref libptouch_free_raster で解放。
|
||||
*/
|
||||
libptouch_err_t libptouch_png_file_to_raster(libptouch_ctx *ctx, const char *path,
|
||||
const libptouch_png_options_t *options,
|
||||
uint8_t **out_raster, size_t *out_raster_bytes,
|
||||
libptouch_raster_params_t *out_params);
|
||||
|
||||
void libptouch_free_raster(uint8_t *raster);
|
||||
|
||||
/** ステータス情報リクエスト(ESC i S)の応答バイト数(cv_ptp900_jpn_raster_102.pdf) */
|
||||
#define LIBPTOUCH_STATUS_LENGTH 32u
|
||||
|
||||
/**
|
||||
* プリンタからステータスを読む(USB オープン済みであること)。
|
||||
* 送信: 初期化 ESC @ のあと ESC i S。応答は @ref LIBPTOUCH_STATUS_LENGTH バイト固定。
|
||||
*/
|
||||
libptouch_err_t libptouch_get_status(libptouch_ctx *ctx,
|
||||
uint8_t *status /* length @ref LIBPTOUCH_STATUS_LENGTH */);
|
||||
|
||||
/** ステータス 32 バイトを人が読める形で出力(テープ幅・種類・色など) */
|
||||
void libptouch_status_fprint(FILE *fp,
|
||||
const uint8_t *status /* length @ref LIBPTOUCH_STATUS_LENGTH */);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBPTOUCH_H */
|
||||
17
include/libptouch_version.h.in
Normal file
17
include/libptouch_version.h.in
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* libptouch_version.h — generated from this template by CMake
|
||||
*
|
||||
* Author: knb
|
||||
* Email: knb@artif.org
|
||||
*/
|
||||
|
||||
#ifndef LIBPTOUCH_VERSION_H
|
||||
#define LIBPTOUCH_VERSION_H
|
||||
|
||||
/** リリースバージョン(CMake project(VERSION …) と同期) */
|
||||
#define LIBPTOUCH_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||
#define LIBPTOUCH_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||
#define LIBPTOUCH_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||
#define LIBPTOUCH_VERSION_STRING "@PROJECT_VERSION@"
|
||||
|
||||
#endif
|
||||
BIN
reference/cv_ptp900_jpn_raster_102.pdf
Normal file
BIN
reference/cv_ptp900_jpn_raster_102.pdf
Normal file
Binary file not shown.
9
samples/README.md
Normal file
9
samples/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# samples
|
||||
|
||||
試験・デモ用のサンプル画像(PNG など)を置くディレクトリです。リポジトリに含める場合はライセンス・著作権に注意してください。
|
||||
|
||||
例(ドライラン):
|
||||
|
||||
```bash
|
||||
./build/ptouch-print -n -f samples/your.png
|
||||
```
|
||||
292
src/cli/main.c
Normal file
292
src/cli/main.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* ptouch-print — CLI for libptouch
|
||||
*
|
||||
* Author: knb
|
||||
* Email: knb@artif.org
|
||||
*/
|
||||
|
||||
#include "libptouch.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
static void usage(const char *argv0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [options]\n"
|
||||
" -f, --file PATH 入力ファイル\n"
|
||||
" -w, --width DOTS 1bit ラスター時: 幅(ドット)\n"
|
||||
" -H, --height DOTS 1bit ラスター時: 高さ(ドット)\n"
|
||||
" -t, --threshold N PNG 二値化しきい値 0–255(既定 %u、PNG のみ)\n"
|
||||
" -n, --dry-run 読み込みと check_raster のみ(USB なし)\n"
|
||||
" -S, --status USB 接続プリンタのステータス(テープ種・幅・色等)を表示して終了\n"
|
||||
" -V, --version バージョンを表示して終了\n"
|
||||
" -h, --help このヘルプ\n"
|
||||
"\n"
|
||||
"PNG の場合は幅・高さはファイルから取得(-w/-H 不要)。\n"
|
||||
"1bit packed ラスター(行優先)の場合は -f -w -H が必須。\n"
|
||||
"--status のときは -f は不要(他オプションは無視されます)。\n",
|
||||
argv0, (unsigned)LIBPTOUCH_PNG_DEFAULT_THRESHOLD);
|
||||
}
|
||||
|
||||
/** パスが .png で終わる、または先頭 8 バイトが PNG シグネチャ */
|
||||
static int input_is_png(const char *path)
|
||||
{
|
||||
const char *dot = strrchr(path, '.');
|
||||
if (dot && strcasecmp(dot, ".png") == 0)
|
||||
return 1;
|
||||
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if (!fp)
|
||||
return 0;
|
||||
unsigned char sig[8];
|
||||
size_t n = fread(sig, 1, sizeof(sig), fp);
|
||||
fclose(fp);
|
||||
if (n != sizeof(sig))
|
||||
return 0;
|
||||
static const unsigned char png_magic[8] = { 137, 80, 78, 71,
|
||||
13, 10, 26, 10 };
|
||||
return memcmp(sig, png_magic, sizeof(png_magic)) == 0;
|
||||
}
|
||||
|
||||
static int read_file(const char *path, uint8_t **out, size_t *out_len)
|
||||
{
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "open %s: %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||
fprintf(stderr, "fseek: %s\n", strerror(errno));
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
long sz = ftell(fp);
|
||||
if (sz < 0) {
|
||||
fprintf(stderr, "ftell: %s\n", strerror(errno));
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
rewind(fp);
|
||||
uint8_t *buf = malloc((size_t)sz);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
size_t n = fread(buf, 1, (size_t)sz, fp);
|
||||
fclose(fp);
|
||||
if (n != (size_t)sz) {
|
||||
fprintf(stderr, "short read\n");
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
*out = buf;
|
||||
*out_len = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *file = NULL;
|
||||
unsigned width = 0, height = 0;
|
||||
unsigned threshold = LIBPTOUCH_PNG_DEFAULT_THRESHOLD;
|
||||
int dry_run = 0;
|
||||
int has_threshold = 0;
|
||||
int want_status = 0;
|
||||
static struct option longopts[] = {
|
||||
{ "width", required_argument, NULL, 'w' },
|
||||
{ "height", required_argument, NULL, 'H' },
|
||||
{ "file", required_argument, NULL, 'f' },
|
||||
{ "threshold", required_argument, NULL, 't' },
|
||||
{ "dry-run", no_argument, NULL, 'n' },
|
||||
{ "status", no_argument, NULL, 'S' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "w:H:f:t:nhSV", longopts, NULL)) !=
|
||||
-1) {
|
||||
switch (c) {
|
||||
case 'w':
|
||||
width = (unsigned)strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'H':
|
||||
height = (unsigned)strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'f':
|
||||
file = optarg;
|
||||
break;
|
||||
case 't':
|
||||
threshold = (unsigned)strtoul(optarg, NULL, 10);
|
||||
if (threshold > 255u) {
|
||||
fprintf(stderr, "-t must be 0..255\n");
|
||||
return 2;
|
||||
}
|
||||
has_threshold = 1;
|
||||
break;
|
||||
case 'n':
|
||||
dry_run = 1;
|
||||
break;
|
||||
case 'S':
|
||||
want_status = 1;
|
||||
break;
|
||||
case 'V':
|
||||
printf("ptouch-print %s\n", LIBPTOUCH_VERSION_STRING);
|
||||
return 0;
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (want_status) {
|
||||
if (file || width || height || dry_run || has_threshold)
|
||||
fprintf(stderr,
|
||||
"warning: options other than --status are ignored\n");
|
||||
|
||||
libptouch_ctx *sctx = libptouch_create();
|
||||
if (!sctx) {
|
||||
fprintf(stderr, "libptouch_create failed\n");
|
||||
return 1;
|
||||
}
|
||||
libptouch_err_t se = libptouch_open_usb(sctx);
|
||||
if (se != LIBPTOUCH_OK) {
|
||||
fprintf(stderr, "open_usb: %s\n", libptouch_strerror(sctx));
|
||||
libptouch_destroy(sctx);
|
||||
return 1;
|
||||
}
|
||||
uint8_t st[LIBPTOUCH_STATUS_LENGTH];
|
||||
se = libptouch_get_status(sctx, st);
|
||||
if (se != LIBPTOUCH_OK) {
|
||||
fprintf(stderr, "get_status: %s\n", libptouch_strerror(sctx));
|
||||
libptouch_close(sctx);
|
||||
libptouch_destroy(sctx);
|
||||
return 1;
|
||||
}
|
||||
libptouch_status_fprint(stdout, st);
|
||||
libptouch_close(sctx);
|
||||
libptouch_destroy(sctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
fprintf(stderr, "-f is required (or use --status)\n");
|
||||
usage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int png = input_is_png(file);
|
||||
if (png) {
|
||||
if (width != 0 || height != 0)
|
||||
fprintf(stderr,
|
||||
"warning: -w/-H ignored for PNG (using image size)\n");
|
||||
} else {
|
||||
if (width == 0 || height == 0) {
|
||||
fprintf(stderr,
|
||||
"1bit raster requires -w and -H (or use a PNG file)\n");
|
||||
usage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
if (has_threshold)
|
||||
fprintf(stderr,
|
||||
"warning: -t applies to PNG only (ignored)\n");
|
||||
}
|
||||
|
||||
libptouch_ctx *ctx = libptouch_create();
|
||||
if (!ctx) {
|
||||
fprintf(stderr, "libptouch_create failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t *data = NULL;
|
||||
size_t data_len = 0;
|
||||
libptouch_raster_params_t params = { 0, 0, 0 };
|
||||
libptouch_err_t e;
|
||||
|
||||
if (png) {
|
||||
libptouch_png_options_t opt = { .threshold = (uint8_t)threshold };
|
||||
e = libptouch_png_file_to_raster(ctx, file,
|
||||
has_threshold ? &opt : NULL,
|
||||
&data, &data_len, ¶ms);
|
||||
if (e != LIBPTOUCH_OK) {
|
||||
fprintf(stderr, "png_file_to_raster: %s\n",
|
||||
libptouch_strerror(ctx));
|
||||
libptouch_destroy(ctx);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (read_file(file, &data, &data_len) != 0) {
|
||||
libptouch_destroy(ctx);
|
||||
return 1;
|
||||
}
|
||||
params.width_dots = width;
|
||||
params.height_dots = height;
|
||||
params.margin_mm = 0;
|
||||
}
|
||||
|
||||
e = libptouch_check_raster(ctx, data, data_len, ¶ms);
|
||||
if (e != LIBPTOUCH_OK) {
|
||||
fprintf(stderr, "check_raster: %s\n",
|
||||
libptouch_strerror(ctx));
|
||||
libptouch_destroy(ctx);
|
||||
if (png)
|
||||
libptouch_free_raster(data);
|
||||
else
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dry_run) {
|
||||
printf("dry-run OK: %zu bytes, %ux%u dots\n", data_len,
|
||||
(unsigned)params.width_dots,
|
||||
(unsigned)params.height_dots);
|
||||
libptouch_destroy(ctx);
|
||||
if (png)
|
||||
libptouch_free_raster(data);
|
||||
else
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
e = libptouch_open_usb(ctx);
|
||||
if (e != LIBPTOUCH_OK) {
|
||||
fprintf(stderr, "open_usb: %s\n", libptouch_strerror(ctx));
|
||||
libptouch_destroy(ctx);
|
||||
if (png)
|
||||
libptouch_free_raster(data);
|
||||
else
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
e = libptouch_print_raster(ctx, data, data_len, ¶ms);
|
||||
if (e != LIBPTOUCH_OK) {
|
||||
fprintf(stderr, "print_raster: %s\n",
|
||||
libptouch_strerror(ctx));
|
||||
libptouch_close(ctx);
|
||||
libptouch_destroy(ctx);
|
||||
if (png)
|
||||
libptouch_free_raster(data);
|
||||
else
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
libptouch_close(ctx);
|
||||
libptouch_destroy(ctx);
|
||||
if (png)
|
||||
libptouch_free_raster(data);
|
||||
else
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
1164
src/libptouch.c
Normal file
1164
src/libptouch.c
Normal file
File diff suppressed because it is too large
Load Diff
16
udev/99-ptouch-label-brother.rules
Normal file
16
udev/99-ptouch-label-brother.rules
Normal file
@@ -0,0 +1,16 @@
|
||||
# Brother P-touch — libusb でユーザから開けるようにする (Ubuntu 等)
|
||||
# PT-P900W: lsusb で ID 04f9:2085
|
||||
#
|
||||
# 設置:
|
||||
# sudo cp udev/99-ptouch-label-brother.rules /etc/udev/rules.d/
|
||||
# sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||
# sudo usermod -aG plugdev "$USER"
|
||||
# 再ログインするか USB を抜き差しする
|
||||
#
|
||||
# TAG+=uaccess … systemd-logind がアクティブセッションに ACL を付与(デスクトップ向け)
|
||||
# GROUP=plugdev … 従来どおり plugdev に所属していれば読み書き可
|
||||
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="04f9", ATTR{idProduct}=="2085", MODE="0660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# 他機種を使う場合は lsusb の ID を足す例(コメントを外して複製):
|
||||
# SUBSYSTEM=="usb", ATTR{idVendor}=="04f9", ATTR{idProduct}=="2086", MODE="0660", GROUP="plugdev", TAG+="uaccess"
|
||||
Reference in New Issue
Block a user