#!/bin/bash # SmallClaw Image Editing Dependencies Installer # Run: bash scripts/install-image-deps.sh [--with-rembg] # # --with-rembg AI 배경 제거(rembg) 설치 (~500MB onnxruntime 포함) set -e WITH_REMBG=false for arg in "$@"; do [ "$arg" = "--with-rembg" ] && WITH_REMBG=true done GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' ok() { echo -e " ${GREEN}✓${NC} $1"; } skip() { echo -e " ${YELLOW}↷${NC} $1 (already installed)"; } echo "=== SmallClaw Image Dependencies Installer ===" echo "" # ────────────────────────────────────────────────── # 1. 시스템 패키지 # ────────────────────────────────────────────────── echo "[1/4] 시스템 패키지 (apt)" APT_OK=true if [ "$(id -u)" -eq 0 ]; then SUDO="" elif sudo -n true 2>/dev/null; then SUDO="sudo" else echo " 경고: sudo 권한 없음 — apt 설치를 건너뜁니다." echo " 수동 설치: sudo apt install libimage-exiftool-perl pngquant optipng jpegoptim webp potrace librsvg2-bin tesseract-ocr tesseract-ocr-kor tesseract-ocr-eng fonts-dejavu-core libheif-dev libavif-dev" APT_OK=false fi if [ "$APT_OK" = true ]; then $SUDO apt-get update -qq APT_PKGS=( libimage-exiftool-perl # exiftool CLI — EXIF 읽기/쓰기 pngquant # PNG 손실 압축 optipng # PNG 무손실 최적화 jpegoptim # JPEG 최적화 webp # cwebp / dwebp — WebP 변환 potrace # 비트맵 → SVG 벡터화 librsvg2-bin # rsvg-convert — SVG → 래스터 tesseract-ocr # OCR 엔진 tesseract-ocr-kor # 한국어 언어 데이터 tesseract-ocr-eng # 영어 언어 데이터 fonts-dejavu-core # 워터마크용 DejaVu 폰트 libheif-dev # HEIC/HEIF 디코더 헤더 libavif-dev # AVIF 디코더 헤더 ) for pkg in "${APT_PKGS[@]% *}"; do pkg_name=$(echo "$pkg" | awk '{print $1}') if dpkg -l "$pkg_name" 2>/dev/null | grep -q "^ii"; then skip "$pkg_name" else echo " installing $pkg_name..." $SUDO apt-get install -y "$pkg_name" -qq ok "$pkg_name" fi done fi # APT_OK # ────────────────────────────────────────────────── # 2. Python 패키지 (필수) # ────────────────────────────────────────────────── echo "" echo "[2/4] Python 패키지 (pip, 필수)" PIP_PKGS=( "pillow>=10.0" # 이미지 처리 기본 "pillow-avif-plugin" # AVIF 포맷 지원 "pi-heif" # HEIC/HEIF 포맷 지원 "opencv-python-headless" # 고급 이미지 처리 "numpy" # 픽셀 배열 연산 "scikit-image" # 노이즈 제거·모폴로지 등 고급 처리 "Wand" # ImageMagick Python 바인딩 "pdfplumber" # PDF 테이블 추출 (선·공백 혼합 방식) ) for spec in "${PIP_PKGS[@]% *}"; do pkg_name=$(echo "$spec" | sed 's/[>=<].*//' | awk '{print $1}') import_name=$(echo "$pkg_name" | tr '[:upper:]' '[:lower:]' | sed 's/-/_/g; s/pillow_avif_plugin/pillow_avif/; s/pillow/PIL/; s/scikit_image/skimage/; s/wand/wand.image/; s/pi_heif/pi_heif/; s/opencv_python_headless/cv2/') if python3 -c "import $import_name" 2>/dev/null; then skip "$pkg_name" else echo " installing $pkg_name..." pip install -q --break-system-packages "$spec" ok "$pkg_name" fi done # ────────────────────────────────────────────────── # 3. Python 패키지 (선택: AI 배경 제거) # ────────────────────────────────────────────────── echo "" echo "[3/4] Python 패키지 (선택: AI 배경 제거)" if [ "$WITH_REMBG" = true ]; then if python3 -c "import rembg" 2>/dev/null; then skip "rembg" else echo " installing rembg[cpu] (~500MB, onnxruntime 포함)..." # --ignore-installed: apt 관리 패키지(jsonschema 등) uninstall 시도를 건너뛰고 # ~/.local 사용자 공간에 설치 (시스템 패키지보다 우선 적용됨) pip install -q --break-system-packages --ignore-installed "rembg[cpu]" 2>/dev/null # rembg가 idna를 3.15로 올리면 roboflow(idna==3.7 필요)가 깨지므로 즉시 복구 pip install -q --break-system-packages --ignore-installed "idna==3.7" 2>/dev/null ok "rembg" fi else echo " rembg: 건너뜀 (활성화: --with-rembg 플래그 추가)" fi # ────────────────────────────────────────────────── # 4. Tesseract 언어 데이터 확인 # ────────────────────────────────────────────────── echo "" echo "[4/4] Tesseract 언어 데이터 확인" TESSDATA_DIR=$(find /usr/share/tesseract-ocr -name tessdata -type d 2>/dev/null | head -1) if [ -z "$TESSDATA_DIR" ]; then echo " 경고: tessdata 디렉토리를 찾을 수 없음" else for lang in eng kor; do if [ -f "$TESSDATA_DIR/${lang}.traineddata" ]; then ok "tesseract-$lang ($TESSDATA_DIR/${lang}.traineddata)" else echo " 경고: ${lang}.traineddata 없음 — sudo apt install tesseract-ocr-${lang}" fi done fi # homeclaw 프로젝트 루트의 eng.traineddata (tesseract.js용) PROJ_ROOT="$(cd "$(dirname "$0")/.." && pwd)" if [ -f "$PROJ_ROOT/eng.traineddata" ]; then ok "tesseract.js eng.traineddata ($PROJ_ROOT/eng.traineddata)" else echo " tesseract.js eng.traineddata 없음 — 필요 시 다운로드:" echo " curl -L https://github.com/naptha/tessdata/blob/gh-pages/4.0.0/eng.traineddata.gz?raw=true | gunzip > $PROJ_ROOT/eng.traineddata" fi # ────────────────────────────────────────────────── # 최종 확인 # ────────────────────────────────────────────────── echo "" echo "=== 설치 확인 ===" echo "" check() { local label="$1"; shift if "$@" &>/dev/null; then echo -e " ${GREEN}✓${NC} $label" else echo -e " ${YELLOW}✗${NC} $label" fi } check "exiftool" exiftool --version check "pngquant" pngquant --version check "optipng" optipng --version check "jpegoptim" jpegoptim --version check "cwebp (WebP)" cwebp -version check "potrace" potrace --version check "rsvg-convert" rsvg-convert --version check "tesseract" tesseract --version check "imagemagick" convert --version check "ffmpeg" ffmpeg -version echo "" python3 - <<'PYCHECK' import sys GREEN = "\033[0;32m"; YELLOW = "\033[1;33m"; NC = "\033[0m" def chk(label, mod): try: m = __import__(mod) ver = getattr(m, "__version__", getattr(m, "VERSION", "ok")) print(f" {GREEN}✓{NC} {label}: {ver}") except ImportError: print(f" {YELLOW}✗{NC} {label}: not found") chk("Pillow", "PIL") chk("pillow-avif-plugin", "pillow_avif") chk("pi-heif", "pi_heif") chk("opencv", "cv2") chk("numpy", "numpy") chk("scikit-image", "skimage") chk("Wand", "wand") chk("pdfplumber", "pdfplumber") chk("rembg (optional)", "rembg") PYCHECK echo "" echo "=== 완료 ===" echo "" echo "image_info / image_edit 툴 사용 가능:" echo " - crop, resize, rotate, flip, grayscale" echo " - brightness, contrast, sharpen, thumbnail, watermark, convert" echo " - HEIC, AVIF, WebP, PNG, JPEG, TIFF, BMP, GIF 포맷 지원" [ "$WITH_REMBG" = true ] && echo " - rembg 배경 제거 (AI)" echo ""