Skip to content

Instantly share code, notes, and snippets.

@daniel-perry
Created April 11, 2015 19:56
Show Gist options
  • Save daniel-perry/6dc0640536c09d12c265 to your computer and use it in GitHub Desktop.
Save daniel-perry/6dc0640536c09d12c265 to your computer and use it in GitHub Desktop.
rough go at converting .psb (photoshop) image to raw data (block of ints). Assumes .psb is not compressed and uses RGB (easy to change to grayscale).
# converts a .psb (photoshop photo type) to a raw image format.
#
# Raw format:
# height Uint32
# width Uint32
# depth Uint32 (8,16,32)
# data block Uint8, Uint16, Uint32 (depending on depth value = 8, 16, 32)
# using file description Oct 2013 version here:
# https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
function main()
if length(ARGS) != 2
println("usage: script.jl in.psb out.raw")
return
end
infn = ARGS[1]
outfn = ARGS[2]
f = open(infn)
println("Parsing header info..")
################
# File header
###############
magic_num = read(f,Uint8,4)
magic_str = @sprintf("%s%s%s%s", utf32(magic_num[1]),utf32(magic_num[2]),utf32(magic_num[3]),utf32(magic_num[4]))
if magic_str != "8BPS"
println("BAD magic number: ", magic_str)
return
end
version = ntoh(read(f,Uint16))
if !(version == 1 || version == 2)
println("BAD version number: ", version)
return
else
println("file version ", version)
end
reserved_zero = read(f,Uint8,6)
channels = ntoh(read(f, Uint16))
println("channels: ", channels)
height = ntoh(read(f, Uint32))
println("height: ", height)
if version == 1 && height > 30000
println("invalid image height ",height, " > 30,000")
return
elseif version == 2 && height > 300000
println("invalid image height ", height, " > 300,000")
return
end
width = ntoh(read(f, Uint32))
println("width: ", width)
if version == 1 && width > 30000
println("invalid image width ",width, " > 30,000")
return
elseif version == 2 && width > 300000
println("invalid image width ", width, " > 300,000")
return
end
depth = ntoh(read(f, Uint16))
println("depth: ", depth)
colormode = ntoh(read(f, Uint16))
# Bitmap = 0; Grayscale = 1; Indexed = 2; RGB = 3; CMYK = 4; Multichannel = 7; Duotone = 8; Lab = 9
if colormode == 0
println("colomode: Bitmap (0)")
elseif colormode == 1
println("colomode: Grayscale (1)")
elseif colormode == 2
println("colomode: Indexed (2)")
elseif colormode == 3
println("colomode: RGB (3)")
elseif colormode == 4
println("colomode: CMYK (4)")
elseif colormode == 7
println("colomode: Multichannel (7)")
elseif colormode == 8
println("colomode: Duotone (8)")
elseif colormode == 9
println("colomode: Lab (9)")
else
println("invalid colormode: ", colormode)
return
end
if false
####################
# Color mode data
###################
color_mode_length = ntoh(read(f, Uint32))
if color_mode_length > 0
println("Indexed and duotone colormodes not yet supported.")
return
end
###################
# Image resource section
##################
image_resource_section = ntoh(read(f, Uint32))
if image_resource_section > 0
println("warning: image resource section contains data, not yet supported, skipping ", image_resource_section, " bytes.")
throw_away = read(f, Uint8, image_resource_section)
end
####################
# Layers and mask section
####################
layers_and_mask_section = ntoh(read(f,Uint32))
if layers_and_mask_section > 0
println("warning: layers and mask section contains data, not yet supported, skipping ", layers_and_mask_section, " bytes.")
throw_away = read(f, Uint8, layers_and_mask_section)
end
###################
# Image data section
##################
println("parsing image data..")
image_data_length = ntoh(read(f, Uint16))
println("image data length: ", image_data_length)
end # commenting out header sections
# Quick hack - skip to end of file and backup the size of the image.. if it's uncompressed we should be able to extract the image data.
# skip to end of file
pos = position(f)
tmp = read(f,Uint8,1)
pos2 = position(f)
pos_per_byte = pos2-pos
uncompressed_image_data_length_bytes = height * width * channels * div(depth,8)
println("data length (B): ", uncompressed_image_data_length_bytes )
println("data length (GB): ", uncompressed_image_data_length_bytes / 1028^3 )
seekend(f)
pos_end = position(f)
pos_im_start = pos_end - pos_per_byte * uncompressed_image_data_length_bytes
seek(f, pos_im_start)
if depth == 8
PixelType = Uint8
elseif depth == 16
PixelType = Uint16
elseif depth == 32
PixelType = Uint32
else
println("unsupported depth value: ", depth)
end
comp_length = div(uncompressed_image_data_length_bytes,3)
# read red data
data = read(f, PixelType, comp_length)
red_fn = @sprintf("%s_red.raw",outfn)
outf = open(red_fn,"w")
write(outf, convert(Uint32,height))
write(outf, convert(Uint32,width))
write(outf, convert(Uint32,depth))
write(outf, data)
close(outf)
# read green data
data = read(f, PixelType, comp_length)
green_fn = @sprintf("%s_green.raw",outfn)
outf = open(green_fn,"w")
write(outf, convert(Uint32,height))
write(outf, convert(Uint32,width))
write(outf, convert(Uint32,depth))
write(outf, data)
close(outf)
# read blue data
data = read(f, PixelType, comp_length)
blue_fn = @sprintf("%s_blue.raw",outfn)
outf = open(blue_fn,"w")
write(outf, convert(Uint32,height))
write(outf, convert(Uint32,width))
write(outf, convert(Uint32,depth))
write(outf,data)
close(outf)
close(f)
end
main()
# read in 3 raw images representing r,g,b components, and write out a grey component
function main()
if length(ARGS) != 4
println("usage: script.jl red_in.raw green_in.raw blue_in.raw grey_out.raw")
return
end
redfn = ARGS[1]
greenfn = ARGS[2]
bluefn = ARGS[3]
outfn = ARGS[4]
#buffer_size = 1028^3 # 1 GB buffer size per channel
buffer_size = 100 * 1028^2 # 100 MB buffer size per channel
# read red data
redf = open(redfn)
height = read(redf, Uint32)
width = read(redf, Uint32)
depth = read(redf, Uint32)
data_size_bytes = height*width* div(depth,8)
PixelType = Uint8
if(depth == 8)
PixelType = Uint8
elseif(depth == 16)
PixelType = Uint16
elseif(depth == 32)
PixelType = Uint32
else
println("error don't know how to handle depth ", depth)
return
end
# verify we have corresponding green and red files:
greenf = open(greenfn)
h = read(greenf,Uint32)
w = read(greenf,Uint32)
d = read(greenf,Uint32)
if( h != height || w != width || d != depth)
println("error the sizes don't agree between red and green.")
return
end
# verify we have corresponding blue and red files:
bluef = open(bluefn)
h = read(bluef,Uint32)
w = read(bluef,Uint32)
d = read(bluef,Uint32)
if( h != height || w != width || d != depth)
println("error the sizes don't agree between red and blue.")
return
end
println("height: ", height)
println("width: ", width)
println("depth: ", depth)
println("data size (B): ", data_size_bytes)
println("data size (GB): ", data_size_bytes / 1028^3)
outf = open(outfn,"w")
write(outf, height)
write(outf, width)
write(outf, depth)
read_size = min(buffer_size, data_size_bytes)
bytes_read = 0
while read_size > 0 #bytes_read + read_size <= data_size_bytes
red_buffer = read(redf, PixelType, read_size)
green_buffer = read(greenf, PixelType, read_size)
blue_buffer = read(bluef, PixelType, read_size)
# rgb to grayscale
# see http://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/
# 0.21 R + 0.72 G + 0.07 B.
gray_buffer = convert(Array{PixelType,1}, int( 0.21 * red_buffer + 0.72 * green_buffer + 0.07 * blue_buffer))
write(outf, gray_buffer)
# finish up remainder:
bytes_read += read_size
if bytes_read + read_size > data_size_bytes
read_size = data_size_bytes - bytes_read
end
end
close(redf)
close(greenf)
close(bluef)
close(outf)
end
main()
# subsample a large raw file into a nrrd for viewing, etc.
using Images
function main()
infn = ARGS[1]
outfn = ARGS[2]
subsample = 2
inf = open(infn)
height = read(inf, Uint32)
width = read(inf, Uint32)
depth = read(inf, Uint32)
PixelType = Uint8
if(depth == 8)
PixelType = Uint8
elseif(depth == 16)
PixelType = Uint16
elseif(depth == 32)
PixelType = Uint32
else
println("uknown depth ", depth)
return
end
data_length = height * width * div(depth,8)
data = read(inf, PixelType, data_length)
close(inf)
data = reshape(data, (convert(Int64,height), convert(Int64,width)))
data = data[1:subsample:end, 1:subsample:end]
imwrite(grayim(data), outfn)
end
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment