From c6b09f28bba16515915f40acd28a3e2fb6cf46e7 Mon Sep 17 00:00:00 2001 From: Sdanisch Date: Sun, 27 Sep 2015 17:54:50 +0200 Subject: [PATCH 01/14] activate precompile This was only for ImageMagick, see JuliaIO/ImageMagick.jl#7 --- src/Images.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Images.jl b/src/Images.jl index bfe618d7..451742df 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -1,4 +1,4 @@ -VERSION >= v"0.4.0-dev+6521" && __precompile__(@unix? true : false) +VERSION >= v"0.4.0-dev+6521" && __precompile__(true) module Images From a6f9eb9b4ccb712ab27476f2a5fb0d011cd59935 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 27 Sep 2015 13:41:15 -0500 Subject: [PATCH 02/14] Delete unnecessary items from Images --- src/Images.jl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Images.jl b/src/Images.jl index 451742df..6b61d677 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -38,9 +38,6 @@ immutable TypeConst{N} end # for passing compile-time constants to functions include("core.jl") include("map.jl") include("overlays.jl") -const have_imagemagick = include("ioformats/libmagickwand.jl") -@osx_only include("ioformats/OSXnative.jl") -include("io.jl") include("labeledarrays.jl") include("algorithms.jl") include("connected.jl") @@ -148,12 +145,6 @@ export # types widthheight, raw, - # io functions - add_image_file_format, - imread, - imwrite, - loadformat, - # iterator functions first_index, iterate_spatial, From d6549a2070358f370f91ba900f5f69cb07d2c6ae Mon Sep 17 00:00:00 2001 From: Sdanisch Date: Sun, 27 Sep 2015 18:08:27 +0200 Subject: [PATCH 03/14] removed all IO related files but SIF & Imagine --- src/io.jl | 660 --------------------------------- src/ioformats/OSXnative.jl | 432 --------------------- src/ioformats/dummy.jl | 12 - src/ioformats/libmagickwand.jl | 368 ------------------ src/ioformats/nrrd.jl | 431 --------------------- test/io.jl | 151 -------- test/io/small.nrrd | Bin 4296 -> 0 bytes test/io/small.raw | Bin 4000 -> 0 bytes test/io/small_time.nrrd | Bin 5162 -> 0 bytes test/io/smallgz.nrrd | Bin 3888 -> 0 bytes test/io/units.nhdr | 14 - test/readOSX.jl | 74 ---- test/readnrrd.jl | 58 --- test/readremote.jl | 213 ----------- test/readstream.jl | 23 -- test/runtests.jl | 7 - 16 files changed, 2443 deletions(-) delete mode 100644 src/io.jl delete mode 100644 src/ioformats/OSXnative.jl delete mode 100644 src/ioformats/dummy.jl delete mode 100644 src/ioformats/libmagickwand.jl delete mode 100644 src/ioformats/nrrd.jl delete mode 100644 test/io.jl delete mode 100644 test/io/small.nrrd delete mode 100644 test/io/small.raw delete mode 100644 test/io/small_time.nrrd delete mode 100644 test/io/smallgz.nrrd delete mode 100644 test/io/units.nhdr delete mode 100644 test/readOSX.jl delete mode 100644 test/readnrrd.jl delete mode 100644 test/readremote.jl delete mode 100644 test/readstream.jl diff --git a/src/io.jl b/src/io.jl deleted file mode 100644 index 43c6920c..00000000 --- a/src/io.jl +++ /dev/null @@ -1,660 +0,0 @@ -########## I/O ########### - -import .LibMagick -import .LibOSXNative - -abstract ImageFileType - -# Database of image file extension, magic bytes, and file type stubs -# Add new items to this database using add_image_file_format (below) -# -# Filename extensions do not uniquely specify the image type, so we -# have extensions pointing to a list of candidate formats. On reading, -# this list is really just a hint to improve efficiency: in the end, -# it's the set of magic bytes in the file that determine the file -# format. -fileext = Dict{ByteString, Vector{Int}}() -filemagic = Array(Vector{UInt8}, 0) -filetype = Array(Any, 0) -filesrcloaded = Array(Bool, 0) -filesrc = Array(AbstractString, 0) -filemmap = Array(Bool,0) # if it supports memory-mapped operation - -function _loadformat(index::Int) - filename = joinpath("ioformats", filesrc[index]) - if !isfile(filename) - filename = joinpath(dirname(@__FILE__), "ioformats", filesrc[index]) - end - include(filename) - filesrcloaded[index] = true -end -function loadformat{FileType<:ImageFileType}(::Type{FileType}) - indx = find(filetype .== FileType) - if length(indx) == 1 - _loadformat(indx[1]) - elseif isempty(indx) - error("File format ", FileType, " not found") - else - error("File format ", FileType, " is entered multiple times") - end - nothing -end - -# if supportmmap == true, then imread() should take a mmap keyword argument that is either -# :auto, true or false. -function add_image_file_format{ImageType<:ImageFileType}(ext::ByteString, magic::Vector{UInt8}, - ::Type{ImageType}, filecode::ASCIIString; supportsmmap::Bool=false) - # Check to see whether these magic bytes are already in the database - for i in 1:length(filemagic) - if magic == filemagic[i] - fileext[ext] = [i] # update/add extension lookup - filetype[i] = ImageType - return - end - end - # Add a new entry on the list - push!(filemagic, magic) - len = length(filemagic) - push!(filetype, ImageType) - if haskey(fileext, ext) - push!(fileext[ext], len) - else - fileext[ext] = [len] - end - push!(filesrcloaded, isempty(filecode)) - push!(filesrc, filecode) - push!(filemmap, supportsmmap) -end -add_image_file_format{ImageType<:ImageFileType}(ext::ByteString, magic::Vector{UInt8}, ::Type{ImageType}; supportsmmap::Bool=false) = - add_image_file_format(ext, magic, ImageType, "", supportsmmap=supportsmmap) -add_image_file_format{ImageType<:ImageFileType}(ext::ByteString, ::Type{ImageType}, filecode::ASCIIString; supportsmmap::Bool=false) = - add_image_file_format(ext, b"", ImageType, filecode, supportsmmap=supportsmmap) - -# Define our fallback file formats now, because we need them in generic imread. -# This has no extension (and is not added to the database), because it is always used as a stream. -type ImageMagick <: ImageFileType end -type OSXNative <: ImageFileType end - -function imread(filename::AbstractString;extraprop="",extrapropertynames=false,mmap=:auto) - - if (mmap != :auto) && (mmap != true) && (mmap != false) - error("Argument mmap must be either true, false or :auto") - end - - _, ext = splitext(filename) - ext = lowercase(ext) - - img = open(filename, "r") do stream - # Tries to read the image using a set of potential type candidates. - # Returns the image if successful, `nothing` else. - function tryread(candidates) - if (index = image_decode_magic(stream, candidates)) > 0 - # Position to end of this type's magic bytes - seek(stream, length(filemagic[index])) - if !filesrcloaded[index] - _loadformat(index) - end - - if mmap == true && !filemmap[index] # find out if it supports mmap - error("Reader does not support memory-mapped operation") - elseif filemmap[index] - imread(stream, filetype[index], mmap=mmap) - else - imread(stream, filetype[index]) - end - end - end - - # Use the extension as a hint to determine file type - if haskey(fileext, ext) && (img = tryread(fileext[ext])) != nothing - return img - end - - # Extension wasn't helpful, look at all known magic bytes - if (img = tryread(1:length(filemagic))) != nothing - return img - end - end - - if img != nothing - return img - end - - @osx_only begin - if mmap == true - error("mmap not supported with the OSX native interface") - end - - img = imread(filename, OSXNative) - if img != nothing - return img - end - end - - # There are no registered readers for this type. Try using ImageMagick if available. - if have_imagemagick - if mmap == true - error("mmap not supported for this file type (trying with ImageMagick)") - end - return imread(filename, ImageMagick,extraprop=extraprop,extrapropertynames=extrapropertynames) - else - error("Do not know how to read file ", filename, ". Is ImageMagick installed properly? See README.") - end -end - -imread{C<:Color}(filename::AbstractString, ::Type{C}) = imread(filename, ImageMagick, C) - -# Identify via magic bytes -function image_decode_magic{S<:IO}(stream::S, candidates::AbstractVector{Int}) - maxlen = 0 - for i in candidates - len = length(filemagic[i]) - maxlen = (len > maxlen) ? len : maxlen - end - # If there are no magic bytes, simply use the file extension - if maxlen == 0 && length(candidates) == 1 - return candidates[1] - end - - magicbuf = zeros(UInt8, maxlen) - for i=1:maxlen - if eof(stream) break end - magicbuf[i] = read(stream, UInt8) - end - for i in candidates - if length(filemagic[i]) == 0 - continue - end - ret = ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, Int), magicbuf, filemagic[i], min(length(filemagic[i]), length(magicbuf))) - if ret == 0 - return i - end - end - return -1 -end - -function imwrite(img, filename::AbstractString; kwargs...) - _, ext = splitext(filename) - ext = lowercase(ext) - if haskey(fileext, ext) - # Write using specific format - candidates = fileext[ext] - index = candidates[1] # TODO?: use options, don't default to first - if !filesrcloaded[index] - _loadformat(index) - end - imwrite(img, filename, filetype[index]; kwargs...) - elseif have_imagemagick - # Fall back on ImageMagick - imwrite(img, filename, ImageMagick; kwargs...) - else - error("Do not know how to write file ", filename) - end -end - -function imwrite{T<:ImageFileType}(img, filename::AbstractString, ::Type{T}; kwargs...) - open(filename, "w") do s - imwrite(img, s, T; kwargs...) - end -end - -# only mime writeable to PNG if 2D (used by IJulia for example) -mimewritable(::MIME"image/png", img::AbstractImage) = sdims(img) == 2 && timedim(img) == 0 -# We have to disable Color's display via SVG, because both will get sent with unfortunate results. -# See IJulia issue #229 -mimewritable{T<:Color}(::MIME"image/svg+xml", ::AbstractMatrix{T}) = false - -writemime(stream::IO, ::MIME"image/png", img::AbstractImageIndexed; kwargs...) = - writemime(stream, MIME"image/png", convert(Image, img); kwargs...) - -function writemime(stream::IO, ::MIME"image/png", img::AbstractImage; mapi=mapinfo_writemime(img), minpixels=10^4, maxpixels=10^6) - assert2d(img) - A = data(img) - nc = ncolorelem(img) - npix = length(A)/nc - while npix > maxpixels - A = restrict(A, coords_spatial(img)) - npix = length(A)/nc - end - if npix < minpixels - fac = ceil(Int, sqrt(minpixels/npix)) - r = ones(Int, ndims(img)) - r[coords_spatial(img)] = fac - A = repeat(A, inner=r) - end - wand = image2wand(shareproperties(img, A), mapi, nothing) - blob = LibMagick.getblob(wand, "png") - write(stream, blob) -end - -function mapinfo_writemime(img; maxpixels=10^6) - if length(img) <= maxpixels - return mapinfo_writemime_(img) - end - mapinfo_writemime_restricted(img) -end -mapinfo_writemime_{T}(img::AbstractImage{Gray{T}}) = mapinfo(Gray{Ufixed8},img) -mapinfo_writemime_{C<:Color}(img::AbstractImage{C}) = mapinfo(RGB{Ufixed8},img) -mapinfo_writemime_{AC<:GrayA}(img::AbstractImage{AC}) = mapinfo(GrayA{Ufixed8},img) -mapinfo_writemime_{AC<:TransparentColor}(img::AbstractImage{AC}) = mapinfo(RGBA{Ufixed8},img) -mapinfo_writemime_(img::AbstractImage) = mapinfo(Ufixed8,img) - -mapinfo_writemime_restricted{T}(img::AbstractImage{Gray{T}}) = ClampMinMax(Gray{Ufixed8},0.0,1.0) -mapinfo_writemime_restricted{C<:Color}(img::AbstractImage{C}) = ClampMinMax(RGB{Ufixed8},0.0,1.0) -mapinfo_writemime_restricted{AC<:GrayA}(img::AbstractImage{AC}) = ClampMinMax(GrayA{Ufixed8},0.0,1.0) -mapinfo_writemime_restricted{AC<:TransparentColor}(img::AbstractImage{AC}) = ClampMinMax(RGBA{Ufixed8},0.0,1.0) -mapinfo_writemime_restricted(img::AbstractImage) = mapinfo(Ufixed8,img) - - -#### Implementation of specific formats #### - -#### OSX Native readers from CoreGraphics -imread(source, ::Type{OSXNative}) = LibOSXNative.imread(source) - - -#### ImageMagick library - -# fixed type for depths > 8 -const ufixedtype = @compat Dict(10=>Ufixed10, 12=>Ufixed12, 14=>Ufixed14, 16=>Ufixed16) - -@compat function imread(filename::Union{AbstractString,IO,Vector{UInt8}}, ::Type{ImageMagick};extraprop="",extrapropertynames=false) - wand = LibMagick.MagickWand() - LibMagick.readimage(wand, filename) - LibMagick.resetiterator(wand) - - if extrapropertynames - return(LibMagick.getimageproperties(wand,"*")) - end - - imtype = LibMagick.getimagetype(wand) - # Determine what we need to know about the image format - sz = size(wand) - n = LibMagick.getnumberimages(wand) - if n > 1 - sz = tuple(sz..., n) - end - havealpha = LibMagick.getimagealphachannel(wand) - prop = Dict("spatialorder" => ["x", "y"], "pixelspacing" => [1,1]) - cs = LibMagick.getimagecolorspace(wand) - if imtype == "GrayscaleType" || imtype == "GrayscaleMatteType" - cs = "Gray" - end - prop["IMcs"] = cs - - if extraprop != "" - for extra in [extraprop;] - prop[extra] = LibMagick.getimageproperty(wand,extra) - end - end - - depth = LibMagick.getimagechanneldepth(wand, LibMagick.DefaultChannels) - if depth <= 8 - T = Ufixed8 # always use 8-bit for 8-bit and less - else - T = ufixedtype[2*((depth+1)>>1)] # always use an even # of bits (see issue 242#issuecomment-68845157) - end - - channelorder = cs - if havealpha - if channelorder == "sRGB" || channelorder == "RGB" - if is_little_endian - T, channelorder = BGRA{T}, "BGRA" - else - T, channelorder = ARGB{T}, "ARGB" - end - elseif channelorder == "Gray" - T, channelorder = GrayA{T}, "IA" - else - error("Cannot parse colorspace $channelorder") - end - else - if channelorder == "sRGB" || channelorder == "RGB" - T, channelorder = RGB{T}, "RGB" - elseif channelorder == "Gray" - T, channelorder = Gray{T}, "I" - else - error("Cannot parse colorspace $channelorder") - end - end - # Allocate the buffer and get the pixel data - buf = Array(T, sz...) - LibMagick.exportimagepixels!(buf, wand, cs, channelorder) - if n > 1 - prop["timedim"] = ndims(buf) - end - Image(buf, prop) -end - -imread{C<:Colorant}(filename::AbstractString, ::Type{ImageMagick}, ::Type{C}) = convert(Image{C}, imread(filename, ImageMagick)) - -imwrite(img::AbstractImageIndexed, filename::AbstractString, ::Type{ImageMagick}; kwargs...) = imwrite(convert(Image, img), filename, ImageMagick; kwargs...) - -function imwrite(img, filename::AbstractString, ::Type{ImageMagick}; mapi = mapinfo(ImageMagick, img), quality = nothing) - wand = image2wand(img, mapi, quality) - LibMagick.writeimage(wand, filename) -end - -function image2wand(img, mapi, quality) - imgw = map(mapi, img) - imgw = permutedims_horizontal(imgw) - have_color = colordim(imgw)!=0 - if ndims(imgw) > 3+have_color - error("At most 3 dimensions are supported") - end - wand = LibMagick.MagickWand() - if haskey(img, "IMcs") - cs = img["IMcs"] - else - cs = colorspace(imgw) - if in(cs, ("RGB", "RGBA", "ARGB", "BGRA")) - cs = LibMagick.libversion > v"6.7.5" ? "sRGB" : "RGB" - end - end - channelorder = colorspace(imgw) - if channelorder == "Gray" - channelorder = "I" - elseif channelorder == "GrayA" - channelorder = "IA" - end - tmp = to_explicit(to_contiguous(data(imgw))) - LibMagick.constituteimage(tmp, wand, cs, channelorder) - if quality != nothing - LibMagick.setimagecompressionquality(wand, quality) - end - LibMagick.resetiterator(wand) - wand -end - -# ImageMagick mapinfo client. Converts to RGB and uses Ufixed. -mapinfo{T<:Ufixed}(::Type{ImageMagick}, img::AbstractArray{T}) = MapNone{T}() -mapinfo{T<:AbstractFloat}(::Type{ImageMagick}, img::AbstractArray{T}) = MapNone{Ufixed8}() -for ACV in (Color, AbstractRGB) - for CV in subtypes(ACV) - (length(CV.parameters) == 1 && !(CV.abstract)) || continue - CVnew = CV<:AbstractGray ? Gray : RGB - @eval mapinfo{T<:Ufixed}(::Type{ImageMagick}, img::AbstractArray{$CV{T}}) = MapNone{$CVnew{T}}() - @eval mapinfo{CV<:$CV}(::Type{ImageMagick}, img::AbstractArray{CV}) = MapNone{$CVnew{Ufixed8}}() - CVnew = CV<:AbstractGray ? Gray : BGR - AC, CA = alphacolor(CV), coloralpha(CV) - ACnew, CAnew = alphacolor(CVnew), coloralpha(CVnew) - @eval begin - mapinfo{T<:Ufixed}(::Type{ImageMagick}, img::AbstractArray{$AC{T}}) = MapNone{$ACnew{T}}() - mapinfo{P<:$AC}(::Type{ImageMagick}, img::AbstractArray{P}) = MapNone{$ACnew{Ufixed8}}() - mapinfo{T<:Ufixed}(::Type{ImageMagick}, img::AbstractArray{$CA{T}}) = MapNone{$CAnew{T}}() - mapinfo{P<:$CA}(::Type{ImageMagick}, img::AbstractArray{P}) = MapNone{$CAnew{Ufixed8}}() - end - end -end -mapinfo(::Type{ImageMagick}, img::AbstractArray{RGB24}) = MapNone{RGB{Ufixed8}}() -mapinfo(::Type{ImageMagick}, img::AbstractArray{ARGB32}) = MapNone{BGRA{Ufixed8}}() - -# Clamping mapinfo client. Converts to RGB and uses Ufixed, clamping floating-point values to [0,1]. -mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{T}) = MapNone{T}() -mapinfo{T<:AbstractFloat}(::Type{Clamp}, img::AbstractArray{T}) = ClampMinMax(Ufixed8, zero(T), one(T)) -for ACV in (Color, AbstractRGB) - for CV in subtypes(ACV) - (length(CV.parameters) == 1 && !(CV.abstract)) || continue - CVnew = CV<:AbstractGray ? Gray : RGB - @eval mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{$CV{T}}) = MapNone{$CVnew{T}}() - @eval mapinfo{CV<:$CV}(::Type{Clamp}, img::AbstractArray{CV}) = Clamp{$CVnew{Ufixed8}}() - CVnew = CV<:AbstractGray ? Gray : BGR - AC, CA = alphacolor(CV), coloralpha(CV) - ACnew, CAnew = alphacolor(CVnew), coloralpha(CVnew) - @eval begin - mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{$AC{T}}) = MapNone{$ACnew{T}}() - mapinfo{P<:$AC}(::Type{Clamp}, img::AbstractArray{P}) = Clamp{$ACnew{Ufixed8}}() - mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{$CA{T}}) = MapNone{$CAnew{T}}() - mapinfo{P<:$CA}(::Type{Clamp}, img::AbstractArray{P}) = Clamp{$CAnew{Ufixed8}}() - end - end -end -mapinfo(::Type{Clamp}, img::AbstractArray{RGB24}) = MapNone{RGB{Ufixed8}}() -mapinfo(::Type{Clamp}, img::AbstractArray{ARGB32}) = MapNone{BGRA{Ufixed8}}() - -# Make the data contiguous in memory, this is necessary for imagemagick since it doesn't handle stride. -to_contiguous(A::AbstractArray) = A -to_contiguous(A::SubArray) = copy(A) - -to_explicit(A::AbstractArray) = A -to_explicit{T<:Ufixed}(A::AbstractArray{T}) = reinterpret(FixedPointNumbers.rawtype(T), A) -to_explicit{T<:Ufixed}(A::AbstractArray{RGB{T}}) = reinterpret(FixedPointNumbers.rawtype(T), A, tuple(3, size(A)...)) -to_explicit{T<:AbstractFloat}(A::AbstractArray{RGB{T}}) = to_explicit(map(ClipMinMax(RGB{Ufixed8}, zero(RGB{T}), one(RGB{T})), A)) -to_explicit{T<:Ufixed}(A::AbstractArray{Gray{T}}) = reinterpret(FixedPointNumbers.rawtype(T), A, size(A)) -to_explicit{T<:AbstractFloat}(A::AbstractArray{Gray{T}}) = to_explicit(map(ClipMinMax(Gray{Ufixed8}, zero(Gray{T}), one(Gray{T})), A)) -to_explicit{T<:Ufixed}(A::AbstractArray{GrayA{T}}) = reinterpret(FixedPointNumbers.rawtype(T), A, tuple(2, size(A)...)) -to_explicit{T<:AbstractFloat}(A::AbstractArray{GrayA{T}}) = to_explicit(map(ClipMinMax(GrayA{Ufixed8}, zero(GrayA{T}), one(GrayA{T})), A)) -to_explicit{T<:Ufixed}(A::AbstractArray{BGRA{T}}) = reinterpret(FixedPointNumbers.rawtype(T), A, tuple(4, size(A)...)) -to_explicit{T<:AbstractFloat}(A::AbstractArray{BGRA{T}}) = to_explicit(map(ClipMinMax(BGRA{Ufixed8}, zero(BGRA{T}), one(BGRA{T})), A)) -to_explicit{T<:Ufixed}(A::AbstractArray{RGBA{T}}) = reinterpret(FixedPointNumbers.rawtype(T), A, tuple(4, size(A)...)) -to_explicit{T<:AbstractFloat}(A::AbstractArray{RGBA{T}}) = to_explicit(map(ClipMinMax(RGBA{Ufixed8}, zero(RGBA{T}), one(RGBA{T})), A)) - -# Write values in permuted order -let method_cache = Dict() -global writepermuted -function writepermuted(stream, img, mapi::MapInfo, perm; gray2color::Bool = false) - cd = colordim(img) - key = (perm, cd, gray2color) - if !haskey(method_cache, key) - mapfunc = cd > 0 ? (:map1) : (:map) - loopsyms = [symbol(string("i_",d)) for d = 1:ndims(img)] - body = gray2color ? quote - g = $mapfunc(mapi, img[$(loopsyms...)]) - write(stream, g) - write(stream, g) - write(stream, g) - end : quote - write(stream, $mapfunc(mapi, img[$(loopsyms...)])) - end - loopargs = [:($(loopsyms[d]) = 1:size(img, $d)) for d = 1:ndims(img)] - loopexpr = Expr(:for, Expr(:block, loopargs[perm[end:-1:1]]...), body) - f = @eval begin - local _writefunc_ - function _writefunc_(stream, img, mapi) - $loopexpr - end - end - else - f = method_cache[key] - end - f(stream, img, mapi) - nothing -end -end - -function write{T<:Ufixed}(io::IO, c::AbstractRGB{T}) - write(io, reinterpret(c.r)) - write(io, reinterpret(c.g)) - write(io, reinterpret(c.b)) -end - -function write(io::IO, c::RGB24) - write(io, red(c)) - write(io, green(c)) - write(io, blue(c)) -end - -## PPM, PGM, and PBM ## -type PPMBinary <: ImageFileType end -type PGMBinary <: ImageFileType end -type PBMBinary <: ImageFileType end - -#add_image_file_format(".ppm", b"P6", PPMBinary) -#add_image_file_format(".ppm", b"P3", PPMASCII) -#add_image_file_format(".pgm", b"P5", PGMBinary) -#add_image_file_format(".pgm", b"P2", PGMASCII) -#add_image_file_format(".pbm", b"P4", PBMBinary) -#add_image_file_format(".pbm", b"P1", PBMASCII) - -function parse_netpbm_size(stream::IO) - szline = strip(readline(stream)) - while isempty(szline) || szline[1] == '#' - szline = strip(readline(stream)) - end - parseints(szline, 2) -end - -function parse_netpbm_maxval(stream::IO) - skipchars(stream, isspace, linecomment='#') - maxvalline = strip(readline(stream)) - parse(Int, maxvalline) -end - -function imread{S<:IO}(stream::S, ::Type{PPMBinary}) - w, h = parse_netpbm_size(stream) - maxval = parse_netpbm_maxval(stream) - local dat - if maxval <= 255 - datraw = read(stream, Ufixed8, 3, w, h) - dat = reinterpret(RGB{Ufixed8}, datraw, (w, h)) - elseif maxval <= typemax(UInt16) - # read first as UInt16 so the loop is type-stable, then convert to Ufixed - datraw = Array(UInt16, 3, w, h) - # there is no endian standard, but netpbm is big-endian - if !is_little_endian - for indx = 1:3*w*h - datraw[indx] = read(stream, UInt16) - end - else - for indx = 1:3*w*h - datraw[indx] = bswap(read(stream, UInt16)) - end - end - # Determine the appropriate Ufixed type - T = ufixedtype[ceil(Int, log2(maxval)/2)<<1] - dat = reinterpret(RGB{T}, datraw, (w, h)) - else - error("Image file may be corrupt. Are there really more than 16 bits in this image?") - end - T = eltype(dat) - Image(dat, @compat Dict("spatialorder" => ["x", "y"], "pixelspacing" => [1,1])) -end - -function imread{S<:IO}(stream::S, ::Type{PGMBinary}) - w, h = parse_netpbm_size(stream) - maxval = parse_netpbm_maxval(stream) - local dat - if maxval <= 255 - dat = read(stream, Ufixed8, w, h) - elseif maxval <= typemax(UInt16) - datraw = Array(UInt16, w, h) - if !is_little_endian - for indx = 1:w*h - datraw[indx] = read(stream, UInt16) - end - else - for indx = 1:w*h - datraw[indx] = bswap(read(stream, UInt16)) - end - end - # Determine the appropriate Ufixed type - T = ufixedtype[ceil(Int, log2(maxval)/2)<<1] - dat = reinterpret(RGB{T}, datraw, (w, h)) - else - error("Image file may be corrupt. Are there really more than 16 bits in this image?") - end - T = eltype(dat) - Image(dat, @compat Dict("colorspace" => "Gray", "spatialorder" => ["x", "y"], "pixelspacing" => [1,1])) -end - -function imread{S<:IO}(stream::S, ::Type{PBMBinary}) - w, h = parse_netpbm_size(stream) - dat = BitArray(w, h) - nbytes_per_row = ceil(Int, w/8) - for irow = 1:h, j = 1:nbytes_per_row - tmp = read(stream, UInt8) - offset = (j-1)*8 - for k = 1:min(8, w-offset) - dat[offset+k, irow] = (tmp>>>(8-k))&0x01 - end - end - Image(dat, @compat Dict("spatialorder" => ["x", "y"], "pixelspacing" => [1,1])) -end - -function imwrite(img, filename::AbstractString, ::Type{PPMBinary}) - open(filename, "w") do stream - write(stream, "P6\n") - write(stream, "# ppm file written by Julia\n") - imwrite(img, stream, PPMBinary) - end -end - -pnmmax{T<:AbstractFloat}(::Type{T}) = 255 -pnmmax{T<:Ufixed}(::Type{T}) = reinterpret(FixedPointNumbers.rawtype(T), one(T)) -pnmmax{T<:Unsigned}(::Type{T}) = typemax(T) - -function imwrite{T<:Color}(img::AbstractArray{T}, s::IO, ::Type{PPMBinary}, mapi = mapinfo(ImageMagick, img)) - w, h = widthheight(img) - TE = eltype(T) - mx = pnmmax(TE) - write(s, "$w $h\n$mx\n") - p = permutation_horizontal(img) - writepermuted(s, img, mapi, p; gray2color = T <: AbstractGray) -end - -function imwrite{T}(img::AbstractArray{T}, s::IO, ::Type{PPMBinary}, mapi = mapinfo(ImageMagick, img)) - w, h = widthheight(img) - cs = colorspace(img) - in(cs, ("RGB", "Gray")) || error("colorspace $cs not supported") - mx = pnmmax(T) - write(s, "$w $h\n$mx\n") - p = permutation_horizontal(img) - writepermuted(s, img, mapi, p; gray2color = cs == "Gray") -end - - -function parseints(line, n) - ret = Array(Int, n) - pos = 1 - for i = 1:n - pos2 = search(line, ' ', pos) - if pos2 == 0 - pos2 = length(line)+1 - end - ret[i] = parse(Int, line[pos:pos2-1]) - pos = pos2+1 - if pos > length(line) && i < n - error("Line terminated without finding all ", n, " integers") - end - end - tuple(ret...) - -end - -# Permute to a color, horizontal, vertical, ... storage order (with time always last) -function permutation_horizontal(img) - cd = colordim(img) - td = timedim(img) - p = spatialpermutation(["x", "y"], img) - if cd != 0 - p[p .>= cd] += 1 - insert!(p, 1, cd) - end - if td != 0 - push!(p, td) - end - p -end - -permutedims_horizontal(img) = permutedims(img, permutation_horizontal(img)) - - -### Register formats for later loading here -type Dummy <: ImageFileType; end -add_image_file_format(".dummy", b"Dummy Image", Dummy, "dummy.jl") - -# NRRD image format -type NRRDFile <: ImageFileType end -add_image_file_format(".nrrd", b"NRRD", NRRDFile, "nrrd.jl", supportsmmap=true) -add_image_file_format(".nhdr", b"NRRD", NRRDFile, "nrrd.jl", supportsmmap=true) - -# Andor Technologies SIF file format -type AndorSIF <: Images.ImageFileType end -add_image_file_format(".sif", b"Andor Technology Multi-Channel File", AndorSIF, "SIF.jl") - -# Imagine file format (http://holylab.wustl.edu, "Software" tab) -type ImagineFile <: ImageFileType end -add_image_file_format(".imagine", b"IMAGINE", ImagineFile, "Imagine.jl") - -# PCO b16 image format -type B16File <: ImageFileType end -add_image_file_format(".b16", b"PCO-", B16File, "b16.jl") diff --git a/src/ioformats/OSXnative.jl b/src/ioformats/OSXnative.jl deleted file mode 100644 index ff0d806d..00000000 --- a/src/ioformats/OSXnative.jl +++ /dev/null @@ -1,432 +0,0 @@ -module LibOSXNative - -#import Base: error, size -using Images, Colors, ColorVectorSpace, FixedPointNumbers, Compat - -export imread - -imread(io::IOStream) = imread(readbytes(io)) - -function imread(b::Array{UInt8,1}) - data = CFDataCreate(b) - imgsrc = CGImageSourceCreateWithData(data) - CFRelease(data) - read_and_release_imgsrc(imgsrc) -end - -function imread(filename) - myURL = CFURLCreateWithFileSystemPath(abspath(filename)) - imgsrc = CGImageSourceCreateWithURL(myURL) - CFRelease(myURL) - read_and_release_imgsrc(imgsrc) -end - -## core, internal function -function read_and_release_imgsrc(imgsrc) - imgsrc == C_NULL && return nothing - - # Get image information - imframes = convert(Int,CGImageSourceGetCount(imgsrc)) - if imframes == 0 - # Bail out to ImageMagick - warn("OSX reader found no frames") - CFRelease(imgsrc) - return nothing - end - dict = CGImageSourceCopyPropertiesAtIndex(imgsrc, 0) - imheight = CFNumberGetValue(CFDictionaryGetValue(dict, "PixelHeight"), Int16) - imwidth = CFNumberGetValue(CFDictionaryGetValue(dict, "PixelWidth"), Int16) - isindexed = CFBooleanGetValue(CFDictionaryGetValue(dict, "IsIndexed")) - if isindexed - # Bail out to ImageMagick - warn("OSX reader: indexed color images not implemented") - CFRelease(imgsrc) - return nothing - end - hasalpha = CFBooleanGetValue(CFDictionaryGetValue(dict, "HasAlpha")) - - pixeldepth = CFNumberGetValue(CFDictionaryGetValue(dict, "Depth"), Int16) - # Colormodel is one of: "RGB", "Gray", "CMYK", "Lab" - colormodel = CFStringGetCString(CFDictionaryGetValue(dict, "ColorModel")) - if colormodel == "" - # Bail out to ImageMagick - warn("OSX reader found empty colormodel string") - CFRelease(imgsrc) - return nothing - end - imtype = CFStringGetCString(CGImageSourceGetType(imgsrc)) - alphacode, storagedepth = alpha_and_depth(imgsrc) - - # Get image description string - imagedescription = "" - if imtype == "public.tiff" - tiffdict = CFDictionaryGetValue(dict, "{TIFF}") - imagedescription = tiffdict != C_NULL ? - CFStringGetCString(CFDictionaryGetValue(tiffdict, "ImageDescription")) : nothing - end - CFRelease(dict) - - # Allocate the buffer and get the pixel data - sz = imframes > 1 ? (convert(Int,imwidth), convert(Int,imheight), convert(Int,imframes)) : (convert(Int,imwidth), convert(Int,imheight)) - T = pixeldepth <= 8 ? Ufixed8 : Images.ufixedtype[pixeldepth] - if colormodel == "Gray" && alphacode == 0 && storagedepth == 1 - buf = Array(Gray{T}, sz) - fillgray!(reinterpret(T, buf, tuple(sz...)), imgsrc) - elseif colormodel == "Gray" && in(alphacode, [1, 3]) - buf = Array(GrayA{T}, sz) - fillgrayalpha!(reinterpret(T, buf, tuple(2, sz...)), imgsrc) - elseif colormodel == "Gray" && in(alphacode, [2, 4]) - buf = Array(AGray{T}, sz) - fillgrayalpha!(reinterpret(T, buf, tuple(2, sz...)), imgsrc) - elseif colormodel == "RGB" && in(alphacode, [1, 3]) - buf = Array(RGBA{T}, sz) - fillcolor!(reinterpret(T, buf, tuple(4, sz...)), imgsrc, storagedepth) - elseif colormodel == "RGB" && in(alphacode, [2, 4]) - buf = Array(ARGB{T}, sz) - fillcolor!(reinterpret(T, buf, tuple(4, sz...)), imgsrc, storagedepth) - elseif colormodel == "RGB" && alphacode == 0 - buf = Array(RGB{T}, sz) - fillcolor!(reinterpret(T, buf, tuple(3, sz...)), imgsrc, storagedepth) - elseif colormodel == "RGB" && in(alphacode, [5, 6]) - buf = alphacode == 5 ? Array(RGB4{T}, sz) : Array(RGB1{T}, sz) - fillcolor!(reinterpret(T, buf, tuple(4, sz...)), imgsrc, storagedepth) - else - warn("Unknown colormodel ($colormodel) and alphacode ($alphacode) found by OSX reader") - CFRelease(imgsrc) - return nothing - end - CFRelease(imgsrc) - - # Set the image properties - prop = @compat Dict( - "spatialorder" => ["x", "y"], - "pixelspacing" => [1, 1], - "imagedescription" => imagedescription, - "suppress" => Set(Any["imagedescription"]) - ) - if imframes > 1 - prop["timedim"] = ndims(buf) - end - Image(buf, prop) -end - -function alpha_and_depth(imgsrc) - CGimg = CGImageSourceCreateImageAtIndex(imgsrc, 0) # Check only first frame - alphacode = CGImageGetAlphaInfo(CGimg) - bitspercomponent = CGImageGetBitsPerComponent(CGimg) - bitsperpixel = CGImageGetBitsPerPixel(CGimg) - CGImageRelease(CGimg) - # Alpha codes documented here: - # https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/CGImage/Reference/reference.html#//apple_ref/doc/uid/TP30000956-CH3g-459700 - # Dividing bits per pixel by bits per component tells us how many - # color + alpha slices we have in the file. - alphacode, convert(Int,div(bitsperpixel, bitspercomponent)) -end - -function fillgray!{T}(buffer::AbstractArray{T, 2}, imgsrc) - imwidth, imheight = size(buffer, 1), size(buffer, 2) - CGimg = CGImageSourceCreateImageAtIndex(imgsrc, 0) - imagepixels = CopyImagePixels(CGimg) - pixelptr = CFDataGetBytePtr(imagepixels, eltype(buffer)) - imbuffer = pointer_to_array(pixelptr, (imwidth, imheight), false) - buffer[:, :] = imbuffer - CFRelease(imagepixels) - CGImageRelease(CGimg) -end - -# Image stack -function fillgray!{T}(buffer::AbstractArray{T, 3}, imgsrc) - imwidth, imheight, nimages = size(buffer, 1), size(buffer, 2), size(buffer, 3) - for i in 1:nimages - CGimg = CGImageSourceCreateImageAtIndex(imgsrc, i - 1) - imagepixels = CopyImagePixels(CGimg) - pixelptr = CFDataGetBytePtr(imagepixels, T) - imbuffer = pointer_to_array(pixelptr, (imwidth, imheight), false) - buffer[:, :, i] = imbuffer - CFRelease(imagepixels) - CGImageRelease(CGimg) - end -end - -function fillgrayalpha!(buffer::AbstractArray{UInt8, 3}, imgsrc) - imwidth, imheight = size(buffer, 2), size(buffer, 3) - CGimg = CGImageSourceCreateImageAtIndex(imgsrc, 0) - imagepixels = CopyImagePixels(CGimg) - pixelptr = CFDataGetBytePtr(imagepixels, UInt16) - imbuffer = pointer_to_array(pixelptr, (imwidth, imheight), false) - buffer[1, :, :] = imbuffer & 0xff - buffer[2, :, :] = div(imbuffer & 0xff00, 256) - CFRelease(imagepixels) - CGImageRelease(CGimg) -end -fillgrayalpha!(buffer::AbstractArray{Ufixed8, 3}, imgsrc) = fillgrayalpha!(reinterpret(UInt8, buffer), imgsrc) - -function fillcolor!{T}(buffer::AbstractArray{T, 3}, imgsrc, nc) - imwidth, imheight = size(buffer, 2), size(buffer, 3) - CGimg = CGImageSourceCreateImageAtIndex(imgsrc, 0) - imagepixels = CopyImagePixels(CGimg) - pixelptr = CFDataGetBytePtr(imagepixels, T) - imbuffer = pointer_to_array(pixelptr, (nc, imwidth, imheight), false) - buffer[:, :, :] = imbuffer - CFRelease(imagepixels) - CGImageRelease(CGimg) -end - -function fillcolor!{T}(buffer::AbstractArray{T, 4}, imgsrc, nc) - imwidth, imheight, nimages = size(buffer, 2), size(buffer, 3), size(buffer, 4) - for i in 1:nimages - CGimg = CGImageSourceCreateImageAtIndex(imgsrc, i - 1) - imagepixels = CopyImagePixels(CGimg) - pixelptr = CFDataGetBytePtr(imagepixels, T) - imbuffer = pointer_to_array(pixelptr, (nc, imwidth, imheight), false) - buffer[:, :, :, i] = imbuffer - CFRelease(imagepixels) - CGImageRelease(CGimg) - end -end - - -## OSX Framework Wrappers ###################################################### - -const foundation = Libdl.find_library(["/System/Library/Frameworks/Foundation.framework/Resources/BridgeSupport/Foundation"]) -const imageio = Libdl.find_library(["/System/Library/Frameworks/ImageIO.framework/ImageIO"]) - -const kCFNumberSInt8Type = 1 -const kCFNumberSInt16Type = 2 -const kCFNumberSInt32Type = 3 -const kCFNumberSInt64Type = 4 -const kCFNumberFloat32Type = 5 -const kCFNumberFloat64Type = 6 -const kCFNumberCharType = 7 -const kCFNumberShortType = 8 -const kCFNumberIntType = 9 -const kCFNumberLongType = 10 -const kCFNumberLongLongType = 11 -const kCFNumberFloatType = 12 -const kCFNumberDoubleType = 13 -const kCFNumberCFIndexType = 14 -const kCFNumberNSIntegerType = 15 -const kCFNumberCGFloatType = 16 -const kCFNumberMaxType = 16 - -# Objective-C and NS wrappers -oms{T}(id, uid, ::Type{T}=Ptr{Void}) = - ccall(:objc_msgSend, T, (Ptr{Void}, Ptr{Void}), id, selector(uid)) - -ogc{T}(id, ::Type{T}=Ptr{Void}) = - ccall((:objc_getClass, "Cocoa.framework/Cocoa"), Ptr{Void}, (Ptr{UInt8}, ), id) - -selector(sel::AbstractString) = ccall(:sel_getUid, Ptr{Void}, (Ptr{UInt8}, ), sel) - -NSString(init::AbstractString) = ccall(:objc_msgSend, Ptr{Void}, - (Ptr{Void}, Ptr{Void}, Ptr{UInt8}, UInt64), - oms(ogc("NSString"), "alloc"), - selector("initWithCString:encoding:"), init, 1) - -NSLog(str::AbstractString, obj) = ccall((:NSLog, foundation), Ptr{Void}, - (Ptr{Void}, Ptr{Void}), NSString(str), obj) - -NSLog(str::AbstractString) = ccall((:NSLog, foundation), Ptr{Void}, - (Ptr{Void}, ), NSString(str)) - -NSLog(obj::Ptr) = ccall((:NSLog, foundation), Ptr{Void}, (Ptr{Void}, ), obj) - -# Core Foundation -# General -CFRetain(CFTypeRef::Ptr{Void}) = CFTypeRef != C_NULL && - ccall(:CFRetain, Void, (Ptr{Void}, ), CFTypeRef) - -CFRelease(CFTypeRef::Ptr{Void}) = CFTypeRef != C_NULL && - ccall(:CFRelease, Void, (Ptr{Void}, ), CFTypeRef) - -function CFGetRetainCount(CFTypeRef::Ptr{Void}) - CFTypeRef == C_NULL && return 0 - ccall(:CFGetRetainCount, Clonglong, (Ptr{Void}, ), CFTypeRef) -end - -CFShow(CFTypeRef::Ptr{Void}) = CFTypeRef != C_NULL && - ccall(:CFShow, Void, (Ptr{Void}, ), CFTypeRef) - -function CFCopyDescription(CFTypeRef::Ptr{Void}) - CFTypeRef == C_NULL && return C_NULL - ccall(:CFCopyDescription, Ptr{Void}, (Ptr{Void}, ), CFTypeRef) -end - -#CFCopyTypeIDDescription(CFTypeID::Cint) = CFTypeRef != C_NULL && -# ccall(:CFCopyTypeIDDescription, Ptr{Void}, (Cint, ), CFTypeID) - -function CFGetTypeID(CFTypeRef::Ptr{Void}) - CFTypeRef == C_NULL && return nothing - ccall(:CFGetTypeID, Culonglong, (Ptr{Void}, ), CFTypeRef) -end - -CFURLCreateWithString(filename) = - ccall(:CFURLCreateWithString, Ptr{Void}, - (Ptr{Void}, Ptr{Void}, Ptr{Void}), C_NULL, NSString(filename), C_NULL) - -CFURLCreateWithFileSystemPath(filename::AbstractString) = - ccall(:CFURLCreateWithFileSystemPath, Ptr{Void}, - (Ptr{Void}, Ptr{Void}, Cint, Bool), C_NULL, NSString(filename), 0, false) - -# CFDictionary -CFDictionaryGetKeysAndValues(CFDictionaryRef::Ptr{Void}, keys, values) = - CFDictionaryRef != C_NULL && - ccall(:CFDictionaryGetKeysAndValues, Void, - (Ptr{Void}, Ptr{Ptr{Void}}, Ptr{Ptr{Void}}), CFDictionaryRef, keys, values) - -function CFDictionaryGetValue(CFDictionaryRef::Ptr{Void}, key) - CFDictionaryRef == C_NULL && return C_NULL - ccall(:CFDictionaryGetValue, Ptr{Void}, - (Ptr{Void}, Ptr{Void}), CFDictionaryRef, key) -end - -CFDictionaryGetValue(CFDictionaryRef::Ptr{Void}, key::AbstractString) = - CFDictionaryGetValue(CFDictionaryRef::Ptr{Void}, NSString(key)) - -# CFNumber -function CFNumberGetValue(CFNum::Ptr{Void}, numtype) - CFNum == C_NULL && return nothing - out = Cint[0] - ccall(:CFNumberGetValue, Bool, (Ptr{Void}, Cint, Ptr{Cint}), CFNum, numtype, out) - out[1] -end - -CFNumberGetValue(CFNum::Ptr{Void}, ::Type{Int8}) = - CFNumberGetValue(CFNum, kCFNumberSInt8Type) - -CFNumberGetValue(CFNum::Ptr{Void}, ::Type{Int16}) = - CFNumberGetValue(CFNum, kCFNumberSInt16Type) - -CFNumberGetValue(CFNum::Ptr{Void}, ::Type{Int32}) = - CFNumberGetValue(CFNum, kCFNumberSInt32Type) - -CFNumberGetValue(CFNum::Ptr{Void}, ::Type{Int64}) = - CFNumberGetValue(CFNum, kCFNumberSInt64Type) - -CFNumberGetValue(CFNum::Ptr{Void}, ::Type{Float32}) = - CFNumberGetValue(CFNum, kCFNumberFloat32Type) - -CFNumberGetValue(CFNum::Ptr{Void}, ::Type{Float64}) = - CFNumberGetValue(CFNum, kCFNumberFloat64Type) - -CFNumberGetValue(CFNum::Ptr{Void}, ::Type{UInt8}) = - CFNumberGetValue(CFNum, kCFNumberCharType) - -#CFBoolean -CFBooleanGetValue(CFBoolean::Ptr{Void}) = - CFBoolean != C_NULL && - ccall(:CFBooleanGetValue, Bool, (Ptr{Void}, ), CFBoolean) - -# CFString -function CFStringGetCString(CFStringRef::Ptr{Void}) - CFStringRef == C_NULL && return "" - buffer = Array(UInt8, 1024) # does this need to be bigger for Open Microscopy TIFFs? - res = ccall(:CFStringGetCString, Bool, (Ptr{Void}, Ptr{UInt8}, UInt, UInt16), - CFStringRef, buffer, length(buffer), 0x0600) - res == C_NULL && return "" - return bytestring(pointer(buffer)) -end - -# These were unsafe, can return null pointers at random times. -# See Apple Developer Docs -#CFStringGetCStringPtr(CFStringRef::Ptr{Void}) = -# ccall(:CFStringGetCStringPtr, Ptr{UInt8}, (Ptr{Void}, UInt16), CFStringRef, 0x0600) -# -#getCFString(CFStr::Ptr{Void}) = CFStringGetCStringPtr(CFStr) != C_NULL ? -# bytestring(CFStringGetCStringPtr(CFStr)) : "" - -# Core Graphics -# CGImageSource -CGImageSourceCreateWithURL(myURL::Ptr{Void}) = - ccall((:CGImageSourceCreateWithURL, imageio), Ptr{Void}, (Ptr{Void}, Ptr{Void}), myURL, C_NULL) - -CGImageSourceCreateWithData(data::Ptr{Void}) = - ccall((:CGImageSourceCreateWithData, imageio), Ptr{Void}, (Ptr{Void}, Ptr{Void}), data, C_NULL) - -CGImageSourceGetType(CGImageSourceRef::Ptr{Void}) = - ccall(:CGImageSourceGetType, Ptr{Void}, (Ptr{Void}, ), CGImageSourceRef) - -CGImageSourceGetStatus(CGImageSourceRef::Ptr{Void}) = - ccall(:CGImageSourceGetStatus, UInt32, (Ptr{Void}, ), CGImageSourceRef) - -CGImageSourceGetStatusAtIndex(CGImageSourceRef::Ptr{Void}, n) = - ccall(:CGImageSourceGetStatusAtIndex, Int32, - (Ptr{Void}, Csize_t), CGImageSourceRef, n) #Int32? - -CGImageSourceCopyProperties(CGImageSourceRef::Ptr{Void}) = - ccall(:CGImageSourceCopyProperties, Ptr{Void}, - (Ptr{Void}, Ptr{Void}), CGImageSourceRef, C_NULL) - -CGImageSourceCopyPropertiesAtIndex(CGImageSourceRef::Ptr{Void}, n) = - ccall(:CGImageSourceCopyPropertiesAtIndex, Ptr{Void}, - (Ptr{Void}, Csize_t, Ptr{Void}), CGImageSourceRef, n, C_NULL) - -CGImageSourceGetCount(CGImageSourceRef::Ptr{Void}) = - ccall(:CGImageSourceGetCount, Csize_t, (Ptr{Void}, ), CGImageSourceRef) - -CGImageSourceCreateImageAtIndex(CGImageSourceRef::Ptr{Void}, i) = - ccall(:CGImageSourceCreateImageAtIndex, Ptr{Void}, - (Ptr{Void}, UInt64, Ptr{Void}), CGImageSourceRef, i, C_NULL) - - -# CGImageGet -CGImageGetAlphaInfo(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetAlphaInfo, UInt32, (Ptr{Void}, ), CGImageRef) - -CGImageGetBitmapInfo(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetBitmapInfo, UInt32, (Ptr{Void}, ), CGImageRef) - -CGImageGetBitsPerComponent(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetBitsPerComponent, Csize_t, (Ptr{Void}, ), CGImageRef) - -CGImageGetBitsPerPixel(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetBitsPerPixel, Csize_t, (Ptr{Void}, ), CGImageRef) - -CGImageGetBytesPerRow(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetBytesPerRow, Csize_t, (Ptr{Void}, ), CGImageRef) - -CGImageGetColorSpace(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetColorSpace, UInt32, (Ptr{Void}, ), CGImageRef) - -CGImageGetDecode(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetDecode, Ptr{Float64}, (Ptr{Void}, ), CGImageRef) - -CGImageGetHeight(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetHeight, Csize_t, (Ptr{Void}, ), CGImageRef) - -CGImageGetRenderingIntent(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetRenderingIntent, UInt32, (Ptr{Void}, ), CGImageRef) - -CGImageGetShouldInterpolate(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetShouldInterpolate, Bool, (Ptr{Void}, ), CGImageRef) - -CGImageGetTypeID() = - ccall(:CGImageGetTypeID, Culonglong, (),) - -CGImageGetWidth(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetWidth, Csize_t, (Ptr{Void}, ), CGImageRef) - -CGImageRelease(CGImageRef::Ptr{Void}) = - ccall(:CGImageRelease, Void, (Ptr{Void}, ), CGImageRef) - -# Get pixel data -# See: https://developer.apple.com/library/mac/qa/qa1509/_index.html -CGImageGetDataProvider(CGImageRef::Ptr{Void}) = - ccall(:CGImageGetDataProvider, Ptr{Void}, (Ptr{Void}, ), CGImageRef) - -CGDataProviderCopyData(CGDataProviderRef::Ptr{Void}) = - ccall(:CGDataProviderCopyData, Ptr{Void}, (Ptr{Void}, ), CGDataProviderRef) - -CopyImagePixels(inImage::Ptr{Void}) = - CGDataProviderCopyData(CGImageGetDataProvider(inImage)) - -CFDataGetBytePtr{T}(CFDataRef::Ptr{Void}, ::Type{T}) = - ccall(:CFDataGetBytePtr, Ptr{T}, (Ptr{Void}, ), CFDataRef) - -CFDataGetLength(CFDataRef::Ptr{Void}) = - ccall(:CFDataGetLength, Ptr{Int64}, (Ptr{Void}, ), CFDataRef) - -CFDataCreate(bytes::Array{UInt8,1}) = - ccall(:CFDataCreate,Ptr{Void},(Ptr{Void},Ptr{UInt8},Csize_t),C_NULL,bytes,length(bytes)) - -end # Module diff --git a/src/ioformats/dummy.jl b/src/ioformats/dummy.jl deleted file mode 100644 index 99620bf7..00000000 --- a/src/ioformats/dummy.jl +++ /dev/null @@ -1,12 +0,0 @@ -import Images.imread, Images.imwrite - -function imread{S<:IO}(stream::S, ::Type{Images.Dummy}) - pixels = reshape(uint8(1:12), 3, 4) - Image(pixels, Compat.@compat Dict("colorspace" => "Gray", "spatialorder" => "xy")) -end - -function imwrite(img, filename::AbstractString, ::Type{Images.Dummy}) - open(filename, "w") do stream - println(stream, "Dummy Image") - end -end diff --git a/src/ioformats/libmagickwand.jl b/src/ioformats/libmagickwand.jl deleted file mode 100644 index 36604b9c..00000000 --- a/src/ioformats/libmagickwand.jl +++ /dev/null @@ -1,368 +0,0 @@ -module LibMagick - -using Colors, FixedPointNumbers, ..ColorVectorSpace, Compat - -import Base: error, size - -export MagickWand, - constituteimage, - exportimagepixels!, - getblob, - getimagealphachannel, - getimagecolorspace, - getimagedepth, - getnumberimages, - importimagepixels, - readimage, - resetiterator, - setimagecolorspace, - setimagecompression, - setimagecompressionquality, - setimageformat, - writeimage - - -# Find the library -depsfile = joinpath(dirname(@__FILE__),"..","..","deps","deps.jl") -versionfile = joinpath(dirname(@__FILE__),"..","..","deps","versioninfo.jl") -if isfile(depsfile) - include(depsfile) -else - error("Images not properly installed. Please run Pkg.build(\"Images\") then restart Julia.") -end -if isfile(versionfile) - include(versionfile) -end - -const have_imagemagick = isdefined(:libwand) - -# Initialize the library -if !have_imagemagick - function __init__() - warn("ImageMagick utilities not found. Install for more file format support.") - end -end - - -# Constants -# Storage types -const CHARPIXEL = 1 -const DOUBLEPIXEL = 2 -const FLOATPIXEL = 3 -const INTEGERPIXEL = 4 -const SHORTPIXEL = 7 -@compat IMStorageTypes = Union{UInt8, UInt16, UInt32, Float32, Float64} -storagetype(::Type{UInt8}) = CHARPIXEL -storagetype(::Type{UInt16}) = SHORTPIXEL -storagetype(::Type{UInt32}) = INTEGERPIXEL -storagetype(::Type{Float32}) = FLOATPIXEL -storagetype(::Type{Float64}) = DOUBLEPIXEL -storagetype{T<:Ufixed}(::Type{T}) = storagetype(FixedPointNumbers.rawtype(T)) -storagetype{CV<:Colorant}(::Type{CV}) = storagetype(eltype(CV)) - -# Channel types -type ChannelType - value::UInt32 -end -const UndefinedChannel = ChannelType(0x00000000) -const RedChannel = ChannelType(0x00000001) -const GrayChannel = ChannelType(0x00000001) -const CyanChannel = ChannelType(0x00000001) -const GreenChannel = ChannelType(0x00000002) -const MagentaChannel = ChannelType(0x00000002) -const BlueChannel = ChannelType(0x00000004) -const YellowChannel = ChannelType(0x00000004) -const AlphaChannel = ChannelType(0x00000008) -const MatteChannel = ChannelType(0x00000008) -const OpacityChannel = ChannelType(0x00000008) -const BlackChannel = ChannelType(0x00000020) -const IndexChannel = ChannelType(0x00000020) -const CompositeChannels = ChannelType(0x0000002F) -const TrueAlphaChannel = ChannelType(0x00000040) -const RGBChannels = ChannelType(0x00000080) -const GrayChannels = ChannelType(0x00000080) -const SyncChannels = ChannelType(0x00000100) -const AllChannels = ChannelType(0x7fffffff) -const DefaultChannels = ChannelType( (AllChannels.value | SyncChannels.value) &~ OpacityChannel.value ) - - -# Image type -const IMType = ["BilevelType", "GrayscaleType", "GrayscaleMatteType", "PaletteType", "PaletteMatteType", "TrueColorType", "TrueColorMatteType", "ColorSeparationType", "ColorSeparationMatteType", "OptimizeType", "PaletteBilevelMatteType"] -const IMTypedict = Dict([(IMType[i], i) for i = 1:length(IMType)]) - -const CStoIMTypedict = @compat Dict("Gray" => "GrayscaleType", "GrayA" => "GrayscaleMatteType", "RGB" => "TrueColorType", "ARGB" => "TrueColorMatteType", "CMYK" => "ColorSeparationType") - -# Colorspace -const IMColorspace = ["RGB", "Gray", "Transparent", "OHTA", "Lab", "XYZ", "YCbCr", "YCC", "YIQ", "YPbPr", "YUV", "CMYK", "sRGB"] -const IMColordict = Dict([(IMColorspace[i], i) for i = 1:length(IMColorspace)]) - -function nchannels(imtype::AbstractString, cs::AbstractString, havealpha = false) - n = 3 - if startswith(imtype, "Grayscale") || startswith(imtype, "Bilevel") - n = 1 - cs = havealpha ? "GrayA" : "Gray" - elseif cs == "CMYK" - n = 4 - else - cs = havealpha ? "ARGB" : "RGB" # only remaining variants supported by exportimagepixels - end - n + havealpha, cs -end - -# channelorder = ["Gray" => "I", "GrayA" => "IA", "RGB" => "RGB", "ARGB" => "ARGB", "RGBA" => "RGBA", "CMYK" => "CMYK"] - -# Compression -const NoCompression = 1 - -type MagickWand - ptr::Ptr{Void} -end - -function MagickWand() - wand = MagickWand(ccall((:NewMagickWand, libwand), Ptr{Void}, ())) - finalizer(wand, destroymagickwand) - wand -end - -destroymagickwand(wand::MagickWand) = ccall((:DestroyMagickWand, libwand), Ptr{Void}, (Ptr{Void},), wand.ptr) - -type PixelWand - ptr::Ptr{Void} -end - -function PixelWand() - wand = PixelWand(ccall((:NewPixelWand, libwand), Ptr{Void}, ())) - finalizer(wand, destroypixelwand) - wand -end - -destroypixelwand(wand::PixelWand) = ccall((:DestroyPixelWand, libwand), Ptr{Void}, (Ptr{Void},), wand.ptr) - -const IMExceptionType = Array(Cint, 1) -function error(wand::MagickWand) - pMsg = ccall((:MagickGetException, libwand), Ptr{UInt8}, (Ptr{Void}, Ptr{Cint}), wand.ptr, IMExceptionType) - msg = bytestring(pMsg) - relinquishmemory(pMsg) - error(msg) -end -function error(wand::PixelWand) - pMsg = ccall((:PixelGetException, libwand), Ptr{UInt8}, (Ptr{Void}, Ptr{Cint}), wand.ptr, IMExceptionType) - msg = bytestring(pMsg) - relinquishmemory(pMsg) - error(msg) -end - -function getsize(buffer, channelorder) - if channelorder == "I" - return size(buffer, 1), size(buffer, 2), size(buffer, 3) - else - return size(buffer, 2), size(buffer, 3), size(buffer, 4) - end -end -getsize{C<:Colorant}(buffer::AbstractArray{C}, channelorder) = size(buffer, 1), size(buffer, 2), size(buffer, 3) - -colorsize(buffer, channelorder) = channelorder == "I" ? 1 : size(buffer, 1) -colorsize{C<:Colorant}(buffer::AbstractArray{C}, channelorder) = 1 - -bitdepth{C<:Colorant}(buffer::AbstractArray{C}) = 8*eltype(C) -bitdepth{T}(buffer::AbstractArray{T}) = 8*sizeof(T) - -# colorspace is included for consistency with constituteimage, but it is not used -function exportimagepixels!{T}(buffer::AbstractArray{T}, wand::MagickWand, colorspace::ASCIIString, channelorder::ASCIIString; x = 0, y = 0) - cols, rows, nimages = getsize(buffer, channelorder) - ncolors = colorsize(buffer, channelorder) - p = pointer(buffer) - for i = 1:nimages - nextimage(wand) - status = ccall((:MagickExportImagePixels, libwand), Cint, (Ptr{Void}, Cssize_t, Cssize_t, Csize_t, Csize_t, Ptr{UInt8}, Cint, Ptr{Void}), wand.ptr, x, y, cols, rows, channelorder, storagetype(T), p) - status == 0 && error(wand) - p += sizeof(T)*cols*rows*ncolors - end - buffer -end - -# function importimagepixels{T}(buffer::AbstractArray{T}, wand::MagickWand, colorspace::ASCIIString; x = 0, y = 0) -# cols, rows = getsize(buffer, colorspace) -# status = ccall((:MagickImportImagePixels, libwand), Cint, (Ptr{Void}, Cssize_t, Cssize_t, Csize_t, Csize_t, Ptr{UInt8}, Cint, Ptr{Void}), wand.ptr, x, y, cols, rows, channelorder[colorspace], storagetype(T), buffer) -# status == 0 && error(wand) -# nothing -# end - -function constituteimage{T<:Unsigned}(buffer::AbstractArray{T}, wand::MagickWand, colorspace::ASCIIString, channelorder::ASCIIString; x = 0, y = 0) - cols, rows, nimages = getsize(buffer, channelorder) - ncolors = colorsize(buffer, channelorder) - p = pointer(buffer) - depth = bitdepth(buffer) - for i = 1:nimages - status = ccall((:MagickConstituteImage, libwand), Cint, (Ptr{Void}, Cssize_t, Cssize_t, Ptr{UInt8}, Cint, Ptr{Void}), wand.ptr, cols, rows, channelorder, storagetype(T), p) - status == 0 && error(wand) - setimagecolorspace(wand, colorspace) - status = ccall((:MagickSetImageDepth, libwand), Cint, (Ptr{Void}, Csize_t), wand.ptr, depth) - status == 0 && error(wand) - p += sizeof(T)*cols*rows*ncolors - end - nothing -end - -function getblob(wand::MagickWand, format::AbstractString) - setimageformat(wand, format) - len = Array(Csize_t, 1) - ptr = ccall((:MagickGetImagesBlob, libwand), Ptr{UInt8}, (Ptr{Void}, Ptr{Csize_t}), wand.ptr, len) - blob = pointer_to_array(ptr, convert(Int, len[1])) - finalizer(blob, relinquishmemory) - blob -end - -function pingimage(wand::MagickWand, filename::AbstractString) - status = ccall((:MagickPingImage, libwand), Cint, (Ptr{Void}, Ptr{UInt8}), wand.ptr, filename) - status == 0 && error(wand) - nothing -end - -function readimage(wand::MagickWand, filename::AbstractString) - status = ccall((:MagickReadImage, libwand), Cint, (Ptr{Void}, Ptr{UInt8}), wand.ptr, filename) - status == 0 && error(wand) - nothing -end - -function readimage(wand::MagickWand, stream::IO) - status = ccall((:MagickReadImageFile, libwand), Cint, (Ptr{Void}, Ptr{Void}), wand.ptr, Libc.FILE(stream).ptr) - status == 0 && error(wand) - nothing -end - -function readimage(wand::MagickWand, stream::Vector{UInt8}) - status = ccall((:MagickReadImageBlob, libwand), Cint, (Ptr{Void}, Ptr{Void}, Cint), wand.ptr, stream, length(stream)*sizeof(eltype(stream))) - status == 0 && error(wand) - nothing -end - -function writeimage(wand::MagickWand, filename::AbstractString) - status = ccall((:MagickWriteImages, libwand), Cint, (Ptr{Void}, Ptr{UInt8}, Cint), wand.ptr, filename, true) - status == 0 && error(wand) - nothing -end - -function size(wand::MagickWand) - height = ccall((:MagickGetImageHeight, libwand), Csize_t, (Ptr{Void},), wand.ptr) - width = ccall((:MagickGetImageWidth, libwand), Csize_t, (Ptr{Void},), wand.ptr) - return convert(Int, width), convert(Int, height) -end - -getnumberimages(wand::MagickWand) = convert(Int, ccall((:MagickGetNumberImages, libwand), Csize_t, (Ptr{Void},), wand.ptr)) - -nextimage(wand::MagickWand) = ccall((:MagickNextImage, libwand), Cint, (Ptr{Void},), wand.ptr) == 1 - -resetiterator(wand::MagickWand) = ccall((:MagickResetIterator, libwand), Void, (Ptr{Void},), wand.ptr) - -newimage(wand::MagickWand, cols::Integer, rows::Integer, pw::PixelWand) = ccall((:MagickNewImage, libwand), Cint, (Ptr{Void}, Csize_t, Csize_t, Ptr{Void}), wand.ptr, cols, rows, pw.ptr) == 0 && error(wand) - -# test whether image has an alpha channel -getimagealphachannel(wand::MagickWand) = ccall((:MagickGetImageAlphaChannel, libwand), Cint, (Ptr{Void},), wand.ptr) == 1 - - -function getimageproperties(wand::MagickWand,patt::AbstractString) - numbProp = Csize_t[0] - p = ccall((:MagickGetImageProperties, libwand),Ptr{Ptr{UInt8}},(Ptr{Void},Ptr{UInt8},Ptr{Csize_t}),wand.ptr,patt,numbProp) - if p == C_NULL - error("Pattern not in property names") - else - nP = convert(Int, numbProp[1]) - ret = Array(ASCIIString, nP) - for i = 1:nP - ret[i] = bytestring(unsafe_load(p,i)) - end - ret - - end -end - -function getimageproperty(wand::MagickWand,prop::AbstractString) - p = ccall((:MagickGetImageProperty, libwand),Ptr{UInt8},(Ptr{Void},Ptr{UInt8}),wand.ptr,prop) - if p == convert(Ptr{UInt8}, C_NULL) - possib = getimageproperties(wand,"*") - warn("Undefined property, possible names are \"$(join(possib,"\",\""))\"") - nothing - else - bytestring(p) - end -end - -# # get number of colors in the image -# magickgetimagecolors(wand::MagickWand) = ccall((:MagickGetImageColors, libwand), Csize_t, (Ptr{Void},), wand.ptr) - -# get the type -function getimagetype(wand::MagickWand) - t = ccall((:MagickGetImageType, libwand), Cint, (Ptr{Void},), wand.ptr) - # Apparently the following is necessary, because the type is "potential" - ccall((:MagickSetImageType, libwand), Void, (Ptr{Void}, Cint), wand.ptr, t) - 1 <= t <= length(IMType) || error("Image type ", t, " not recognized") - IMType[t] -end - -# get the colorspace -function getimagecolorspace(wand::MagickWand) - cs = ccall((:MagickGetImageColorspace, libwand), Cint, (Ptr{Void},), wand.ptr) - 1 <= cs <= length(IMColorspace) || error("Colorspace ", cs, " not recognized") - IMColorspace[cs] -end - -# set the colorspace -function setimagecolorspace(wand::MagickWand, cs::ASCIIString) - status = ccall((:MagickSetImageColorspace, libwand), Cint, (Ptr{Void},Cint), wand.ptr, IMColordict[cs]) - status == 0 && error(wand) - nothing -end - -# set the compression -function setimagecompression(wand::MagickWand, compression::Integer) - status = ccall((:MagickSetImageCompression, libwand), Cint, (Ptr{Void},Cint), wand.ptr, int32(compression)) - status == 0 && error(wand) - nothing -end - -function setimagecompressionquality(wand::MagickWand, quality::Integer) - 0 < quality <= 100 || error("quality setting must be in the (inclusive) range 1-100.\nSee http://www.imagemagick.org/script/command-line-options.php#quality for details") - status = ccall((:MagickSetImageCompressionQuality, libwand), Cint, (Ptr{Void}, Cint), wand.ptr, quality) - status == 0 && error(wand) - nothing -end - -# set the image format -function setimageformat(wand::MagickWand, format::ASCIIString) - status = ccall((:MagickSetImageFormat, libwand), Cint, (Ptr{Void}, Ptr{UInt8}), wand.ptr, format) - status == 0 && error(wand) - nothing -end - -# get the pixel depth -getimagedepth(wand::MagickWand) = convert(Int, ccall((:MagickGetImageDepth, libwand), Csize_t, (Ptr{Void},), wand.ptr)) - -# pixel depth for given channel type -getimagechanneldepth(wand::MagickWand, channelType::ChannelType) = convert(Int, ccall((:MagickGetImageChannelDepth, libwand), Csize_t, (Ptr{Void},UInt32), wand.ptr, channelType.value )) - -pixelsetcolor(wand::PixelWand, colorstr::ByteString) = ccall((:PixelSetColor, libwand), Csize_t, (Ptr{Void},Ptr{UInt8}), wand.ptr, colorstr) == 0 && error(wand) - -relinquishmemory(p) = ccall((:MagickRelinquishMemory, libwand), Ptr{UInt8}, (Ptr{UInt8},), p) - -# get library information -# If you pass in "*", you get the full list of options -function queryoptions(pattern::AbstractString) - nops = Cint[0] - pops = ccall((:MagickQueryConfigureOptions, libwand), Ptr{Ptr{UInt8}}, (Ptr{UInt8}, Ptr{Cint}), pattern, nops) - ret = Array(ASCIIString, nops[1]) - for i = 1:nops[1] - ret[i] = bytestring(unsafe_load(pops, i)) - end - ret -end - -# queries the value of a particular option -function queryoption(option::AbstractString) - p = ccall((:MagickQueryConfigureOption, libwand), Ptr{UInt8}, (Ptr{UInt8},), option) - bytestring(p) -end - -end - -LibMagick.have_imagemagick diff --git a/src/ioformats/nrrd.jl b/src/ioformats/nrrd.jl deleted file mode 100644 index 303a7c80..00000000 --- a/src/ioformats/nrrd.jl +++ /dev/null @@ -1,431 +0,0 @@ -module NRRD - -using Images, SIUnits, SIUnits.ShortUnits, Compat -import Images: imread, imwrite -import Zlib -import FixedPointNumbers - -typedict = @compat Dict( - "signed char" => Int8, - "int8" => Int8, - "int8_t" => Int8, - "uchar" => UInt8, - "unsigned char" => UInt8, - "uint8" => UInt8, - "uint8_t" => UInt8, - "short" => Int16, - "short int" => Int16, - "signed short" => Int16, - "signed short int" => Int16, - "int16" => Int16, - "int16_t" => Int16, - "ushort" => UInt16, - "unsigned short" => UInt16, - "unsigned short int" => UInt16, - "uint16" => UInt16, - "uint16_t" => UInt16, - "int" => Int32, - "signed int" => Int32, - "int32" => Int32, - "int32_t" => Int32, - "uint" => UInt32, - "unsigned int" => UInt32, - "uint32" => UInt32, - "uint32_t" => UInt32, - "longlong" => Int64, - "long long" => Int64, - "long long int" => Int64, - "signed long long" => Int64, - "signed long long int" => Int64, - "int64" => Int64, - "int64_t" => Int64, - "ulonglong" => UInt64, - "unsigned long long" => UInt64, - "unsigned long long int" => UInt64, - "uint64" => UInt64, - "uint64_t" => UInt64, - "float16" => Float16, - "float" => Float32, - "double" => Float64) - -spacedimdict = @compat Dict( - "right-anterior-superior" => 3, - "ras" => 3, - "left-anterior-superior" => 3, - "las" => 3, - "left-posterior-superior" => 3, - "lps" => 3, - "right-anterior-superior-time" => 4, - "rast" => 4, - "left-anterior-superior-time" => 4, - "last" => 4, - "left-posterior-superior-time" => 4, - "lpst" => 4, - "scanner-xyz" => 3, - "scanner-xyz-time" => 4, - "3d-right-handed" => 3, - "3d-left-handed" => 3, - "3d-right-handed-time" => 4, - "3d-left-handed-time" => 4) - -function myendian() - if ENDIAN_BOM == 0x04030201 - return "little" - elseif ENDIAN_BOM == 0x01020304 - return "big" - end -end - -function imread{S<:IO}(stream::S, ::Type{Images.NRRDFile}; mmap=:auto) - version = ascii(read(stream, UInt8, 4)) - skipchars(stream,isspace) - header = Dict{ASCIIString, UTF8String}() - props = Dict{ASCIIString, Any}() - comments = Array(ASCIIString, 0) - # Read until we encounter a blank line, which is the separator between the header and data - line = strip(readline(stream)) - while !isempty(line) - if line[1] != '#' - key, value = split(line, ":") - if !isempty(value) && value[1] == '=' - # This is a NRRD key/value pair, insert straight into props - props[key] = value[2:end] - else - header[lowercase(key)] = strip(value) - end - else - cmt = strip(lstrip(line, collect("#"))) - if !isempty(cmt) - push!(comments, cmt) - end - end - line = strip(readline(stream)) - end - # Fields that go straight into the properties dict - if haskey(header, "content") - props["content"] = header["content"] - end - # Check to see whether the data are in an external file - sdata = stream - if haskey(header, "data file") - path = dirname(stream2name(sdata)) - sdata = open(joinpath(path, header["data file"])) - elseif haskey(header, "datafile") - path = dirname(stream2name(sdata)) - sdata = open(joinpath(path, header["datafile"])) - end - if in(header["encoding"], ("gzip", "gz")) - sdata = Zlib.Reader(sdata) - end - # Parse properties and read the data - nd = parse(Int, header["dimension"]) - sz = parse_vector_int(header["sizes"]) - length(sz) == nd || error("parsing of sizes: $(header["sizes"]) is inconsistent with $nd dimensions") - T = typedict[header["type"]] - local A - need_bswap = haskey(header, "endian") && header["endian"] != myendian() && sizeof(T) > 1 - - can_mmap = header["encoding"] == "raw" && !need_bswap - - if mmap == true && (!can_mmap) - error("Cannot use memory-mapped for reading a non-raw or bswapped file") - end - - do_mmap = can_mmap && (prod(sz) > 10^8) && (mmap == :auto) - do_mmap |= can_mmap && (mmap == true) - - if do_mmap - # Use memory-mapping for large files - fn = stream2name(sdata) - datalen = div(filesize(fn) - position(sdata), sizeof(T)) - strds = [1,cumprod(sz)] - k = length(sz) - sz[k] = div(datalen, strds[k]) - while sz[k] == 0 && k > 1 - pop!(sz) - k -= 1 - sz[k] = div(datalen, strds[k]) - end - A = mmap_array(T, tuple(sz...), sdata, position(sdata)) - elseif header["encoding"] == "raw" || in(header["encoding"], ("gzip", "gz")) - A = read(sdata, T, sz...) - if need_bswap - A = reshape([bswap(a) for a in A], size(A)) - end - else - error("\"", header["encoding"], "\" encoding not supported.") - end - isspatial = trues(nd) - # Optional fields - if haskey(header, "kinds") - kinds = split(header["kinds"], " ") - length(kinds) == nd || error("parsing of kinds: $(header["kinds"]) is inconsistent with $nd dimensions") - for i = 1:nd - k = kinds[i] - if k == "time" - props["timedim"] = i - isspatial[i] = false - elseif in(k, ("3-color","4-color","list","point","vector","covariant-vector","normal","2-vector","3-vector","4-vector","3-gradient","3-normal","scalar","complex","quaternion")) - props["colordim"] = i - props["colorspace"] = k - isspatial[i] = false - elseif k == "RGB-color" - props["colordim"] = i - props["colorspace"] = "RGB" - isspatial[i] = false - elseif k == "HSV-color" - props["colordim"] = i - props["colorspace"] = "HSV" - isspatial[i] = false - elseif k == "RGBA-color" - props["colordim"] = i - props["colorspace"] = "RGBA" - isspatial[i] = false - elseif contains(k, "matrix") - error("matrix types are not yet supported") - end - end - end - if !haskey(props, "colordim") - props["colorspace"] = "Gray" - end - if haskey(header, "min") || haskey(header, "max") - mn = typemin(T) - mx = typemax(T) - if haskey(header, "min") - mn = parse(T, header["min"]) - end - if haskey(header, "max") - mx = parse(T, header["max"]) - end - props["limits"] = (mn, mx) - end - if haskey(header, "labels") - lbls = parse_vector_strings(header["labels"]) - props["spatialorder"] = lbls[isspatial] - else - props["spatialorder"] = [string(convert(Char, 97+(i+22)%26)) for i = 1:sum(isspatial)] - end - spacedim = sum(isspatial) - if haskey(header, "space") - props["space"] = header["space"] - spacedim = spacedimdict[lowercase(header["space"])] - spacedim == sum(isspatial) || error("spacedim $spacedim disagrees with isspatial=$isspatial") - elseif haskey(header, "space dimension") - spacedim = int(header["space dimension"]) - spacedim == sum(isspatial) || error("spacedim $spacedim disagrees with isspatial=$isspatial") - end - @compat units = Array(Union{SIUnits.SIUnit,SIUnits.SIQuantity}, 0) - if haskey(header, "space units") - ustrs = parse_vector_strings(header["space units"]) - length(ustrs) == spacedim || error("parsing of space units: $(header["space units"]) is inconsistent with $spacedim space dimensions") - for i = 1:spacedim - try - push!(units, eval(symbol(ustrs[i]))) - catch - evalworked = false - warn("Could not evaluate unit string $(ustrs[i])") - end - end - if length(units) < spacedim - units = Array(SIUnits.SIQuantity, 0) # Don't use any units - props["spaceunits"] = ustrs # ...but store the string representation - end - end - if haskey(header, "space directions") - # space directions are per-axis, but can be "none" - sd = split(header["space directions"], " ") - length(sd) == nd || error("parsing of space directions: $(header["space directions"]) is inconsistent with $nd dimensions") - sdf = Array(Any, 0) - for i = 1:nd - if sd[i] == "none" - isspatial[i] && error("Dimension $i is spatial, but has space directions \"none\".") - else - v = parse_vector_float(sd[i][2:end-1]) - if !isempty(units) - vu = [v[i]*units[i] for i = 1:spacedim] - push!(sdf, vu) - else - push!(sdf, v) - end - end - end - props["spacedirections"] = sdf - # If spacedirections is diagonal, put that into pixelspacing - have_pixelspacing = true - for i = 1:length(sdf) - v = sdf[i] - for j = 1:spacedim - if i != j - have_pixelspacing &= 0*v[j] == v[j] # this is units-safe - end - end - end - if have_pixelspacing - ps = [sdf[i][i] for i = 1:spacedim] - props["pixelspacing"] = ps - end - elseif haskey(header, "spacings") - ps = parse_vector_float(header["spacings"]) - length(ps) == nd || error("parsing of spacings: $(header["spacings"]) is inconsistent with $nd dimensions") - pss = ps[isspatial] - if !isempty(units) - vu = [pss[i]*units[i] for i = 1:length(pss)] - props["pixelspacing"] = vu - else - props["pixelspacing"] = pss - end - end - if !isempty(comments) - props["comments"] = comments - end - Image(A, props) -end - -function imwrite(img, sheader::IO, ::Type{Images.NRRDFile}; props::Dict = Dict{ASCIIString,Any}()) - println(sheader, "NRRD0001") - # Write the datatype - T = get(props, "type", eltype(data(img))) - if T<:AbstractFloat - println(sheader, "type: ", (T == Float32) ? "float" : - (T == Float64) ? "double" : - (T == Float16) ? "float16" : - error("Can't write type $T")) - elseif eltype(T) <: FixedPointNumbers.UfixedBase - # we don't want to write something like "type: ufixedbase{uint8,8}", so fix it - T = FixedPointNumbers.rawtype(eltype(eltype(img))) - println(sheader, "type: ", lowercase(string(T))) - else - println(sheader, "type: ", lowercase(string(T))) - end - # Extract size and kinds - sz = get(props, "sizes", size(img)) - kinds = ["space" for i = 1:length(sz)] - td = timedim(img) - if td != 0 - kinds[td] = "time" - end - cd = colordim(img) - if cd != 0 - if colorspace(img) == "RGB" - kinds[cd] = "RGB-color" - elseif size(img, cd) == 3 - kinds[cd] = "3-color" - else - kinds[cd] = "list" - end - end - kinds = get(props, "kinds", kinds) - # Write size and kinds - println(sheader, "dimension: ", length(sz)) - print(sheader, "sizes:") - for z in sz - print(sheader, " ", z) - end - print(sheader, "\nkinds:") - for k in kinds - print(sheader, " ", k) - end - print(sheader, "\n") - println(sheader, "encoding: ", get(props, "encoding", "raw")) - println(sheader, "endian: ", get(props, "endian", ENDIAN_BOM == 0x04030201 ? "little" : "big")) - ps = get(props, "pixelspacing", pixelspacing(img)) - ps = convert(Vector{Any}, ps) - index = sort([cd, td]) - index[1] > 0 && insert!(ps, index[1], "nan") - index[2] > 0 && insert!(ps, index[2], "nan") - print(sheader, "spacings:") - printunits = false - for x in ps - if isa(x, SIUnits.SIQuantity) - printunits = true - print(sheader, " ", x.val) - else - print(sheader, " ", x) - end - end - print(sheader,"\n") - if printunits - print(sheader, "space units:") - for x in ps - if isa(x, SIUnits.SIQuantity) - print(sheader," \"", strip(string(SIUnits.unit(x))), "\"") - end - end - print(sheader, "\n") - end - datafilename = get(props, "datafile", "") - if isempty(datafilename) - datafilename = get(props, "data file", "") - end - if isempty(datafilename) - write(sheader, "\n") - write(sheader, data(img)) - else - println(sheader, "data file: ", datafilename) - if !get(props, "headeronly", false) - open(datafilename, "w") do file - write(file, data(img)) - end - end - end - sheader -end - -function parse_vector_int(s::AbstractString) - ss = split_nokeep(s, r"[ ,;]") - v = Array(Int, length(ss)) - for i = 1:length(ss) - v[i] = parse(Int, ss[i]) - end - return v -end - -function parse_vector_float(s::AbstractString) - ss = split_nokeep(s, r"[ ,;]") - v = Array(Float64, length(ss)) - for i = 1:length(ss) - v[i] = parse(Float64, ss[i]) - end - return v -end - -function parse_vector_strings(s::AbstractString) - (first(s) == '"' && last(s) == '"') || error("AbstractStrings must be delimited with quotes") - split(s[2:end-1], "\" \"") -end - -if VERSION < v"0.4-dev" - split_nokeep(a, b) = split(a, b, false) -else - split_nokeep(a, b) = split(a, b, keep=false) -end - -function stream2name(s::IO) - name = s.name - if !startswith(name, " Micro*Meter, "mm" => Milli*Meter, "s" => Second) -function parse_quantity(s::AbstractString, strict::Bool = true) - # Find the last character of the numeric component - m = match(r"[0-9\.\+-](?![0-9\.\+-])", s) - if m == nothing - error("AbstractString does not have a 'value unit' structure") - end - val = float64(s[1:m.offset]) - ustr = strip(s[m.offset+1:end]) - if isempty(ustr) - if strict - error("AbstractString does not have a 'value unit' structure") - else - return val - end - end - val * _unit_string_dict[ustr] -end - -end diff --git a/test/io.jl b/test/io.jl deleted file mode 100644 index 66374a0f..00000000 --- a/test/io.jl +++ /dev/null @@ -1,151 +0,0 @@ -using FactCheck, Images, Colors, FixedPointNumbers - -facts("IO") do - workdir = joinpath(tempdir(), "Images") - if !isdir(workdir) - mkdir(workdir) - end - - context("Gray png") do - a = rand(2,2) - aa = convert(Array{Ufixed8}, a) - fn = joinpath(workdir, "2by2.png") - Images.imwrite(a, fn) - b = Images.imread(fn) - @fact convert(Array, b) --> aa - Images.imwrite(aa, fn) - b = Images.imread(fn) - @fact convert(Array, b) --> aa - aaimg = Images.grayim(aa) - open(fn, "w") do file - writemime(file, MIME("image/png"), aaimg, minpixels=0) - end - b = Images.imread(fn) - @fact b --> aaimg - aa = convert(Array{Ufixed16}, a) - Images.imwrite(aa, fn) - b = Images.imread(fn) - @fact convert(Array, b) --> aa - aa = Ufixed12[0.6 0.2; - 1.4 0.8] - open(fn, "w") do file - writemime(file, MIME("image/png"), Images.grayim(aa), minpixels=0) - end - b = Images.imread(fn) - @fact Images.data(b) --> Ufixed8[0.6 0.2; - 1.0 0.8] - end - - context("Color") do - fn = joinpath(workdir, "2by2.png") - img = Images.colorim(rand(3,2,2)) - img24 = convert(Images.Image{RGB24}, img) - Images.imwrite(img24, fn) - b = Images.imread(fn) - imgrgb8 = convert(Images.Image{RGB{Ufixed8}}, img) - @fact Images.data(imgrgb8) --> Images.data(b) - end - - context("Writemime's use of restrict") do - abig = Images.grayim(rand(UInt8, 1024, 1023)) - fn = joinpath(workdir, "big.png") - open(fn, "w") do file - writemime(file, MIME("image/png"), abig, maxpixels=10^6) - end - b = Images.imread(fn) - @fact Images.data(b) --> convert(Array{Ufixed8,2}, Images.data(Images.restrict(abig, (1,2)))) - end - - context("More writemime tests") do - a = Images.colorim(rand(UInt8, 3, 2, 2)) - fn = joinpath(workdir, "2by2.png") - open(fn, "w") do file - writemime(file, MIME("image/png"), a, minpixels=0) - end - b = Images.imread(fn) - @fact Images.data(b) --> Images.data(a) - - abig = Images.colorim(rand(UInt8, 3, 1021, 1026)) - fn = joinpath(workdir, "big.png") - open(fn, "w") do file - writemime(file, MIME("image/png"), abig, maxpixels=10^6) - end - b = Images.imread(fn) - @fact Images.data(b) --> convert(Array{RGB{Ufixed8},2}, Images.data(Images.restrict(abig, (1,2)))) - - # Issue #269 - abig = Images.colorim(rand(UInt16, 3, 1024, 1023)) - open(fn, "w") do file - writemime(file, MIME("image/png"), abig, maxpixels=10^6) - end - b = Images.imread(fn) - @fact Images.data(b) --> convert(Array{RGB{Ufixed8},2}, Images.data(Images.restrict(abig, (1,2)))) - end - - context("Colormap usage") do - datafloat = reshape(linspace(0.5, 1.5, 6), 2, 3) - dataint = round(UInt8, 254*(datafloat .- 0.5) .+ 1) # ranges from 1 to 255 - # build our colormap - b = RGB(0,0,1) - w = RGB(1,1,1) - r = RGB(1,0,0) - cmaprgb = Array(RGB{Float64}, 255) - f = linspace(0,1,128) - cmaprgb[1:128] = [(1-x)*b + x*w for x in f] - cmaprgb[129:end] = [(1-x)*w + x*r for x in f[2:end]] - img = Images.ImageCmap(dataint, cmaprgb) - Images.imwrite(img,joinpath(workdir,"cmap.jpg")) - cmaprgb = Array(RGB, 255) # poorly-typed cmap, issue #336 - cmaprgb[1:128] = [(1-x)*b + x*w for x in f] - cmaprgb[129:end] = [(1-x)*w + x*r for x in f[2:end]] - img = Images.ImageCmap(dataint, cmaprgb) - Images.imwrite(img,joinpath(workdir,"cmap.pbm")) - end - - context("Alpha") do - c = reinterpret(Images.BGRA{Ufixed8}, [0xf0884422]'') - fn = joinpath(workdir, "alpha.png") - Images.imwrite(c, fn) - C = Images.imread(fn) - # @test C[1] == c[1] # disabled because Travis has a weird, old copy of ImageMagick for which this fails (see #261) - Images.imwrite(reinterpret(ARGB32, [0xf0884422]''), fn) - D = Images.imread(fn) - # @test D[1] == c[1] - end - - context("3D TIFF (issue #307)") do - A = Images.grayim(rand(0x00:0xff, 2, 2, 4)) - fn = joinpath(workdir, "3d.tif") - Images.imwrite(A, fn) - B = Images.imread(fn) - @fact A --> B - end - - context("Clamping (issue #256)") do - A = grayim(rand(2,2)) - A[1,1] = -0.4 - fn = joinpath(workdir, "2by2.png") - @fact_throws InexactError Images.imwrite(A, fn) - Images.imwrite(A, fn, mapi=Images.mapinfo(Images.Clamp, A)) - B = Images.imread(fn) - A[1,1] = 0 - @fact B --> map(Ufixed8, A) - end - - @unix_only context("Reading from a stream (issue #312)") do - fn = joinpath(workdir, "2by2.png") - io = open(fn) - img = Images.imread(io, Images.ImageMagick) - close(io) - @fact isa(img, Images.Image) --> true - end - - @unix_only context("Reading from a byte array (issue #279)") do - fn = joinpath(workdir, "2by2.png") - io = open(fn) - arr = readbytes(io) - close(io) - img = Images.imread(arr, Images.ImageMagick) - @fact isa(img, Images.Image) --> true - end -end diff --git a/test/io/small.nrrd b/test/io/small.nrrd deleted file mode 100644 index 695408e5e5186002879232b4dd9821d3c9d49b9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4296 zcmY+Gc{mnm_s2;nk0m56iuPqniqcQhsLxT;RMfN$jY2#`c*G+ulC4NZ`=-)5HSNo^ zzD?4U#I#{rjU+{usEHQh_q^}>`{#FE_jTRpzQ1R=?{l5&dyd=GsV;VQb`AzTZA29k z7OYe&ZQL|>HvWOZN*jMwc!-bMCL&Df8|WYC>!S`-h1&S2oiy6>)ao#&!GqOGWr%Hr zDl*(xsZkD4+J-9CgG0l^{RaQn)^?scB-lW`I85ne;~%W@Q5*OLhA2ZLG>)8X>WC`=WhR)ztAmxAqp!*@Ff_o) zCfq0L|3aw30|NpzDjK){c5h%X>5`6YF^uN?mZg|A+LKxuNnwi}?|+y;_Z7QYslSZ@ ziM{c9ts^-~3)#9hj=b7LrmPyn=@Cl_ZT}PZ-@rEOIKs5Y(_^-_^jh0fHo0Hm+|V@y zRqUoNDVFyRfwVmlir4TJBqn<@QBjX=WGTuSZNN8&o9%*)6{za?>Zd7s(V)%u%VvauWk_a%0PNGf2BwDGtTZemXpgD64=X) zht2VnSM`;~>DL+Qt1T7fUr9TE7Kb`h`FN;-^8+iH*u0*deeo{$-MHQpZw2_AK_t@{T6gS&7tobI4$mD5UP8rUDKEWIu(^b5(FEcdjIKx9e zknliHO0DN$?HtY2^5qmRk7Z=1wOn{pN9c_L5>6B_IsG0Bb8fKK%R(ldjpws&1ooau zG>-LSQd0pPee$sTuC-|G{)avhE%^M|T1@-2lg<@t9IFQM-Ti1j<)6jlQAg=FOx3Y@Pp|9Rh zPG5etp2xttq4>Bg!v0PSiy~vmXs4$5vAH-+wUE4&1^lA!LC4aWIJK#t!x|eEp$8c=8@g`OHt5PdMV9ifup=ON~d;er7U-J@Sa}@tnw~4fN{# z1<&?HMCG1D-{1+AU3T(w*>I+rBrxH#rry{7O_@s#4@`;}rTD;f4|6&BwX@8wslc;$ z41I!Tv2&r3SiaTdW~+|W>}Vy8zu)KAW?f-b4vqa3lHO8CkCCB7eQ9Kl@jZ-Z{>9Ye z2Pt;%Acrl?L@ch5;9@STEB@y7!pm5^))xzvFUfnq!(~Gv4GMoo+k2vFo{UfGN?yMh z#n)~-P|ebp=+QSBlod$8Za-X9;aq+d&*=^mDOxm-Y%72C99A&@ZVPRCH*w7L6>ZZ) z=)V7F0)BR;WZI7$=xjsLhzuNNt;eF`6XS;}q-U>pjHx_M=Ho>Kg$8i3gBRYTTu6^i z;UCAvT-;tyhE5~t>F@cPb`+1WLR{V)C8TmVCr)o;_`M$FYpvu)^fUTQJBEc-1%)?t z#H`~>a=Wz?y$C1TXvGt?&Vzn05;Po9%Ny7CJo3ED`s!BlI>JUuEQ*Niq${!hKcVWj zgy+s_-1RuZ26X{LVzL=wW+)}e*0NhWm+CGRw4P=qd)7||rxn~CcommFTFG)#LwWMN z4xgmna?Ji7D_zSt?4v8cT<9#{4xNj3brW@E29k014tdUn7`f)~vfffQr!*1vJclu_ zv}M|j7Q~{HSPc)L=;%5w%t@l9Xd#FDu0ee$il-aGXzd@*(gW$Z|6(S;9lM0OZy1Zy z26NnY1_^nyI5j?rfbvZ!7sT@Q-6on#vswDMfp7ji$CfwKa8SGPF<>>(tL8I7JDC*@ zacme8#fW*P5|Z_RtF4=eTvfxk$&eH%J%&qc{h&VY;(?p-Zmd1@WKYyTqE^eq3Zd&a&pD_LSzz^1)gGTV9`C41dz zyUUK>brML>pT_$|YYCdYp5zW1Y|9qDt=E<7r?kamb}X{Yg0Ut3ykFj%H_zsh7WXqJ zbrRXTVIr1`Z}Y47KfHR|#DbI|OsUIYbq{aSUDna*MJQRHqL{a9Gj|Uf$*J=ea&Xsc z^4b~830D<&FZE}o#WZ$r7=fAXD)jI8lWlU4$a~tdbI?s{Oci1ssu0&bF|0_ONYGX# zE%z1>p1KsBypx#OWHH&Km25k0E(_Mz&^~QZWxpk8bS?uUS5OoIR*zDccJl>}A3k6_;0lV-wLBQuN_G~T%jSCp6!xm- z)DmaxL4k_R|nBmDKY>c$W+^V@J?i!(EmMejKW-AZFV&veWdW zY)mry%F}6VOk(or81_VLMWxz^f$ehI#`Ki@k*%an`U^Z~+`wgZ43BRFV6}D=T0K*6 zuKNj>L-RNnVj?}Pt`S^hB9C3oB_OGib*|Gn@0G-=8QVCeUV&@l5^_8=b5O`xWS5}~ zKC3O$FDb;Rrd=eq@~rBN8&tTnu5@qoPcb&NY; zF3;WD%7T!Ke40?jS8sFK-CiMAzA=%p!xrOi@h9CY@3F?R9_1i2ITvXqA+u^ZlvB;M zGEKkH{LgZ0Igf|EqiuUH(hJ8@S>=z_IiX%NXT-0H<*wrxy4odTIA=2|do7uAw2tph zQ&@l0k1U;Jij$*w?BvA9`70S3Gn#ITSJ3?ME-!l=p>nl`JDvR4k?h3CT`LJVy^zks zw{RzEEqZ<2G2Q%loWpf$`$kCRLqY5yMyG>iiLDI9JoZy&Wsj%#h$@o54RIaC>Dx0)=J*jNc zlKS5t5S*hggM8lM?N>?45N+8O@FQ0BF8EEYhFj!+V8 zwSmc+*+{E22&XhnJ%6kr+^@Z88=XNCPTcY* zWbSQX_cb@VWyj!cXUpEaM3!9j2(Msu%!IX`TFLGP?Dy!vb?xBGlx?zKvS2dMe_K7n$Jf%uiEn6TMEtgYJ18uJ_u zA2`iWkE87Q<_7x`6w)R;7!S=n;d^r?0Sb-lW(MW{BNXn*B6^Xt>ylm)5P?@gK9(&o?VjIHfuDwalu@@<;}ULYxvwZ z8ULd33>iG1BMKckIH|R4+p>}UOQLwB$@A)A?QypmOuKV)xYm6E3pzW}+x}ma#1*h_ z>R%i_o(vmO$-lmZ@p(UzShgM0L``os9#2}>J9b(;r*nNRulHVKT)$Bq-!`4;|BR#L zObTX?5-`gCo_XP0XtT7VT#vSvFtA5{V*X_x~cSyvBB%TrerTr$&SQGa%*CkykRV7N3JH&YzB`%K&n+FOB7C6&sIp!#2&KM z{W2GaCg5Mbm)h6}>W2M>-l;&mMyw+y&XbACdIpA+uwa^=Seid$U&3t0wZi`vrQ!T- z4ml3CJo#+_uD#7m-@sVD6UwL5X#pa2-_-joPA&S+cluo4XV=GpkI#R5i zhia3Sqz8XxYM=8wyb#47Q=MqC>C2}Mhp_D4Mfz^8XYac^guZJhJzJWwu6o7!gNAZ? z?Q(wW>B7^ND9S2(OXJkrjGC{I^0H=qLP3emAF^jz;s^~XRh63Rgn{4BDJM=i;>*x*i4CjXNkT16^k5Wnb5V3 zG|j(5pWWZk(7#8GbdlFT+ffiU43~ZDSyt}I=S#cT+T=rpB8qNtQ(5HI1(Wn@wgi?? z-Xn>mGtQ`*Jc-Dh$b_mn=#O>Bu1_3o>%;iotANUDI&MI-}q_BFSNXhe=KObex;Z;GeWaWAA_T`n{F8e`|?xul8b59*kXOe|~x##@D>_cs%PU zKe#C*-%CS^dh5x;b6-fFTZ7v^g*Y{jMOH>iS=5nB`-E1ogj_Aj>HZ)UJ@7Woc08S<+) zyLPW7aQA%vv|332+M&#KT!HO_a8`swklsF+qUWY!KSd?E@k{w5*qV+d)3I;eg#Nu) zh84#$XXRKvx40Ad*gy^*|HR>tYA$+@#{0u6Qfys$TNA=d=XrFW8ODgLNPe`u&%YVk zvL;F)oT;Mf-&m5WBh{MQk@7Yeg9$6>v&9>oxmBc{D#aj8TguiH)9|XZ92`2Gxsl!^ z*~W8x`zCfctYkqO19@eqC(rKI68)kMbNR-Mj29epPhy~7EUOJiVKzOE0_$9&tX~uI zvVoo!-|;jnBsAwVy6s+2(RnwsN=M*k6wQQhYQHD`OQ~ZuPmBr~t^CYX4^uhaY$3C& z%ki`crXbT&%Y5YMcX{`lVj|wF8dn0oUA7MEC zAEulS#_rj>nP$96uZ$wy5ie7FfP+68! za92}II=&^RYkSf8-JZ4@QG}*=@WY#EH6v>H;9SQu&xdTPY9sG|?xwJ&v(CIG-WmS&TH%m*O}p*{jH*s&hG7ZkDodlPlP-<6-}sIR4c})*9=} zi`TWxjkS>zwvSlvT*}e8+VaO`3;A*AJQP(;)RwlB^z#qMbtu5VIh(ij=CUomi6yVI z8T(ElZg*M{RVT3=;YZ=|6fVz+rL}N5M|&p_d?b{Yo0p*F8^!8FX}JGkA{S0vCAjwz zRwfVPxMkN5$Rzw5>@Z4G$WQG%$l(r8 z`CmbM=@VRv#qeKP>?hng70HU>J5daGCZnbZt3E~8kFI1(CzW_?uH~nrn&R#90|yi- zjJoc_yTbV>`&1%&1ekxu;nh5nBWH11 zGlu<}Ct|+xK7V@u$GeYBER7$+e`m_nyFfn6N*jN!!auUmvx&mYv&>rjlG{Fh^gCfL|F^57bg@?N z5(;o0p&>zz#`430LV^aFOB-)padLdaxl$cDad8qZ)28qyX&zrK=d$y49OwIQSLVUFOj~9H}TLJoOe?$vRRx zHjV>jX*4#*;yNareZTJ@C}<1q2ChXfyocnCY9npa-rzay4vrhcd49(a%fzi{^oYly zb_R||7IHDbNUSYyvAEDko;#b0Uu*>_&QrPM70ZTcshkO3hjZg9vOUy2DBwJ@M_&e= zSIE?>N-^l6A)B{MW`I=)OK0!E-)%CgW?cymyuu#e8j}5tWs_DXsqXTCqNyd6uKbZx zjgh3~t;09LTrSQxl#Zt#aqibj4m@Zt-80I`jISX0-A&#aETOBFnro^j zcGr`o0ay4sp^|2AQ`u{#l}5Wz#cv2+<6gZ`Xt1lelHlY6n#+=cSlmpGGkh85fHu-i`|^X`{Y7MV%Xh)}kuFXU&`j{IV6&adbY$k@wNF8z4RM%UB%#C*|hdF>>mKs$vuQm02X$>qteDhScA9 z!s2XQ88G(~-aZw?4^c>}->+EKJK{4@S7MVYIc45ov}T$}Li!donw}F{o=bLJ2U%Na zC|S>@)2*|%EPbsbe-%E!L-!uzzJ9`{-M{4BKSi8UN0hq^r00-BYEG9?ux}AtYsT|1 zH=cBZjjZ(Z!g1n8qUX4?BValf6USka^O9Tj8Tej~;8xBW_8Ph3VxNls$OSC6+>EQb z8)=mIW1p<{^OtIt`Iw2q0QFr69n7aQ>}xQKb7oVyVLf9nB~$$RGfm@961nyT8T%X9 zd&`BcS>bpO9?1UO7*^e!&n)9a+ECB>>5n;_s4eTVttIYLGKofzekh({byHAgPiFYQ zFdp?O^m}YbI&{>9h z9A{s@I~<5sO53c(c&Pit{JUFlY*9+zKtnN#H`23BL} z{D26fep2Lgf#mMG(rtj2JbrMN@IDU+8tIQ`=U7r_jv*&30`7w2%R`%;!#*kNP)KZ+ysIWXlPj-HHz z%}M0l-i}l5uf&w@#5hKst%gn{FZsl7)oU#3Yk0r^7UO>y&B@fMO#N>>#pmKNc@~X9 z*3T?lww<=CJId`aD_P=lgx4Qm;-dD=_3RB?S?$M(lLt7G5lOvm9>G?vMCzB)koSaT zgYxKPqLh)<-MOw4N!7k(9PZ-47ppJ$EosDeOAg2CUsE*gDPuYm^E9N5i{9~WkcN1_>?GZ;RB`BEEh!$ZE8l0l J=f8h4_C$xw(innIz0N{NclM3hn~G|1E> zl1e0`LMbBe{@+{gt@YMf`<%7cx4ym3Ui;g>;d7_c?e+Eb4TPg&w*^`#282iZZ4DF- z2nh@1MTUg)EEJ7}BSYc>BP|q7{^t?i62c4MPb0Va`Un2McN9NKIFRQb9uUF{vQXUa zyMsRq2=V1FvNa?siofiCa`-WRwt=qx{|%lm@4q8~iqX7~D1J~mO!;@Q;`f5bMS|z$HDtjqmJZ$352>u*nO$ifSF96vA2yp zrp9%bT>8bv)4F59-Re|)D7eMhB1p$)+sv6IrY>mdI`o-)or4Jh*JH_7Y;dbyc8Ae5 zIvNjXMAqM6AV%%C%|NRy3{xw&KR!Xlg&3K~`4`yeZXB|VoLz_PWbdxZA|<#79qpf) zvPXP%T9fo?dzAhZk*g}9pj;s1xqP4t_H5GZ_l*X`Mc>zxF3~V@E8B;5(H_oWhch~~ z*%0y0xaKWH!Uk{7JF~5H6nM^Y?QA6QZ=v2`#SsQ{?^on3cy5cdeQ4-lT3biYS%mh8dtrqt1Fo zx*f`bhgZ0WQt*X+_5IU>WX#&izOqp;M5K~xtmz*L+ET-a-x8U4FyGUrMO+JCsOOI@ z8zf`nVZ+x91654NN$0THmMA&C@^-g{5_)J)Qe4~V*y~l>ovr7BC=y}sWCR5rs^qVM z2}De|8Dx!CSc7eR;HpU{123D#G?cH>v0o?aLE0KF^3&`RmJ=M|v0qFq!JLTr7l$k= zuc?8+EBoqlOArltC$}fvq+z=GYv1caH;hX8-yRdPf>Bd_^KFhQY~)w+Y{PY7P+zoh z%WXD#62*mbhAeTxol>I@p^|$wka0V?v$SW>4;U*S^4jiX}E0C?Je_#174Q) zl0QByv_CJ`3iFsH7J8nD7C6JkhJ6d4tppX(euZkA;;fJ%$@7pfHo#nE$m6UdzzRx} zhKKTEh!%}nJX3eV0)fnx0mF1G5P8*7+s;5v?!ovTV>W8W_03M+T#s7UV`iieY$Tl7 zo4wPNh<(2!49;e_z}Rar?|H8f5(6YZRD!(DYUxVc~Fm7Wc;<7OG4tEowp>phB)pP(M$@m&Bm(JueB^t8Q@rN<2W@ zTiI}{gb8!^iYbbRBX$g&dna>_iQbow_3m(1!13pVy*@W7El_68mZJ zF}-m^$5$D88}yHBe*)SrCDskqFwog1nD(f|43kO0xp9Nqm`ZHXyj;Nl58Xr7W|3Mr zw9_s$+R_o}MXF)jPcRTxt0){IN`h!lop68qdQ^QcYY`)Ju(&0@PS4sMdcUh%b_Q_p z{m(inuXhdzwqC8Yqum*T=8DuGtDN9eb*xM-j|r=$-QC6gbVSxzt}YDWK>1MNXYV9I zTui%u_f@e8TpISC{>CNYgx6s5=Xq?9qw4=%JIq3+$+~4Tk$U*G`s@w%EqA1G6HR+X z8MxJH;}mAk0CB!e_)U2y^my9j5$`EN;OdDg_YN!g#anqD+Q7oL`VW?Aw{?(MXA8m) zHvG9)o`-(3f#A^+8RIYx)EarQ?bZ5l7pdIBU1y4aQbQ;EIvqhRGYpavutxtW#>S-a z3F7tknn!bC<`6SG6>c7GjH)NQJhymQW76lu<+LgWT2$xRJt#89xnh?bn`u+bCUh^9 z&tk(kK|6Jx92++%3sQqvD=_jPf26&Qi78L*@o1_m3Kf@b7#)|y!qB%;JzHF1koxMx z6;mz@IcB8`+o|}IIrHs(J`GJZ3j3txOyHGr#?9x1J9_T6E})Wi@Sq~twN8zI8l(3D zg@Q~ZS4!1U7?9Dlwa+D!lN?H2h4i_&B;@`{pYNI2m<&^7b8su*?et!R}gOHsh z)8enrP}i#Q)%0N_nk})&eZ2*8ZmR@5`|gZKsfCi?=~U!5c3S+NG{f0jS3Cydx`;M+ z7AifIC z*|cxB#R^1n%dB3xaWV7syrf(w0lclMhqd3i!C}v~A!TI}hOe)A!mK7?%>Q!mvy=At ztZ(;cNs|ep1zL88P_2<7efdpJu_m1LhSeiBTS4OQhoeQ2j<_KC@m6C82{{(L+4y@7 z$d{PmT;EGWpY8ce3ZE%R+uB+iM={6Cn6le8ZyYdgow_Ya&ls)N`(-b>lW>!yEU7ag z0;jo(@52E`FtpmkjV@HdSm@jqTO$8_f)eIh1S~PYwGDRB-Zz?GY-fOc#W7K_&$iG%Y27?e zSQjg5O=7h^QgD=MW>mV_7NaTEozGwJ>#IX&swr9)+><;dZN>=kpl9CN3{Nu*U8s0r z@>(A`sU1PJ_Kt9P_wx1tmxa^49yc0?fxX0H*`Kx6c#yE2)PBnq*L97T&yw^YJD1>7 zCP(Mr*BAfZ|Dt1Zs5f-iCkB`~%Y6tO4qAzg)oS)GPz|qQxmfV|qsiyRRa-mEANpN1 zwUPnP)k+HH31p02YZyHHjfuW36yo29c2J>)w8hl0utF$o$pU|EO!USzH?qj64mI+Z zsL==aYV9RGFCDBnUe4Q*Dg{4<-aSi~-5-8*tzk5o1@h+#P*04^^tak>M0J zCu;k{6;Updie&*4#LI)@^4diTD4lw{Htd}pJl!7+T$7-|=`UIffXByC zuZh1FvWEEfw%2j_%yOhEA3UjjOa|p&+Ahg=vvD$Z`A#J}67oe)9AVx8F8WI||2`%m zp`=^6YJol4V?A3RNt+_YWQ%UrQ3m>+FpbmV7`UcPQDeNNfysK}*5o@*{2>-={q;Nx z*TN3%bG1`}cYpMeP}5adeW2bhNrj5cMvZkcmn{%d`6%6~m<9D+qRJ2K#9;AB=%lVY z8QHx@p1c%ShQ9g{Mv9>kv@aA~nIzHSTym-F<0Crme+l!E#5Q;T zKPp~^dFKiTs6caVZ}V<`JyNL6t;4&hd_BFS(e;TFmepMfDtPDwQT0TvyO)^w6nsQD z{W!qexXb+16FpERdkT(JvtV?bvUbsN8%)=Uyp&_xA#q;Tl{XfW=wtsQAByDj*m>Q~ z8&T$X?^ydec5*fDOu09vUsi%}#;R@G7tujjc<8~~egeAVMMquN(;>K_RM%k{9S_`} zCq<0W(44l=#{G{IWTQ{-9=>3SA63prJ3ec`&VQ``pDAB&32pUr-A6+>@wc9;nmZa2 zdH3@6aqw{eq4uBvN2ID*&PxqoU{r#->ph=`Kb;e6EaKz-WPQ=che{m0`29E3pwbS; zuG6i*_&P55&8b;Jx)~PgY+se+$M-uVsR+qe4BRjEocsBkg}zjwD(bW~79Hu~px%jY0zx!_;8y6Pn|CA}BLq9LV?`sefTDG)(>2WKd zxS@4^3q=F-grq_q>saC3#cnTOeP^i3E*-qIOCO(BdOEi@F>z2k$^f~RD8DLN`0M}^ z^Tl@M3Y|1Y^G<4|a|RU+8zXf%VS>n;`Qtn4jJMLt!_zWM z%rr=9CUT~T&L=ASPDUzXc){T+S1&h2uU@h_@EsTNx}?F>m#ZKnwO2cMGZ{yccv9(U zY<%djB+Tz~L%x~SV#Hgb==>o)9T6Rj$E^J=FyV|bDVufuI!+*;G`f>^SrTD+qj$`w z?LeA(MdZ{Pq9Bn9oxzB9KkJZ@GB^M&=xWlk=sXi9n3ZsTb zvhnGKO5qU!zMqJZ{21v;LHCe_@x>D~5TX+OT-@1sXv}nZ>f(lV^>?Td){2n1_$+?O zIF*lQe}cr*x$ta^zMp&28R_KTFG5bUU?^~VSG6O5|C)B1x;I?mDI&PXhq z*OSBq!_s6rUBwKC`wdS&J179lj|JPxU%DVr_^JN+E_;-%F;IRP!`FJsdGGAAxM-Uj zyOP;$g|Q1eDh6JyN36+ANUbXuYj2Mq<3k~O%m+s@73dJ~OMCjXla7{wy~Nk$Onj^p z(oIC-Y7UX zU%khH{)AWg_gqJ$Tnh9w^d2Jq_N~o3J*Coi4J#Khx5 z-w-~Y9fZO!NC3zSHNJZ}sur!!FhM7X!~e#OyfE_xHR0 zja@7_C62o=3+3C+8Rq29G;bqp zc1ulG=J%thhsnO>3_AAootDjNX5)#CQ#EGT7;xwhTJ_Kc$Ijj;t+X`2#%)O#vmZM^ zaCDn)QJy1WM&|D#A23B^6|cKSnG0Ey>F7=O=Aq&F3-jcynrP@FE#Lo$iYWHZzsI)O zBKcqL!~rLF$h^#;&gqk&yhuFJw*8v+Fr zaKqx!5TXD92ZJKq5KssafyD?wi0Y?mcOns|E-Oof!O$`UtQQ^%I~BuWG8h<97K6vT z%Kkem<4#1Qn25eOn7V))3JW1JxgyXo4B^yBT|kkEfP+9!85GQoD2>Ash%h_?ilR8EJ)KetEEg16LP-`yp`u%fR9haKx$R)c3#sOorCRU_%Vf zi>QY{oo;CgLBrHFO;7)6h=#ynhGtAm{I3|#{BzD;N%Xa54%=(>|JX5+HP1l`yMD;J z+4W|B@(n{mOm5h{PMwz$_OZ%FtqPo6 z1TJm?}-fXmF%qwzQ#$AbSOK-fGfCBKT9%&XIN)Y|L(I*Jo?c*UU#5{-eMZD*6Llmoz@gxE%5)WV+x^jb5>k zXm1>;(~lt}{==i>bh~6ND7X>T`mynZGk5j~&8)^;2|PgmMXv2}wLn}1_uMi+-iUeV z3-*1q*s?&X-uEzJ6$~HFi8swzg-Y6{t6LVQg(Bk;b1nqJkQrORnyW4RR%z~(pI!OP zp&x!t>;A@&;cL|z!F3*DnvTh3WWSb!pb)&@3O<1TvvDv{yz`d7@!ZfvL~`ltO^REr zY#Q9Ir0j{>Ktt{^$9>dT^J;x|fs=Cs&5(PEzq%<_m){4I75nT)!siE*4MZ>poIK@f z6T=3+`7!tLtC&gp=zUTEoK$q9$cul6z$bUHUpsP zP5aYD&pJKSDc*H4!D%)#8JDuKPZ=HNLBs&Q*0wJ*`-pbgikkNV4mKTc2KbNmN_>|(s{HM%@l6_Q2b^_%xOk4+cHD$OE?;T9cR?@ zGNNsUI{dvxV|#jwf22ZRs;^EvE6GSSEt;CLyEf|AI-uGcYG`smOik(fkx`)oT?^d) zU7Ju9=t1%<-F30xi*SYo2KWJ5M{2fwfOK)K&l18j#@gY2^o~XX*dX08Xae+7^>(zb zt?q~Iam6U$;n~p3+8ZhR@f^Mj_;)!;LzA~(&yE<2Bc=4;@^$f^Bz61v1}QT4U8D~- zQ*Vn65k$r$)8!|3Wh55cs7#|3YCP#@3mSLxYk8ABhINB88^LC(5pV{_D?=bV7G|#?9%J@aM z9yZ;wL^=C9vNakn`Vup^Tf>SC0xD|y>bb`$qDF$L1zF28cCm#*!^smdo66UNE=n$y zxA3M_+2o|%Y7sDT?EKC?xL#Ne0H~)`#Y_v2wGy5jih8RSyWZtJ>kG>l>s$TK`X`H- zaL^hN!37|gxx52Q6bl$^JVW)j}^7b0Bdhp7JH&r1c~kMX~tR;X~z!dYzmo3(P{N!Q{0 zhh4MK+`@I9__~O)9pU#a2~~!4-xD{b9_Po`l&l^!wobzCEMWIncD~BH zbB|2xdR8{+Fg=hG?i%1qgV61^KO|Hto21GGgg$gQGsV)|h)q1(f~m*1XYsxi8st_c zuoZ5Ws$Q`%icZhC?&ujCu_(FDvOQ;XLAFL;BbM`8U!b>S6{S3#*rPWvu*rfx{ zB_O+v$xvct-1ZhryO(%FgIda`odt??9Z96LocqvJ5cAmKnvGZ)U{-&2gI%VNl=~5< zrtdFy^@(tNQcBXhdES;~ZN%pj$W1O&Cy~#4thS;oR9XWs+bF}}U^kTux z5h2mxva`kT`_I#u75>TVoWB~m>LY{EcFpH>0rU`Eim!pV5EqZ}odq@w^7b`KX7UD^ zJh@WCZW5{qd;{ow*)Dv<`%BKqs@-fwqkWdy>;Qb%|0kPMc*{E2?w8o48b?R?tcJzq z$D-MJj71>b(P*-(u~>o+iaej6olITXJbQs%BI3(xQ+4Bk_@VVpzw_Ng1&^KwSyK5y zkW_n6;HQe%IqKc#KY1$Z=^HyQ$T~0{L&G1s$3PpMwSoiGrJ=aA3-#;x^s*eK=1sHx z^ARBd`Ek4cUz&M4<;|cHskr1s6SFGB;{-2)huULMkgrT;&aF!wB$I5cpL{fivs}4= zGbK6DKmpVjC{e0vj+7|6zd7~=tnKEQYhE*RqgFGhDwEr!g3RkB$-0qIOZv>bJhi)W zWLGNvsZYEa>V1x)*Yeo~y!?H9eRdcaD+Kp+Pz?E#BIZ)J2@3Q(X{(Mlk&5JRq>U4m z9sJ`K-rUPqdF~o;1vZY122LXmmS+!uc=dbS5hF0+2wc<_m1wvM% z7Nx(O)Yx6#?Qj%30SegGfXJMDD#|97*{-oN;rKEI??$z5Hods_g5j+(FV@);|D>tP z@`jqHC#%e0-nuA)4=lY%+42G`9%5-NhXO|>zs54>J8E~N<0q$DYCn;3-1u_7Vwnt+ zf?;Wc9bwl=k;%>r-#~x@aWUWyr+tUIrMhy|Sr|e|xs|Fen)4^ID3TVamkZSoChW9e!xao-MW%k*Z5(&xm>Hy9L4W6M7G8>DNbgo9D%C3>x@ zXdGQ3h=SCM4?_uaw{-_uZb^FdDKFl znQI#PW_V)%M8M)~#R^t8pJf$@#FLL=tRiD_=1ZDXzBDa-^Lwt27%>CgWv3K7 zJ0eO2_NPpyd89In5|TX%#c0XH3dgStYP?6{a{qd;ubvs}hP4{=$cv}{iEy1G~67yMn zJ)TB{M}C7^sQ?cwTmepIXTnBla)gw8}(%zGI~YSnK^ zjmOWrU@V2?K4_rz87nqC6sLE%iP-FFSDqQwK3 zxLazlX>f&GvcbLIoJz^*Y!2zh-p&{79o@z4`|<`$$}6RwmIwuMfEu*-_~z;Y8uO;= zX;WIdsh0Zj)t7S?Uuz>xlPo@9uQ__OZpo>n6N4g)x3?NSsd`z9pUZ_FsdKWmL1MRJ z9e23*A4dJK?d93!siL}Mgdew`m#UnMDEh*Sh~I~16z^^&ArlYYkQ&eII5Xbp&R6{9 zA@_>lW>p2zgvyFo9sO1`nKNUp+C9&G$UExa^^$Bq>%+p=emr^Ib}F?`YEEa|yzlqV zXtmV$(sW9R$f}hBN$+)lcsj((%G}M&ZNEW|Z%1M-DGmFfT6S799 zJ3rP`+vz==_lI3J8GgB)Zfj7NJk`Wt3tc*T#+V&oNh3a|t$rCmKT8A#;1btCEQ~xq zqv4BomhdP+F}%FWnlE7k_VRP%=7o8l^jy$(5<$xQQa9Tp>-dT?vX zVY^(5xS~VLM2Arb^iV5YXiH6Qoh(wOZO7zuK&-msS#DDlB`@j2ZTj zTK4d%KjEAUyx!9>RB-{ zCxv;Fyp=DelbqZw%i#lO6g^RBS?Dk~TV0pYuOQa3w5<4S`P-=v-+%9Eij$CCRoF6T t`0Lg52Ih5$PyH|9DYCWa5?ES-k1RO@uUV`QRM-z3jLKGh$8zS(e*kt5pHlz; diff --git a/test/io/units.nhdr b/test/io/units.nhdr deleted file mode 100644 index d4a9e35f..00000000 --- a/test/io/units.nhdr +++ /dev/null @@ -1,14 +0,0 @@ -NRRD0004 -# Complete NRRD file format specification at: -# http://teem.sourceforge.net/nrrd/format.html -type: float -dimension: 3 -space: left-posterior-superior -sizes: 10 10 10 -space directions: (0.1,0,0) (0,0.2,0) (0,0,1) -space units: "mm" "mm" "mm" -kinds: domain domain domain -endian: little -encoding: raw -space origin: (0,0,0) -data file: small.raw diff --git a/test/readOSX.jl b/test/readOSX.jl deleted file mode 100644 index 3b14ca7e..00000000 --- a/test/readOSX.jl +++ /dev/null @@ -1,74 +0,0 @@ -using FactCheck, Images, Colors, FixedPointNumbers, TestImages - -facts("OS X reader") do - context("Autumn leaves") do - img = testimage("autumn_leaves") - @fact colorspace(img) --> "RGBA" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> RGBA{Ufixed16} - end - context("Camerman") do - img = testimage("cameraman") - @fact colorspace(img) --> "Gray" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> Gray{Ufixed8} - end - context("Earth Apollo") do - img = testimage("earth_apollo17") - @fact colorspace(img) --> "RGB4" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> RGB4{Ufixed8} - end - context("Fabio") do - img = testimage("fabio") - @fact colorspace(img) --> "Gray" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> Gray{Ufixed8} - end - context("House") do - img = testimage("house") - @fact colorspace(img) --> "GrayA" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> GrayA{Ufixed8} - end - context("Jetplane") do - img = testimage("jetplane") - @fact colorspace(img) --> "GrayA" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> GrayA{Ufixed8} - end - context("Lighthouse") do - img = testimage("lighthouse") - @fact colorspace(img) --> "RGB4" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> RGB4{Ufixed8} - end - context("Mandrill") do - img = testimage("mandrill") - @fact colorspace(img) --> "RGB" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> RGB{Ufixed8} - end - context("Moonsurface") do - img = testimage("moonsurface") - @fact colorspace(img) --> "Gray" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> Gray{Ufixed8} - end - context("Mountainstream") do - img = testimage("mountainstream") - @fact colorspace(img) --> "RGB4" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> RGB4{Ufixed8} - end -end diff --git a/test/readnrrd.jl b/test/readnrrd.jl deleted file mode 100644 index 8b4fbd87..00000000 --- a/test/readnrrd.jl +++ /dev/null @@ -1,58 +0,0 @@ -using FactCheck, Images, Colors, FixedPointNumbers - -testing_units = Int == Int64 -if testing_units - using SIUnits, SIUnits.ShortUnits -end - -facts("Read NRRD") do - workdir = joinpath(tempdir(), "Images") - writedir = joinpath(workdir, "write") - if !isdir(workdir) - mkdir(workdir) - end - if !isdir(writedir) - mkdir(writedir) - end - - context("Gray, raw") do - img = imread(joinpath(dirname(@__FILE__), "io", "small.nrrd")) - @fact colorspace(img) --> "Gray" - @fact ndims(img) --> 3 - @fact colordim(img) --> 0 - @fact eltype(img) --> Float32 - outname = joinpath(writedir, "small.nrrd") - imwrite(img, outname) - imgc = imread(outname) - @fact img.data --> imgc.data - end - - context("Units") do - img = imread(joinpath(dirname(@__FILE__), "io", "units.nhdr")) - ps = pixelspacing(img) - @fact ps[1]/(0.1*Milli*Meter) --> roughly(1) - @fact ps[2]/(0.2*Milli*Meter) --> roughly(1) - @fact ps[3]/(1*Milli*Meter) --> roughly(1) - end - - context("Gray, compressed (gzip)") do - img = imread(joinpath(dirname(@__FILE__), "io", "smallgz.nrrd")) - @fact colorspace(img) --> "Gray" - @fact ndims(img) --> 3 - @fact colordim(img) --> 0 - @fact eltype(img) --> Float32 - outname = joinpath(writedir, "smallgz.nrrd") - imwrite(img, outname) - imgc = imread(outname) - @fact img.data --> imgc.data - end - - context("Time is 4th dimension") do - img = imread(joinpath(dirname(@__FILE__), "io", "small_time.nrrd")) - @fact timedim(img) --> 4 - outname = joinpath(writedir, "small_time.nrrd") - imwrite(img, outname) - imgc = imread(outname) - @fact img.data --> imgc.data - end -end diff --git a/test/readremote.jl b/test/readremote.jl deleted file mode 100644 index f2b1b463..00000000 --- a/test/readremote.jl +++ /dev/null @@ -1,213 +0,0 @@ -using FactCheck, Images, Colors, FixedPointNumbers - -facts("Read remote") do - urlbase = "http://www.imagemagick.org/Usage/images/" - workdir = joinpath(tempdir(), "Images") - writedir = joinpath(workdir, "write") - if !isdir(workdir) - mkdir(workdir) - end - if !isdir(writedir) - mkdir(writedir) - end - - function getfile(name) - file = joinpath(workdir, name) - if !isfile(file) - file = download(urlbase*name, file) - end - file - end - - context("Gray") do - file = getfile("jigsaw_tmpl.png") - img = imread(file) - @fact colorspace(img) --> "Gray" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> Gray{Ufixed8} - outname = joinpath(writedir, "jigsaw_tmpl.png") - imwrite(img, outname) - imgc = imread(outname) - @fact img.data --> imgc.data - @fact reinterpret(UInt32, data(map(mapinfo(RGB24, img), img))) --> - map(x->x&0x00ffffff, reinterpret(UInt32, data(map(mapinfo(ARGB32, img), img)))) - @fact mapinfo(UInt32, img) --> mapinfo(RGB24, img) - @fact data(convert(Image{Gray{Float32}}, img)) --> float32(data(img)) - mapi = mapinfo(RGB{Ufixed8}, img) - imgrgb8 = map(mapi, img) - @fact imgrgb8[1,1].r --> img[1].val - open(outname, "w") do file - writemime(file, "image/png", img) - end - end - - context("Gray with alpha channel") do - file = getfile("wmark_image.png") - img = imread(file) - @fact colorspace(img) --> "GrayA" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @fact eltype(img) --> Images.ColorTypes.GrayA{Ufixed8} - @linux_only begin - outname = joinpath(writedir, "wmark_image.png") - imwrite(img, outname) - sleep(0.2) - imgc = imread(outname) - @fact img.data --> imgc.data - open(outname, "w") do file - writemime(file, "image/png", img) - end - end - @fact reinterpret(UInt32, data(map(mapinfo(RGB24, img), img))) --> - map(x->x&0x00ffffff, reinterpret(UInt32, data(map(mapinfo(ARGB32, img), img)))) - @fact mapinfo(UInt32, img) --> mapinfo(ARGB32, img) - end - - context("RGB") do - file = getfile("rose.png") - img = imread(file) - # Mac reader reports RGB4, imagemagick reports RGB - @osx? begin - @fact colorspace(img) --> "RGB4" - end : @fact colorspace(img) --> "RGB" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @osx? begin - @fact eltype(img) --> RGB4{Ufixed8} - end : @fact eltype(img) --> RGB{Ufixed8} - outname = joinpath(writedir, "rose.ppm") - imwrite(img, outname) - imgc = imread(outname) - T = eltype(imgc) - lim = limits(imgc) - @fact typeof(lim[1]) --> typeof(lim[2]) # issue #62 - @fact typeof(lim[2]) --> T # issue #62 - # Why does this one fail on OSX?? - @osx? nothing : @fact img.data --> imgc.data - @fact reinterpret(UInt32, data(map(mapinfo(RGB24, img), img))) --> - map(x->x&0x00ffffff, reinterpret(UInt32, data(map(mapinfo(ARGB32, img), img)))) - @fact mapinfo(UInt32, img) --> mapinfo(RGB24, img) - mapi = mapinfo(RGB{Ufixed8}, img) - imgrgb8 = map(mapi, img) - @fact data(imgrgb8) --> data(img) - convert(Array{Gray{Ufixed8}}, img) - convert(Image{Gray{Ufixed8}}, img) - convert(Array{Gray}, img) - convert(Image{Gray}, img) - imgs = separate(img) - @fact permutedims(convert(Image{Gray}, imgs), [2,1]) --> convert(Image{Gray}, img) - # Make sure that all the operations in README will work: - buf = Array(UInt32, size(img)) - buft = Array(UInt32, reverse(size(img))) - uint32color(img) - uint32color!(buf, img) - imA = convert(Array, img) - uint32color(imA) - uint32color!(buft, imA) - uint32color(imgs) - uint32color!(buft, imgs) - imr = reinterpret(Ufixed8, img) - uint32color(imr) - uint32color!(buf, imr) - @osx? nothing : begin - imhsv = convert(Image{HSV}, float32(img)) - uint32color(imhsv) - uint32color!(buf, imhsv) - @fact pixelspacing(restrict(img)) --> [2.0,2.0] - end - outname = joinpath(writedir, "rose.png") - open(outname, "w") do file - writemime(file, "image/png", img) - end - end - - context("RGBA with 16 bit depth") do - file = getfile("autumn_leaves.png") - img = imread(file) - @osx? begin - @fact colorspace(img) --> "RGBA" - end : @fact colorspace(img) --> "BGRA" - @fact ndims(img) --> 2 - @fact colordim(img) --> 0 - @osx? begin - @fact eltype(img) --> Images.ColorTypes.RGBA{Ufixed16} - end : @fact eltype(img) --> Images.ColorTypes.BGRA{Ufixed16} - outname = joinpath(writedir, "autumn_leaves.png") - @osx? nothing : begin - imwrite(img, outname) - sleep(0.2) - imgc = imread(outname) - @fact img.data --> imgc.data - @fact reinterpret(UInt32, data(map(mapinfo(RGB24, img), img))) --> - map(x->x&0x00ffffff, reinterpret(UInt32, data(map(mapinfo(ARGB32, img), img)))) - @fact mapinfo(UInt32, img) --> mapinfo(ARGB32, img) - end - open(outname, "w") do file - writemime(file, "image/png", img) - end - end - - context("Indexed") do - file = getfile("present.gif") - img = imread(file) - @fact nimages(img) --> 1 - @fact reinterpret(UInt32, data(map(mapinfo(RGB24, img), img))) --> - map(x->x&0x00ffffff, reinterpret(UInt32, data(map(mapinfo(ARGB32, img), img)))) - @fact mapinfo(UInt32, img) --> mapinfo(RGB24, img) - outname = joinpath(writedir, "present.png") - open(outname, "w") do file - writemime(file, "image/png", img) - end - end - - context("Images with a temporal dimension") do - fname = "swirl_video.gif" - #fname = "bunny_anim.gif" # this one has transparency but LibMagick gets confused about its size - file = getfile(fname) # this also has transparency - img = imread(file) - @fact timedim(img) --> 3 - @fact nimages(img) --> 26 - outname = joinpath(writedir, fname) - imwrite(img, outname) - imgc = imread(outname) - # Something weird happens after the 2nd image (compression?), and one starts getting subtle differences. - # So don't compare the values. - # Also take the opportunity to test some things with temporal images - @fact storageorder(img) --> ["x", "y", "t"] - @fact haskey(img, "timedim") --> true - @fact timedim(img) --> 3 - s = getindexim(img, 1:5, 1:5, 3) - @fact timedim(s) --> 0 - s = sliceim(img, :, :, 5) - @fact timedim(s) --> 0 - imgt = sliceim(img, "t", 1) - @fact reinterpret(UInt32, data(map(mapinfo(RGB24, imgt), imgt))) --> - map(x->x&0x00ffffff, reinterpret(UInt32, data(map(mapinfo(ARGB32, imgt), imgt)))) - end - - context("Extra properties") do - @osx? nothing : begin - file = getfile("autumn_leaves.png") - # List properties - extraProps = imread(file, extrapropertynames=true) - - img = imread(file,extraprop=extraProps) - props = properties(img) - for key in extraProps - @fact haskey(props, key) --> true - @fact props[key] --> not(nothing) - end - img = imread(file, extraprop=extraProps[1]) - props = properties(img) - @fact haskey(props, extraProps[1]) --> true - @fact props[extraProps[1]] --> not(nothing) - - println("The following \"Undefined property\" warning indicates normal operation") - img = imread(file, extraprop="Non existing property") - props = properties(img) - @fact haskey(props, "Non existing property") --> true - @fact props["Non existing property"] --> nothing - end - end -end diff --git a/test/readstream.jl b/test/readstream.jl deleted file mode 100644 index 1383f02f..00000000 --- a/test/readstream.jl +++ /dev/null @@ -1,23 +0,0 @@ -using FactCheck, Images, Colors, FixedPointNumbers -@osx_only using TestImages - -facts("Read stream") do - @osx_only begin - # OS X only for the moment, because TestImages is only - # required for OS X (see test/REQUIRE). That seems to cause - # a testing failure on Travis for Linux. - # I assume that at some point, streaming will expand and other tests - # will be needed, at which point we can open up this test - workdir = joinpath(tempdir(), "ImagesStreamTest") - testfile = joinpath(workdir, "jigsaw_tmpl.png") - if !isfile(testfile) - mkpath(workdir) - download("http://www.imagemagick.org/Usage/images/jigsaw_tmpl.png", testfile) - end - open(testfile, "r") do io - img = imread(io, Images.OSXNative) - end - @pending something --> true - rm(workdir, recursive=true) - end -end diff --git a/test/runtests.jl b/test/runtests.jl index 8252ee73..d79027cf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,13 +17,6 @@ FactCheck.setstyle(:compact) include("core.jl") include("map.jl") include("overlays.jl") -include("io.jl") -if testing_units - include("readnrrd.jl") -end -include("readremote.jl") -include("readstream.jl") -@osx_only include("readOSX.jl") include("algorithms.jl") include("edge.jl") From 94a362364503bdcf533c172f38bfccb32283831d Mon Sep 17 00:00:00 2001 From: Sdanisch Date: Sun, 27 Sep 2015 19:46:14 +0200 Subject: [PATCH 04/14] integrate SIF and Imagine @timholy the Imagine port is incomplete because: - don't know file ending - don't know magic byte - would need to implement submodule loading in Fileio (own packige for Imagine?) you should probably just do the changes you feel to be appropriate. --- src/Images.jl | 2 ++ src/ioformats/Imagine.jl | 8 ++--- src/ioformats/SIF.jl | 67 +++++++++++++++++++--------------------- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/src/Images.jl b/src/Images.jl index 6b61d677..6134f420 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -42,6 +42,8 @@ include("labeledarrays.jl") include("algorithms.jl") include("connected.jl") include("edge.jl") +include(joinpath("ioformats", "SIF.jl")) +include(joinpath("ioformats", "Imagine.jl")) function precompile() for T in (UInt8, UInt16, Int, Float32, Float64) diff --git a/src/ioformats/Imagine.jl b/src/ioformats/Imagine.jl index f76a8543..9cd7b1af 100644 --- a/src/ioformats/Imagine.jl +++ b/src/ioformats/Imagine.jl @@ -2,16 +2,14 @@ module Imagine using Images using SIUnits, SIUnits.ShortUnits, Compat - -import Images.imread -import Base.convert +import FileIO: skipmagic, stream, @format_str, Stream export imagine2nrrd, Micron Micron = SIUnits.NonSIUnit{typeof(Meter),:µm}() convert(::Type{SIUnits.SIQuantity},::typeof(Micron)) = Micro*Meter -function imread{S<:IO}(s::S, ::Type{Images.ImagineFile}) +function load(s::Stream{format"Imagine"}) h = parse_header(s, Images.ImagineFile) filename = s.name[7:end-1] basename, ext = splitext(filename) @@ -189,7 +187,7 @@ const field_key_dict = @compat Dict{AbstractString,Function}( "vend" => x->parse(Int,x), "angle from horizontal (deg)" => float64_or_empty) -function parse_header(s::IOStream, ::Type{Images.ImagineFile}) +function parse_header(s::IOStream) headerdict = Dict{ASCIIString, Any}() for this_line = eachline(s) this_line = strip(this_line) diff --git a/src/ioformats/SIF.jl b/src/ioformats/SIF.jl index 41d10dce..92ccafcc 100644 --- a/src/ioformats/SIF.jl +++ b/src/ioformats/SIF.jl @@ -1,19 +1,16 @@ # SIF.jl, adds an imread function for Andor .sif images # 2013 Ronald S. Rock, Jr. - -import Images.imread -function imread{S<:IO}(stream::S, ::Type{Images.AndorSIF}) +import FileIO: skipmagic, stream, @format_str, Stream +function load(fs::Stream{format"AndorSIF"}) # line 1 - seek(stream, 0) - l = strip(readline(stream)) - l == "Andor Technology Multi-Channel File" || error("Not an Andor file: " * l) - + skipmagic(fs, 0) + io = stream(fs) # line 2 - l = strip(readline(stream)) + l = strip(readline(io)) l == "65538 1" || error("Unknown Andor version number at line 2: " * l) # line 3: TInstaImage thru "Head model" - l = strip(readline(stream)) + l = strip(readline(io)) fields = split(l) fields[1] == "65547" || fields[1] == "65558" || error("Unknown TInstaImage version number at line 3: " * fields[1]) @@ -80,54 +77,54 @@ function imread{S<:IO}(stream::S, ::Type{Images.AndorSIF}) ixon["sw_vers4"] = round(Int,fields[58]) # line 4 - ixon["camera_model"] = strip(readline(stream)) + ixon["camera_model"] = strip(readline(io)) # line 5, something like camera dimensions?? - _ = readline(stream) + _ = readline(io) # line 6 - ixon["original_filename"] = strip(readline(stream)) + ixon["original_filename"] = strip(readline(io)) # line 7 - l = strip(readline(stream)) + l = strip(readline(io)) fields = split(l) fields[1] == "65538" || error("Unknown TUserText version number in line 7: $fields[1]") usertextlen = round(Int,fields[2]) # don't need? # line 8 - usertext = strip(readline(stream)) + usertext = strip(readline(io)) # ixon["usertext"] = usertext # Not useful # line 9 TShutter - l = strip(readline(stream)) # Weird! + l = strip(readline(io)) # Weird! # line 10 TCalibImage - l = strip(readline(stream)) + l = strip(readline(io)) # lines 11-22 - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) - _ = strip(readline(stream)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) + _ = strip(readline(io)) # what a bizarre file format here # length of the next string is in this line - next_str_len = round(Int,strip(readline(stream))) + next_str_len = round(Int,strip(readline(io))) # and here is the next string, followed by the length # of the following string, with no delimeter in between! - l = strip(readline(stream)) + l = strip(readline(io)) next_str_len = round(Int,l[(next_str_len + 1):end]) # lather, rinse, repeat... - l = strip(readline(stream)) + l = strip(readline(io)) next_str_len = round(Int,l[(next_str_len + 1):end]) - l = strip(readline(stream)) + l = strip(readline(io)) l = l[(next_str_len + 1):end] fields = split(l) fields[1] == "65538" || error("Unknown version number at image dims record") @@ -142,7 +139,7 @@ function imread{S<:IO}(stream::S, ::Type{Images.AndorSIF}) ixon["single_frame_length"] = round(Int,fields[9]) # Now at the first (and only) subimage - l = strip(readline(stream)) + l = strip(readline(io)) fields = split(l) fields[1] == "65538" || error("unknown TSubImage version number: " * fields[1]) left = round(Int,fields[2]) @@ -172,11 +169,11 @@ function imread{S<:IO}(stream::S, ::Type{Images.AndorSIF}) # rest of the header is a timestamp for each frame # (actually, just a bunch of zeros). Skip for i = 1:frames - _ = readline(stream) + _ = readline(io) end - offset = position(stream) # start of the actual pixel data, 32-bit float, little-endian + offset = position(io) # start of the actual pixel data, 32-bit float, little-endian - pixels = read(stream, Float32, width, height, frames) + pixels = read(io, Float32, width, height, frames) prop = Compat.@compat Dict( "colorspace" => "Gray", "spatialorder" => ["y", "x"], From d3701e20d4ab80257889009d374c8f681e6d63be Mon Sep 17 00:00:00 2001 From: Simon Danisch Date: Sun, 27 Sep 2015 20:20:01 +0200 Subject: [PATCH 05/14] added FileIO dependency --- .travis.yml | 1 + REQUIRE | 1 + appveyor.yml | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bf1746c0..6046219e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ notifications: email: false script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi + - julia -e 'Pkg.clone("https://github.com/JuliaIO/FileIO.jl.git")' - julia -e 'Pkg.clone(pwd()); Pkg.build("Images")' - julia -e 'Pkg.test("Images", coverage=true)' after_success: diff --git a/REQUIRE b/REQUIRE index b97e1ec3..6fc1ad89 100644 --- a/REQUIRE +++ b/REQUIRE @@ -7,3 +7,4 @@ BinDeps SIUnits Zlib Graphics 0.1 +FileIO diff --git a/appveyor.yml b/appveyor.yml index af338a18..acf2845a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,8 +32,8 @@ install: build_script: # Need to convert from shallow to complete for Pkg.clone to work - IF EXIST .git\shallow (git fetch --unshallow) - - C:\projects\julia\bin\julia -F -e "versioninfo(); - Pkg.clone(pwd(), \"Images\"); Pkg.build(\"Images\")" + - C:\projects\julia\bin\julia -F -e "versioninfo(); Pkg.clone(\"https://github.com/JuliaIO/FileIO.jl.git\", \"FileIO\")" + - C:\projects\julia\bin\julia -F -e "Pkg.clone(pwd(), \"Images\"); Pkg.build(\"Images\")" test_script: - C:\projects\julia\bin\julia --check-bounds=yes -e "Pkg.test(\"Images\")" From 74fab29e4c8ddc8b599bc429488408a6e571d00f Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 27 Sep 2015 13:42:00 -0500 Subject: [PATCH 06/14] Revert "Workaround upstream weak type inference" This reverts commit 6e7afc08bdd08cc5da94dc26f33d7cdd11c4c01a. --- src/core.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.jl b/src/core.jl index 7160b8e9..3dd35e6d 100644 --- a/src/core.jl +++ b/src/core.jl @@ -11,7 +11,7 @@ type Image{T,N,A<:AbstractArray} <: AbstractImageDirect{T,N} data::A properties::Dict{ASCIIString,Any} end -Image{T,N}(data::AbstractArray{T,N}, props::Dict) = Image{eltype(data),N,typeof(data)}(data,props) +Image(data::AbstractArray, props::Dict) = Image{eltype(data),ndims(data),typeof(data)}(data,props) Image(data::AbstractArray; kwargs...) = Image(data, kwargs2dict(kwargs)) # Indexed image (colormap) From 5b22bea86b569d106e49456b76d2bca7f2cd05dd Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 27 Sep 2015 13:56:28 -0500 Subject: [PATCH 07/14] Create deprecations for imread and imwrite --- src/Images.jl | 6 +++++- src/ioformats/Imagine.jl | 6 +++--- src/ioformats/SIF.jl | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Images.jl b/src/Images.jl index 6134f420..afbc5d50 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -11,7 +11,7 @@ import Base: atan2, clamp, convert, copy, copy!, ctranspose, delete!, done, elty start, strides, sub, sum, write, writemime, zero # "deprecated imports" are below -using Colors, ColorVectorSpace, FixedPointNumbers, Compat +using Colors, ColorVectorSpace, FixedPointNumbers, Compat, FileIO import Colors: Fractional, red, green, blue typealias AbstractGray{T} Color{T,1} typealias TransparentRGB{C<:AbstractRGB,T} TransparentColor{C,T,4} @@ -238,6 +238,10 @@ export # Deprecated exports scalesigned +import FileIO: load, save +@deprecate imread load +@deprecate imwrite save +export load, save import Base: scale, scale! # delete when deprecations are removed @deprecate scaleminmax ScaleMinMax @deprecate scaleminmax(img::AbstractArray, min::Real, max::Real) ScaleMinMax(RGB24, img, min, max) diff --git a/src/ioformats/Imagine.jl b/src/ioformats/Imagine.jl index 9cd7b1af..684f5f61 100644 --- a/src/ioformats/Imagine.jl +++ b/src/ioformats/Imagine.jl @@ -1,15 +1,15 @@ module Imagine -using Images +using Images, FileIO using SIUnits, SIUnits.ShortUnits, Compat -import FileIO: skipmagic, stream, @format_str, Stream +using FileIO: skipmagic, stream, @format_str, Stream export imagine2nrrd, Micron Micron = SIUnits.NonSIUnit{typeof(Meter),:µm}() convert(::Type{SIUnits.SIQuantity},::typeof(Micron)) = Micro*Meter -function load(s::Stream{format"Imagine"}) +function FileIO.load(s::Stream{format"Imagine"}) h = parse_header(s, Images.ImagineFile) filename = s.name[7:end-1] basename, ext = splitext(filename) diff --git a/src/ioformats/SIF.jl b/src/ioformats/SIF.jl index 92ccafcc..7239cbfd 100644 --- a/src/ioformats/SIF.jl +++ b/src/ioformats/SIF.jl @@ -1,7 +1,7 @@ # SIF.jl, adds an imread function for Andor .sif images # 2013 Ronald S. Rock, Jr. -import FileIO: skipmagic, stream, @format_str, Stream -function load(fs::Stream{format"AndorSIF"}) +using FileIO: skipmagic, stream, @format_str, Stream +function FileIO.load(fs::Stream{format"AndorSIF"}) # line 1 skipmagic(fs, 0) io = stream(fs) From aa2d4d4566635f78179898f4072ee664945d0e30 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 27 Sep 2015 14:32:56 -0500 Subject: [PATCH 08/14] Move Imagine format into ImagineFormat.jl --- src/Images.jl | 1 - src/ioformats/Imagine.jl | 272 --------------------------------------- 2 files changed, 273 deletions(-) delete mode 100644 src/ioformats/Imagine.jl diff --git a/src/Images.jl b/src/Images.jl index afbc5d50..591ce426 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -43,7 +43,6 @@ include("algorithms.jl") include("connected.jl") include("edge.jl") include(joinpath("ioformats", "SIF.jl")) -include(joinpath("ioformats", "Imagine.jl")) function precompile() for T in (UInt8, UInt16, Int, Float32, Float64) diff --git a/src/ioformats/Imagine.jl b/src/ioformats/Imagine.jl deleted file mode 100644 index 684f5f61..00000000 --- a/src/ioformats/Imagine.jl +++ /dev/null @@ -1,272 +0,0 @@ -module Imagine - -using Images, FileIO -using SIUnits, SIUnits.ShortUnits, Compat -using FileIO: skipmagic, stream, @format_str, Stream - -export imagine2nrrd, Micron - -Micron = SIUnits.NonSIUnit{typeof(Meter),:µm}() -convert(::Type{SIUnits.SIQuantity},::typeof(Micron)) = Micro*Meter - -function FileIO.load(s::Stream{format"Imagine"}) - h = parse_header(s, Images.ImagineFile) - filename = s.name[7:end-1] - basename, ext = splitext(filename) - camfilename = basename*".cam" - T = h["pixel data type"] - sz = [h["image width"], h["image height"], h["frames per stack"], h["nStacks"]] - if sz[4] == 1 - sz = sz[1:3] - if sz[3] == 1 - sz = sz[1:2] - end - end - havez = h["frames per stack"] > 1 - havet = h["nStacks"] > 1 - # Check that the file size is consistent with the expected size - if !isfile(camfilename) - warn("Cannot open ", camfilename) - data = Array(T, sz[1], sz[2], sz[3], 0) - else - fsz = filesize(camfilename) - n_stacks = sz[end] - if fsz != sizeof(T)*prod(map(Int64,sz)) # guard against overflow on 32bit - warn("Size of image file is different from expected value") - n_stacks = ifloor(fsz / sizeof(T) / prod(sz[1:end-1])) - end - if sizeof(T)*prod(map(Int64,sz[1:end-1]))*n_stacks > typemax(UInt) - warn("File size is too big to mmap on 32bit") - n_stacks = ifloor(fsz / sizeof(T) / typemax(UInt)) - end - if n_stacks < sz[end] - println("Truncating to ", n_stacks, length(sz) == 4 ? " stacks" : " frames") - sz[end] = n_stacks - end - sc = open(camfilename, "r") - data = mmap_array(T, ntuple(i->sz[i], length(sz)), sc) - end - um_per_pixel = h["um per pixel"]*µm - pstart = h["piezo"]["stop position"] - pstop = h["piezo"]["start position"] - if length(sz)>2 - dz = abs(pstart - pstop)/sz[3] - else dz = 0.0 end - - props = @compat Dict( - "spatialorder" => (havez ? ["x", "l", "z"] : ["x", "l"]), - "colorspace" => "Gray", - "pixelspacing" => (havez ? [um_per_pixel, um_per_pixel, dz] : [um_per_pixel, um_per_pixel]), - "limits" => (@compat(UInt16(0)), @compat(UInt16(2^h["original image depth"]-1))), - "imagineheader" => h, - "suppress" => Set(Any["imagineheader"]) - ) - if havet - props["timedim"] = havez ? 4 : 3 - end - Image(data, props) -end - -abstract Endian -type LittleEndian <: Endian; end -type BigEndian <: Endian; end -const endian_dict = @compat Dict("l"=>LittleEndian, "b"=>BigEndian) -const nrrd_endian_dict = @compat Dict(LittleEndian=>"little",BigEndian=>"big") -parse_endian(s::ASCIIString) = endian_dict[lowercase(s)] - -function parse_vector_int(s::AbstractString) - ss = @compat split(s, r"[ ,;]", keep=false) - v = Array(Int, length(ss)) - for i = 1:length(ss) - v[i] = parse(Int,ss[i]) - end - return v -end - -const bitname_dict = @compat Dict( - "int8" => Int8, - "uint8" => UInt8, - "int16" => Int16, - "uint16" => UInt16, - "int32" => Int32, - "uint32" => UInt32, - "int64" => Int64, - "uint64" => UInt64, - "float16" => Float16, - "float32" => Float32, - "single" => Float32, - "float64" => Float64, - "double" => Float64) - -parse_bittypename(s::ASCIIString) = bitname_dict[lowercase(s)] - -function float64_or_empty(s::ASCIIString) - if isempty(s) - return NaN - else - return parse(Float64,s) - end -end - -function parse_quantity_or_empty(s::ASCIIString) - if isempty(s) - return NaN - else - return parse_quantity(s) - end -end - -_unit_string_dict = @compat Dict("um" => Micro*Meter, "s" => Second, "us" => Micro*Second, "MHz" => Mega*Hertz) -function parse_quantity(s::AbstractString, strict::Bool = true) - # Find the last character of the numeric component - m = match(r"[0-9\.\+-](?![0-9\.\+-])", s) - if m == nothing - error("AbstractString does not have a 'value unit' structure") - end - val = parse(Float64, s[1:m.offset]) - ustr = strip(s[m.offset+1:end]) - if isempty(ustr) - if strict - error("AbstractString does not have a 'value unit' structure") - else - return val - end - end - val * _unit_string_dict[ustr] -end - -# Read and parse a *.imagine file (an Imagine header file) -const compound_fields = Any["piezo", "binning"] -const field_key_dict = @compat Dict{AbstractString,Function}( - "header version" => x->parse(Float64,x), - "app version" => identity, - "date and time" => identity, - "rig" => identity, - "byte order" => parse_endian, - "stimulus file content" => identity, # stimulus info parsed separately - "comment" => identity, - "ai data file" => identity, - "image data file" => identity, - "start position" => parse_quantity, - "stop position" => parse_quantity, - "bidirection" => x->parse(Int,x) != 0, - "output scan rate" => x->parse_quantity(x, false), - "nscans" => x->parse(Int,x), - "channel list" => parse_vector_int, - "label list" => identity, - "scan rate" => x->parse_quantity(x, false), - "min sample" => x->parse(Int,x), - "max sample" => x->parse(Int,x), - "min input" => x->parse(Float64,x), - "max input" => x->parse(Float64,x), - "original image depth" => x->parse(Int,x), - "saved image depth" => x->parse(Int,x), - "image width" => x->parse(Int,x), - "image height" => x->parse(Int,x), - "number of frames requested" => x->parse(Int,x), - "nStacks" => x->parse(Int,x), - "idle time between stacks" => parse_quantity, - "pre amp gain" => float64_or_empty, - "EM gain" => float64_or_empty, - "gain" => float64_or_empty, - "exposure time" => parse_quantity, - "vertical shift speed" => parse_quantity_or_empty, - "vertical clock vol amp" => x->parse(Float64,x), - "readout rate" => parse_quantity_or_empty, - "pixel order" => identity, - "frame index offset" => x->parse(Int,x), - "frames per stack" => x->parse(Int,x), - "pixel data type" => parse_bittypename, - "camera" => identity, - "um per pixel" => x->parse(Float64,x), - "hbin" => x->parse(Int,x), - "vbin" => x->parse(Int,x), - "hstart" => x->parse(Int,x), - "hend" => x->parse(Int,x), - "vstart" => x->parse(Int,x), - "vend" => x->parse(Int,x), - "angle from horizontal (deg)" => float64_or_empty) - -function parse_header(s::IOStream) - headerdict = Dict{ASCIIString, Any}() - for this_line = eachline(s) - this_line = strip(this_line) - if !isempty(this_line) && !ismatch(r"\[.*\]", this_line) - # Split on = - m = match(r"=", this_line) - if m.offset < 2 - error("Line does not contain =") - end - k = this_line[1:m.offset-1] - v = this_line[m.offset+1:end] - if in(k, compound_fields) - thisdict = Dict{ASCIIString, Any}() - # Split on semicolon - strs = split(v, r";") - for i = 1:length(strs) - substrs = split(strs[i], r":") - @assert length(substrs) == 2 - k2 = strip(substrs[1]) - func = field_key_dict[k2] - v2 = strip(substrs[2]) - try - thisdict[k2] = func(v2) - catch err - println("Error processing key ", k2, " with value ", v2) - rethrow(err) - end - end - headerdict[k] = thisdict - else - func = field_key_dict[k] - try - headerdict[k] = func(v) - catch err - println("Error processing key ", k, " with value ", v) - rethrow(err) - end - end - end - end - return headerdict -end - -function imagine2nrrd(sheader::IO, h::Dict{ASCIIString, Any}, datafilename = nothing) - println(sheader, "NRRD0001") - T = h["pixel data type"] - if T<:AbstractFloat - println(sheader, "type: ", (T == Float32) ? "float" : "double") - else - println(sheader, "type: ", lowercase(string(T))) - end - sz = [h["image width"], h["image height"], h["frames per stack"], h["nStacks"]] - kinds = ["space", "space", "space", "time"] - if sz[end] == 1 - sz = sz[1:3] - kinds = kinds[[1,2,4]] - end - println(sheader, "dimension: ", length(sz)) - print(sheader, "sizes:") - for z in sz - print(sheader, " ", z) - end - print(sheader, "\nkinds:") - for k in kinds - print(sheader, " ", k) - end - print(sheader, "\n") - println(sheader, "encoding: raw") - println(sheader, "endian: ", nrrd_endian_dict[h["byte order"]]) - if isa(datafilename, AbstractString) - println(sheader, "data file: ", datafilename) - end - sheader -end - -function imagine2nrrd(nrrdname::AbstractString, h::Dict{ASCIIString, Any}, datafilename = nothing) - sheader = open(nrrdname, "w") - imagine2nrrd(sheader, h, datafilename) - close(sheader) -end - -end From f7dc850549c0167821dc35d6b3440e7748231489 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 27 Sep 2015 15:15:27 -0500 Subject: [PATCH 09/14] Move SIF support to AndorSIF --- src/Images.jl | 1 - src/ioformats/SIF.jl | 188 ------------------------------------------- src/jlimage.c | 149 ---------------------------------- 3 files changed, 338 deletions(-) delete mode 100644 src/ioformats/SIF.jl delete mode 100644 src/jlimage.c diff --git a/src/Images.jl b/src/Images.jl index 591ce426..48760697 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -42,7 +42,6 @@ include("labeledarrays.jl") include("algorithms.jl") include("connected.jl") include("edge.jl") -include(joinpath("ioformats", "SIF.jl")) function precompile() for T in (UInt8, UInt16, Int, Float32, Float64) diff --git a/src/ioformats/SIF.jl b/src/ioformats/SIF.jl deleted file mode 100644 index 7239cbfd..00000000 --- a/src/ioformats/SIF.jl +++ /dev/null @@ -1,188 +0,0 @@ -# SIF.jl, adds an imread function for Andor .sif images -# 2013 Ronald S. Rock, Jr. -using FileIO: skipmagic, stream, @format_str, Stream -function FileIO.load(fs::Stream{format"AndorSIF"}) - # line 1 - skipmagic(fs, 0) - io = stream(fs) - # line 2 - l = strip(readline(io)) - l == "65538 1" || error("Unknown Andor version number at line 2: " * l) - - # line 3: TInstaImage thru "Head model" - l = strip(readline(io)) - fields = split(l) - fields[1] == "65547" || fields[1] == "65558" || - error("Unknown TInstaImage version number at line 3: " * fields[1]) - - ixon = Dict{Any,Any}() - ixon["data_type"] = round(Int,fields[2]) - ixon["active"] = convert(Int,fields[3]) - ixon["structure_vers"] = round(Int,fields[4]) # (== 1) - # date is recored as seconds counted from 1970.1.1 00:00:00 - ixon["date"] = round(Int,fields[5]) # need to convert to actual date - ixon["temperature"] = max(round(Int,fields[6]), round(Int,fields[48])) - ixon["temperature_stable"] = round(Int,fields[6]) != -999 - ixon["head"] = fields[7] - ixon["store_type"] = fields[8] - ixon["data_type"] = fields[9] - ixon["mode"] = fields[10] - ixon["trigger_source"] = fields[11] - ixon["trigger_level"] = fields[12] - ixon["exposure_time"] = float(fields[13]) - ixon["frame_delay"] = float(fields[14]) - ixon["integration_cycle_time"] = float(fields[15]) - ixon["no_integrations"] = round(Int,fields[16]) - ixon["sync"] = fields[17] - ixon["kin_cycle_time"] = float(fields[18]) - ixon["pixel_readout_time"] = float(fields[19]) - ixon["no_points"] = round(Int,fields[20]) - ixon["fast_track_height"] = round(Int,fields[21]) - ixon["gain"] = round(Int,fields[22]) - ixon["gate_delay"] = float(fields[23]) - ixon["gate_width"] = float(fields[24]) - ixon["gate_step"] = float(fields[25]) - ixon["track_height"] = round(Int,fields[26]) - ixon["series_length"] = round(Int,fields[27]) - ixon["read_pattern"] = fields[28] - ixon["shutter_delay"] = fields[29] - ixon["st_center_row"] = round(Int,fields[30]) - ixon["mt_offset"] = round(Int,fields[31]) - ixon["operation_mode"] = fields[32] - ixon["flipx"] = fields[33] - ixon["flipy"] = fields[34] - ixon["clock"] = fields[35] - ixon["aclock"] = fields[36] - ixon["MCP"] = fields[37] - ixon["prop"] = fields[38] - ixon["IOC"] = fields[39] - ixon["freq"] = fields[40] - ixon["vert_clock_amp"] = fields[41] - ixon["data_v_shift_speed"] = float(fields[42]) - ixon["output_amp"] = fields[43] - ixon["pre_amp_gain"] = float(fields[44]) - ixon["serial"] = round(Int,fields[45]) - ixon["num_pulses"] = round(Int,fields[46]) - ixon["m_frame_transfer_acq_mode"] = round(Int,fields[47]) - ixon["unstabilized_temperature"] = round(Int,fields[48]) - ixon["m_baseline_clamp"] = round(Int,fields[49]) - ixon["m_pre_scan"] = round(Int,fields[50]) - ixon["m_em_real_gain"] = round(Int,fields[51]) - ixon["m_baseline_offset"] = round(Int,fields[52]) - _ = fields[53] - _ = fields[54] - ixon["sw_vers1"] = round(Int,fields[55]) - ixon["sw_vers2"] = round(Int,fields[56]) - ixon["sw_vers3"] = round(Int,fields[57]) - ixon["sw_vers4"] = round(Int,fields[58]) - - # line 4 - ixon["camera_model"] = strip(readline(io)) - - # line 5, something like camera dimensions?? - _ = readline(io) - - # line 6 - ixon["original_filename"] = strip(readline(io)) - - # line 7 - l = strip(readline(io)) - fields = split(l) - fields[1] == "65538" || error("Unknown TUserText version number in line 7: $fields[1]") - usertextlen = round(Int,fields[2]) # don't need? - - # line 8 - usertext = strip(readline(io)) - # ixon["usertext"] = usertext # Not useful - - # line 9 TShutter - l = strip(readline(io)) # Weird! - - # line 10 TCalibImage - l = strip(readline(io)) - - # lines 11-22 - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - _ = strip(readline(io)) - - # what a bizarre file format here - # length of the next string is in this line - next_str_len = round(Int,strip(readline(io))) - # and here is the next string, followed by the length - # of the following string, with no delimeter in between! - l = strip(readline(io)) - next_str_len = round(Int,l[(next_str_len + 1):end]) - # lather, rinse, repeat... - l = strip(readline(io)) - next_str_len = round(Int,l[(next_str_len + 1):end]) - l = strip(readline(io)) - l = l[(next_str_len + 1):end] - fields = split(l) - fields[1] == "65538" || error("Unknown version number at image dims record") - ixon["image_format_left"] = round(Int,fields[2]) - ixon["image_format_top"] = round(Int,fields[3]) - ixon["image_format_right"] = round(Int,fields[4]) - ixon["image_format_bottom"] = round(Int,fields[5]) - frames = round(Int,fields[6]) - ixon["frames"] = frames - ixon["num_subimages"] = round(Int,fields[7]) - ixon["total_length"] = round(Int,fields[8]) # in pixels across all frames - ixon["single_frame_length"] = round(Int,fields[9]) - - # Now at the first (and only) subimage - l = strip(readline(io)) - fields = split(l) - fields[1] == "65538" || error("unknown TSubImage version number: " * fields[1]) - left = round(Int,fields[2]) - top = round(Int,fields[3]) - right = round(Int,fields[4]) - bottom = round(Int,fields[5]) - vertical_bin = round(Int,fields[6]) - horizontal_bin = round(Int,fields[7]) - subimage_offset = round(Int,fields[8]) - - # calculate frame width, height, with binning - width = right - left + 1 - mod = width%horizontal_bin - width = round(Int,(width - mod)/horizontal_bin) - height = top - bottom + 1 - mod = height%vertical_bin - height = round(Int,(height - mod)/vertical_bin) - - ixon["left"] = left - ixon["top"] = top - ixon["right"] = right - ixon["bottom"] = bottom - ixon["vertical_bin"] = vertical_bin - ixon["horizontal_bin"] = horizontal_bin - ixon["subimage_offset"] = subimage_offset - - # rest of the header is a timestamp for each frame - # (actually, just a bunch of zeros). Skip - for i = 1:frames - _ = readline(io) - end - offset = position(io) # start of the actual pixel data, 32-bit float, little-endian - - pixels = read(io, Float32, width, height, frames) - prop = Compat.@compat Dict( - "colorspace" => "Gray", - "spatialorder" => ["y", "x"], - "ixon" => ixon, - "suppress" => Set({"ixon"}), - "pixelspacing" => [1, 1] - ) - if frames > 1 - prop["timedim"] = 3 - end - Image(float64(pixels), prop) -end diff --git a/src/jlimage.c b/src/jlimage.c deleted file mode 100644 index e36cc54c..00000000 --- a/src/jlimage.c +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include - -// Compile with: -// gcc -fPIC -shared -L/home/tim/src/julia jlimage.c -o libjlimage.so -lpng -ljulia-release - -// External declarations -void jl_error(const char *msg); - -// Internal declarations -void jl_png_read_close(void **png_p); -void jl_png_write_close(void **png_p); - - - -// Implementations -int jl_png_libpng_ver_major(void) -{ - return PNG_LIBPNG_VER_MAJOR; -} - -int jl_png_libpng_ver_minor(void) -{ - return PNG_LIBPNG_VER_MINOR; -} - -int jl_png_libpng_ver_release(void) -{ - return PNG_LIBPNG_VER_RELEASE; -} - -void** jl_png_read_init(int fd) -{ - // We have to return multiple pointers. Pack them into a single - // memory block. - void **png_p = (void**) malloc(3*sizeof(void*)); - if (png_p == NULL) - return NULL; - png_p[0] = (void*) png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_p[0] == NULL) { - free(png_p); - return NULL; - } - png_p[1] = (void*) png_create_info_struct((png_structp)(png_p[0])); - if (png_p[1] == NULL) { - png_destroy_read_struct((png_structpp) png_p, (png_infopp)NULL, (png_infopp)NULL); - free(png_p); - return NULL; - } - // Open a traditional C file stream from the ios_t file descriptor - png_p[2] = fdopen(fd, "r"); - if (png_p[2] == NULL) { - png_destroy_read_struct((png_structpp) png_p, (png_infopp) (png_p+1), (png_infopp)NULL); - free(png_p); - return NULL; - } - // Set up the default error-handling scheme (to free the allocated memory) - if (setjmp(((png_structp) (png_p[0]))->jmpbuf)) { - jl_png_read_close(png_p); - jl_errorf("PNG read error"); - } - // Initialize I/O - png_init_io((png_structp) (png_p[0]), (FILE*) (png_p[2])); - - return png_p; -} - -int jl_png_read_image(png_structp png_ptr, png_infop info_ptr, char *imbuf) -{ - png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); - png_uint_32 height = png_get_image_height(png_ptr, info_ptr); - char **row_pointers = malloc(height*sizeof(char*)); - if (row_pointers == NULL) - return -1; - int i; - for (i = 0; i < height; i++) - row_pointers[i] = imbuf + i*((long) rowbytes); - png_read_image(png_ptr, (png_bytepp) row_pointers); - png_read_end(png_ptr, info_ptr); - free(row_pointers); - return 0; -} - -void jl_png_read_close(void **png_p) -{ - if (png_p != NULL) { - png_destroy_read_struct((png_structpp) png_p, (png_infopp) (png_p+1), (png_infopp)NULL); - fclose(png_p[2]); - free(png_p); - } -} - -void** jl_png_write_init(int fd) -{ - void **png_p = (void**) malloc(3*sizeof(void*)); - if (png_p == NULL) - return NULL; - png_p[0] = (void*) png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_p[0] == NULL) { - free(png_p); - return NULL; - } - png_p[1] = (void*) png_create_info_struct((png_structp)(png_p[0])); - if (png_p[1] == NULL) { - png_destroy_write_struct((png_structpp) png_p, (png_infopp)NULL); - free(png_p); - return NULL; - } - png_p[2] = fdopen(fd, "w"); - if (png_p[2] == NULL) { - png_destroy_write_struct((png_structpp) png_p, (png_infopp) (png_p+1)); - free(png_p); - return NULL; - } - // Set up the default error-handling scheme (to free the allocated memory) - if (setjmp(((png_structp) (png_p[0]))->jmpbuf)) { - jl_png_write_close(png_p); - jl_errorf("PNG write error"); - } - // Initialize I/O - png_init_io((png_structp) (png_p[0]), (FILE*) (png_p[2])); - - return png_p; -} - -int jl_png_write_image(png_structp png_ptr, png_infop info_ptr, char *imbuf) -{ - png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); - png_uint_32 height = png_get_image_height(png_ptr, info_ptr); - char **row_pointers = malloc(height*sizeof(char*)); - if (row_pointers == NULL) - return -1; - int i; - for (i = 0; i < height; i++) - row_pointers[i] = imbuf + i*((long) rowbytes); - png_write_image(png_ptr, (png_bytepp) row_pointers); - png_write_end(png_ptr, info_ptr); - free(row_pointers); - return 0; -} - -void jl_png_write_close(void **png_p) -{ - if (png_p != NULL) { - png_destroy_write_struct((png_structpp) png_p, (png_infopp) (png_p+1)); - fclose(png_p[2]); - free(png_p); - } -} From 87fbf38c9d6160c3725719f41eb84d42d4c50757 Mon Sep 17 00:00:00 2001 From: Sdanisch Date: Mon, 28 Sep 2015 01:06:56 +0200 Subject: [PATCH 10/14] remove build of imagemagick --- REQUIRE | 2 - deps/build.jl | 105 -------------------------------------------------- 2 files changed, 107 deletions(-) delete mode 100644 deps/build.jl diff --git a/REQUIRE b/REQUIRE index 6fc1ad89..b90fd1d7 100644 --- a/REQUIRE +++ b/REQUIRE @@ -2,8 +2,6 @@ julia 0.3 Compat 0.4 Colors ColorVectorSpace -BinDeps -@osx Homebrew SIUnits Zlib Graphics 0.1 diff --git a/deps/build.jl b/deps/build.jl deleted file mode 100644 index 36c7beac..00000000 --- a/deps/build.jl +++ /dev/null @@ -1,105 +0,0 @@ -using BinDeps, Compat - -@BinDeps.setup - -mpath = get(ENV, "MAGICK_HOME", "") # If MAGICK_HOME is defined, add to library search path -if !isempty(mpath) - push!(DL_LOAD_PATH, mpath) - push!(DL_LOAD_PATH, joinpath(mpath,"lib")) -end -libnames = ["libMagickWand", "CORE_RL_wand_"] -suffixes = ["", "-Q16", "-6.Q16", "-Q8"] -options = ["", "HDRI"] -extensions = ["", ".so.2", ".so.4", ".so.5"] -aliases = vec(libnames.*transpose(suffixes).*reshape(options,(1,1,length(options))).*reshape(extensions,(1,1,1,length(extensions)))) -libwand = library_dependency("libwand", aliases = aliases) - -initfun = """ -__init__() = ccall((:MagickWandGenesis,libwand), Void, ()) -""" - -@linux_only begin - kwargs = Any[(:onload, initfun)] - provides(AptGet, "libmagickwand4", libwand; kwargs...) - provides(AptGet, "libmagickwand5", libwand; kwargs...) - provides(AptGet, "libmagickwand-6.q16-2", libwand; kwargs...) - provides(Pacman, "imagemagick", libwand; kwargs...) - provides(Yum, "ImageMagick", libwand; kwargs...) -end - -# TODO: remove me when upstream is fixed -@windows_only push!(BinDeps.defaults, BuildProcess) - -@windows_only begin - const OS_ARCH = (WORD_SIZE == 64) ? "x64" : "x86" - - # TODO: checksums: we have gpg - # Extract the appropriate filename to download - magick_base = "http://www.imagemagick.org/download/binaries" - binariesfn = download(magick_base) - str = readall(binariesfn) - pattern = "ImageMagick-6.9.*?-Q16-$(OS_ARCH)-dll.exe" - m = match(Regex(pattern), str) - magick_exe = convert(ASCIIString, m.match) - - magick_tmpdir = BinDeps.downloadsdir(libwand) - magick_url = "$(magick_base)/$(magick_exe)" - magick_libdir = joinpath(BinDeps.libdir(libwand), OS_ARCH) - - innounp_url = "https://bintray.com/artifact/download/julialang/generic/innounp.exe" - - provides(BuildProcess, - (@build_steps begin - CreateDirectory(magick_tmpdir) - CreateDirectory(magick_libdir) - FileDownloader(magick_url, joinpath(magick_tmpdir, magick_exe)) - FileDownloader(innounp_url, joinpath(magick_tmpdir, "innounp.exe")) - @build_steps begin - ChangeDirectory(magick_tmpdir) - info("Installing ImageMagick library") - `innounp.exe -q -y -b -e -x -d$(magick_libdir) $(magick_exe)` - end - end), - libwand, - os = :Windows, - unpacked_dir = magick_libdir, - preload = - """ - ENV["MAGICK_CONFIGURE_PATH"] = \"$(escape_string(magick_libdir))\" - ENV["MAGICK_CODER_MODULE_PATH"] = \"$(escape_string(magick_libdir))\" - """, - onload = initfun) -end - -@osx_only begin - if Pkg.installed("Homebrew") === nothing - error("Homebrew package not installed, please run Pkg.add(\"Homebrew\")") - end - using Homebrew - provides( Homebrew.HB, "imagemagick", libwand, os = :Darwin, onload = - """ - function __init__() - ENV["MAGICK_CONFIGURE_PATH"] = joinpath("$(Homebrew.prefix("imagemagick"))","lib","ImageMagick","config-Q16") - ENV["MAGICK_CODER_MODULE_PATH"] = joinpath("$(Homebrew.prefix("imagemagick"))", "lib","ImageMagick","modules-Q16","coders") - ENV["PATH"] = joinpath("$(Homebrew.prefix("imagemagick"))", "bin") * ":" * ENV["PATH"] - ccall((:MagickWandGenesis,libwand), Void, ()) - end - """ ) -end - -@BinDeps.install Dict([(:libwand, :libwand)]) - -# Save the library version; by checking this now, we avoid a runtime dependency on libwand -# See https://github.com/timholy/Images.jl/issues/184#issuecomment-55643225 -module CheckVersion -using Compat -include("deps.jl") -if isdefined(:__init__) - __init__() -end -p = ccall((:MagickQueryConfigureOption, libwand), Ptr{UInt8}, (Ptr{UInt8},), "LIB_VERSION_NUMBER") -vstr = string("v\"", join(split(bytestring(p), ',')[1:3], '.'), "\"") -open(joinpath(dirname(@__FILE__),"versioninfo.jl"), "w") do file - write(file, "const libversion = $vstr\n") -end -end From 7fb68914cf2a5053c35f96f56defa14c2415103e Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 27 Sep 2015 17:52:17 -0500 Subject: [PATCH 11/14] Dump extra output for failing ScaleAutoMinMax(UInt16) test --- test/map.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/map.jl b/test/map.jl index a6ea4599..de7a443d 100644 --- a/test/map.jl +++ b/test/map.jl @@ -192,10 +192,16 @@ facts("Map") do @chk map(mapi, A) RGB24[0x00000000, 0x00808080, 0x00ffffff] # Issue #304 - imgr = colorim(rand(UInt16, 3, 2, 2)) - mi = ScaleAutoMinMax(RGB{Ufixed16}) - res = map(mi, imgr) - @fact raw(res) --> raw(map(ScaleAutoMinMax(Ufixed16), raw(imgr))) + A = rand(UInt16, 3, 2, 2) + imgr = colorim(A) + mi1 = ScaleAutoMinMax(RGB{Ufixed16}) + res1 = raw(map(mi1, imgr)) + mi2 = ScaleAutoMinMax(Ufixed16) + res2 = raw(map(mi2, raw(imgr))) + if res1 != res2 + @show A + end + @fact res1 --> res2 end context("Scaling and ssd") do From 3c3739cf2938509fe2f26674d9f150ba2acd0351 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 27 Sep 2015 20:39:16 -0500 Subject: [PATCH 12/14] Register writemime, but dispatch via FileIO --- src/Images.jl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Images.jl b/src/Images.jl index 48760697..f8166887 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -240,6 +240,17 @@ import FileIO: load, save @deprecate imread load @deprecate imwrite save export load, save + +# only mime writeable to PNG if 2D (used by IJulia for example) +mimewritable(::MIME"image/png", img::AbstractImage) = sdims(img) == 2 && timedim(img) == 0 +# We have to disable Color's display via SVG, because both will get +# sent with unfortunate results. See IJulia issue #229 +mimewritable{T<:Color}(::MIME"image/svg+xml", ::AbstractMatrix{T}) = false + +function __init__() + add_mime(MIME("image/png"), AbstractImage, :ImageMagick) +end + import Base: scale, scale! # delete when deprecations are removed @deprecate scaleminmax ScaleMinMax @deprecate scaleminmax(img::AbstractArray, min::Real, max::Real) ScaleMinMax(RGB24, img, min, max) @@ -259,7 +270,6 @@ import Base: scale, scale! # delete when deprecations are removed @deprecate copy(A::AbstractArray, B::AbstractArray) copyproperties(A, B) @deprecate share(A::AbstractArray, B::AbstractArray) shareproperties(A, B) - const ScaleInfo = MapInfo # can't deprecate types? end From 7358c40fad47872b6b7ff8ba15f3f3772f5d860b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 28 Sep 2015 10:58:42 -0500 Subject: [PATCH 13/14] Fix argument order in imwrite deprecation, and add kwargs to imread --- src/Images.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Images.jl b/src/Images.jl index f8166887..6b943d0f 100644 --- a/src/Images.jl +++ b/src/Images.jl @@ -237,8 +237,8 @@ export # Deprecated exports import FileIO: load, save -@deprecate imread load -@deprecate imwrite save +@deprecate imread(filename; kwargs...) load(filename; kwargs...) +@deprecate imwrite(img, filename; kwargs...) save(filename, img; kwargs...) export load, save # only mime writeable to PNG if 2D (used by IJulia for example) From 9d7fe2be09eb65c8111e5f263442bda643fc329f Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 28 Sep 2015 11:15:47 -0500 Subject: [PATCH 14/14] Re-add Clamp client for mapinfo --- src/map.jl | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/map.jl b/src/map.jl index 0cad5e29..725afebb 100644 --- a/src/map.jl +++ b/src/map.jl @@ -478,7 +478,30 @@ mapinfo{CV<:TransparentColor}(::Type{UInt32}, img::AbstractArray{CV}) = mapinfo( mapinfo(::Type{UInt32}, img::AbstractArray{UInt32}) = MapNone{UInt32}() -# ImageMagick client is defined in io.jl +# Clamping mapinfo client. Converts to RGB and uses Ufixed, clamping +# floating-point values to [0,1]. +mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{T}) = MapNone{T}() +mapinfo{T<:AbstractFloat}(::Type{Clamp}, img::AbstractArray{T}) = ClampMinMax(Ufixed8, zero(T), one(T)) +for ACV in (Color, AbstractRGB) + for CV in subtypes(ACV) + (length(CV.parameters) == 1 && !(CV.abstract)) || continue + CVnew = CV<:AbstractGray ? Gray : RGB + @eval mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{$CV{T}}) = MapNone{$CVnew{T}}() + @eval mapinfo{CV<:$CV}(::Type{Clamp}, img::AbstractArray{CV}) = Clamp{$CVnew{Ufixed8}}() + CVnew = CV<:AbstractGray ? Gray : BGR + AC, CA = alphacolor(CV), coloralpha(CV) + ACnew, CAnew = alphacolor(CVnew), coloralpha(CVnew) + @eval begin + mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{$AC{T}}) = MapNone{$ACnew{T}}() + mapinfo{P<:$AC}(::Type{Clamp}, img::AbstractArray{P}) = Clamp{$ACnew{Ufixed8}}() + mapinfo{T<:Ufixed}(::Type{Clamp}, img::AbstractArray{$CA{T}}) = MapNone{$CAnew{T}}() + mapinfo{P<:$CA}(::Type{Clamp}, img::AbstractArray{P}) = Clamp{$CAnew{Ufixed8}}() + end + end +end +mapinfo(::Type{Clamp}, img::AbstractArray{RGB24}) = MapNone{RGB{Ufixed8}}() +mapinfo(::Type{Clamp}, img::AbstractArray{ARGB32}) = MapNone{BGRA{Ufixed8}}() + # Backwards-compatibility uint32color(img) = map(mapinfo(UInt32, img), img)