Docs
ptp
ptp
Camera control over USB PTP, in Go. No vendor SDK runs in the process.
Source: github.com/mikefsq/ptp .
import (
"github.com/mikefsq/ptp"
"github.com/mikefsq/ptp/fuji"
)
cam, err := fuji.Open("") // empty serial: the only attached body
defer cam.Close() // hands the camera back to its owner
cam.SetManualFocus()
cam.SetShutter(time.Second / 1000)
cam.Capture(120 * time.Second)Layout
| Package | Covers |
|---|---|
ptp |
Framing, sessions, objects, property descriptors, events. |
ptp/usb |
The per-OS USB transports. |
ptp/fuji |
Fujifilm X and GFX. |
ptp/sony |
Sony Alpha. |
ptp/canon, ptp/nikon |
Not implemented. |
Capability interfaces in camera.go give the vendors one shape: Capturer,
ExposureControl, Downloader, BufferReporter, FocusControl, LiveViewer,
and RawDecoder.
Status
ptp/fuji is validated on an X-T5: capture, download, live view, histogram,
exposures from 5 µs to 64 s, bracketed bursts at 0.76 s per frame, clock sync,
and clean teardown. 250 of the body’s 263 properties are named, and all 263 are
reachable with validation against a live descriptor.
ptp/usb on darwin is validated on an X-T5 and a NEX-6. It recovers a wedged
body in software by clearing both bulk endpoints and issuing the still-image
class Device Reset, so a camera left waiting for the rest of an abandoned data
phase no longer needs unplugging.
ptp/sony has RAW decoding validated on A7R V and A7R VI frames. The control
layer is implemented, covering the SDIO handshake, the property blob, the
button-driven shutter, exposure encodings, bursts, card readiness, live view,
clock sync, the image-format surface, and value naming. Its transport and object
layers are validated on a NEX-6, but every SDIO path is unverified: a NEX-6
has no SDIO operations, so nothing that supports them has been driven yet.
RAW decoding
Both vendors decode their own RAW to an undemosaiced ptp.CFA: the full sensor
readout, with the mosaic described rather than applied. Calibration is only valid
while every value still sits at the photosite that produced it, so demosaicing is
left to whatever consumes the frame.
| Uncompressed | Compressed | |
|---|---|---|
| Fujifilm RAF | done | lossless done; lossy not implemented |
| Sony ARW | done | ARW2 lossy and lossless JPEG both done |
Every path is verified pixel-for-pixel against libraw on real frames, including a 40.9 Mpx X-T5 frame, a 64.7 Mpx ILCE-7RM5 frame, and 73.4 Mpx ILCE-7RM6 frames.
The two vendors chose very differently. Fujifilm invented a codec, an adaptive Golomb-Rice scheme over gradient contexts, which is unpublished and was reverse engineered for this module. Sony reused lossless JPEG (ITU-T T.81 Annex H), the same codec behind Canon CR2 and Adobe DNG, so that decoder is written from the spec.
Single-threaded, both decoders sit at parity with libraw, which is the honest framing given that libraw is C++ and this is Go. The difference is that this work divides: Fujifilm into independent column blocks, Sony into independent 512×512 tiles. Four cores, the count on the Raspberry Pi this is aimed at, scale 3.4× to 3.9× over the same decoder’s single-core time on both vendors.