Skip to content

Instantly share code, notes, and snippets.

@stillyslalom
Last active October 10, 2018 18:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stillyslalom/36d72c216da18202d018025d3ef28fff to your computer and use it in GitHub Desktop.
Save stillyslalom/36d72c216da18202d018025d3ef28fff to your computer and use it in GitHub Desktop.
Grayscale cine file reader
using ImageCore: N0f8, N4f12, Gray
using ProgressMeter: @showprogress
using DataStructures: OrderedDict
function cineheader(fname)
h = OrderedDict()
open(fname) do f
# Check magic number
read(f, UInt16) == UInt(18755) || error(basename(fname), " is not a .cine file")
fhtypes = OrderedDict( # File header
:HeadSize => UInt16,
:Compression => UInt16,
:Version => UInt16,
:FirstImageIndex => Int32,
:TotalImages => UInt32,
:FirstImageNum => Int32,
:ImCount => UInt32,
:OffImageHeader => UInt32,
:OffSetup => UInt32,
:OffImageOffsetscl => UInt32,
:TriggerFrac => UInt32,
:TriggerSec => UInt32
)
ihtypes = OrderedDict( # Image header
:ImHeadSize => UInt32,
:Width => Int32,
:Height => Int32,
:Planes => UInt16,
:BitDepth => UInt16,
:Comp => UInt32,
:SizeImage => UInt32,
:PxPerMX => UInt32,
:PxPerMY => UInt32,
:ClrUsed => UInt32,
:ClrImportant => UInt32,
:FPS => UInt16
)
for (ID, headertype) in fhtypes # Read .cine file header
h[ID] = read(f, headertype)
end
seek(f, h[:OffImageHeader])
for (ID, headertype) in ihtypes # Read image header
h[ID] = read(f, headertype)
end
h[:BitType] = h[:BitDepth] == 8 ? Gray{N0f8} : Gray{N4f12}
numframes = h[:ImCount]
numframes > 0 || error("no images exist in file")
seek(f, h[:OffImageOffsetscl])
h[:ImLocs] = read!(f, Array{Int64}(undef, numframes))
seekstart(f)
i = 1
while read(f, UInt16) != 1002 # Get location of images
i += 1
end
h[:ImageOffset] = i
dt = zeros(numframes)
skip(f, 2)
for i = 1:numframes # Calculate dt for each frame
fracstart = read(f, UInt32)
secstart = read(f, UInt32)
dt[i] = (secstart - h[:TriggerSec]) + ((fracstart - h[:TriggerFrac])/2^32)
end
h[:DeltaT] = dt
end
h[:Tmp] = Array{h[:BitType]}(undef, h[:Width], h[:Height])
return h
end
function readframe!(f::IO, frame, h, frameidx)
frameidx <= h[:ImCount] || error("tried to access nonexistent frame $frameidx")
seek(f, h[:ImLocs][frameidx])
skip(f, read(f, UInt32) - 4)
read!(f, h[:Tmp])
frame .= rotl90(h[:Tmp])
end
readframe!(fname, frame, h, frameidx) = open(f -> readframe!(f, frame, h, frameidx), fname)
readframe(f, h, frameidx) = readframe!(f, rotl90(h[:Tmp]), h, frameidx)
function readframe(f, h, frameidxs::AbstractVector{Int})
img = similar(h[:Tmp], h[:Height], h[:Width], length(frameidxs))
for (i, frameidx) in enumerate(frameidxs)
frame = @view img[:,:,i]
readframe!(f, frame, h, fidx)
end
return img
end
function readcine(fname)
h = cineheader(fname)
img = Array{h[:BitType]}(undef, h[:Height], h[:Width], h[:ImCount])
open(fname) do f
@showprogress .1 "Loading $(basename(fname)) " for i = 1:h[:ImCount]
frame = @view img[:,:,i]
readframe!(f, frame, h, i)
end
end
return img, h
end
readcine(fname, h) = readcine(fname)[1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment