Gitlab will be down on Friday 25th May (from 9:00 am to 12:00 )

...
 
Commits (5)
......@@ -13,6 +13,10 @@ greenjson=$(trim:%.trim.jpg=%.green.json)
blue=$(trim:%.trim.jpg=%.blue.png)
bluejson=$(trim:%.trim.jpg=%.blue.json)
snapshots=$(shell ls snapshots/*.pdf)
snapshotsjpg=$(snapshots:%.pdf=%.jpg)
snapshots: $(snapshotsjpg)
trim: $(trim)
contours: $(contourspng) $(contourssvg) $(contoursjson)
gradients: $(gradientsvg) $(gradientpng) $(gradientjson)
......@@ -22,6 +26,11 @@ zapzeros:
find sample -size 0 -exec rm {} \;
cleandata:
rm $(redjson) $(greenjson) $(bluejson) $(gradientjson) $(contoursjson)
cleancontourspng:
rm $(contourspng)
cleangradientpng:
rm $(gradientpng)
# sample.csv: csv/export_mim.csv
sample.csv: csv/mim.normalized.csv
......@@ -37,18 +46,16 @@ sample.json: sample.csv scripts/csv2json.py
sample_with_data.json: sample.json $(contoursjson) $(gradientjson) $(redjson) $(greenjson) $(bluejson)
scripts/joindata.py $^ > $@
poster.pdf: sample_with_data.json scripts/orderings.poster.py $(red) $(green) $(blue) $(gradientpng) $(contourspng)
scripts/orderings.poster.py --filterzeros $< --output $@
poster2.pdf: sample_with_data.json scripts/orderings.poster.py $(red) $(green) $(blue) $(gradientpng) $(contourspng)
scripts/orderings.poster.py --pagesize A1 --columns 36 --fontsize 7 --filterzeros $< --output $@
sample/exif.json:
exiftool -FileModifyDate --json
# sample/exif.json:
# exiftool -FileModifyDate --json
# Contours
%.contours.png %.contours.svg: %.trim.jpg
bin/contours $< $*.contours.png > $*.contours.svg
%.contours.svg: %.trim.jpg
bin/contours $< tmp.png > $*.contours.svg
rm tmp.png
%.contours.png: %.contours.svg
inkscape --export-png=$@ $<
%.contours.json: %.contours.svg
scripts/svgcountpaths.py $< --polyline --json --id $*.jpg --key contours --img $*.contours.png > $@
......@@ -58,7 +65,8 @@ sample/exif.json:
scripts/imagegradient.py $< --svg $*.gradient.svg
%.gradient.png: %.gradient.svg
inkscape --export-png=$*.gradient.png --export-background="#EEEEEE" $<
inkscape --export-png=$*.gradient.png $<
# inkscape --export-png=$*.gradient.png --export-background="#EEEEEE" $<
%.gradient.json: %.gradient.svg
scripts/svgpathlength.py $< --json --id $*.jpg --key gradient --img $*.gradient.png > $@
......@@ -77,3 +85,37 @@ sample/exif.json:
convert $< -format %c histogram:info:- | scripts/histcount.py --json --id $*.jpg --key blue --img $*.blue.png > $@
%.jpg: %.pdf
convert $< $@
#
# POSTER
#
poster.pdf: sample_with_data.json scripts/orderings.poster.py $(red) $(green) $(blue) $(gradientpng) $(contourspng)
scripts/orderings.poster.py --filterzeros $< --output $@
poster2.pdf: sample_with_data.json scripts/orderings.poster.py $(red) $(green) $(blue) $(gradientpng) $(contourspng)
scripts/orderings.poster.py \
--pagesize A1 --landscape \
--columns 72 \
--fontsize 7 \
--filterzeros $< --output $@
poster3.pdf: sample_with_data.json scripts/orderings.poster.py $(red) $(green) $(blue) $(gradientpng) $(contourspng)
scripts/orderings.poster.py \
--pagesize A1 --landscape \
--columns 36 \
--fontsize 7 \
--filterzeros $< --output $@
poster3.tiles.pdf: poster3.pdf
pdfposter -m A4 -p A1 $< $@
poster4.pdf: sample_with_data.json scripts/orderings.poster.py $(red) $(green) $(blue) $(gradientpng) $(contourspng)
scripts/orderings.poster2.py \
--pagesize A1 --landscape \
--columns 101 \
--fontsize 7 \
--filterzeros $< --output $@
......@@ -35,12 +35,20 @@ X RGB
* text
* parse year ...
* deal with empty values
X deal with empty values
Rerun on larger selection
* Rerun on larger selection
Talk about "empty" or exceptional values ??? .... leave space on margins ???
* Talk about "empty" or exceptional values ??? .... leave space on margins ???
<!> Need to filter empty values / missing images.
* Filter zeros
Show a central column featuring a single image with all values IN CONTEXT.
Add landscape option!
New poster style: show a central column featuring a single image with all values IN CONTEXT.
monday evening
X Contours transparent, maybe heavier
* RGB transparent
* Gradients transparent
#!/usr/bin/env python3
from PIL import Image, ImageDraw
from numpy import *
from scipy.ndimage import filters
import sys, json, os, math
import argparse
def hsl_to_rgb (h, s, l):
# fix ranges for hsl values
if h == None:
h = 0
if h < 0 or h > 360:
h = h % 360
if s < 0:
s = 0
s = max(0.0, min(1.0, s))
l = max(0.0, min(1.0, l))
# From FvD 13.37, CSS Color Module Level 3
if l <= .5:
m2 = l * (1 + s)
else:
m2 = l + s - l * s
m1 = 2 * l - m2
def v(h):
if (h > 360):
h -= 360
elif (h < 0):
h += 360
if (h < 60):
return m1 + (m2 - m1) * h / 60
if (h < 180):
return m2
if (h < 240):
return m1 + (m2 - m1) * (240 - h) / 60
return m1
def vv(h):
return round(v(h) * 255)
return (int(vv(h + 120)), int(vv(h)), int(vv(h - 120)))
parser = argparse.ArgumentParser(description='Calculate an image gradient.')
parser.add_argument('input', help='an image path as input')
parser.add_argument('--format', default="magimage", help='save output format, default hslimage (direction is hue, magnitude is lightness). Other options: magimage (magnitude image), json.')
parser.add_argument('--output', help='save to output path')
parser.add_argument('--width', type=int, default=None, help='resize width, default: None (no resize)')
parser.add_argument('--svg', default=None, help='output svg path')
parser.add_argument('--svg-grid-size', type=int, default=25, help='density of svg arrows (default: 25)')
parser.add_argument('--svg-mag-scale', type=float, default=5.0, help='svg arrow magnitude scaler (default: 5.0)')
args = parser.parse_args()
# Based on Programming Computer Vision, chapter 1, Image Derivatives
p = args.input
path, base = os.path.split(p)
base, ext = os.path.splitext(base)
out = args.output # or os.path.join(path, base + ".gradient.png")
im = Image.open(p).convert('L')
width, height = im.size
if args.width:
scaled_height = int(height * (float(args.width)/width))
im.thumbnail((args.width, scaled_height))
width, height = args.width, scaled_height
im = array(im)
# Sobel derivative filters
# imx = zeros(im.shape)
# filters.sobel(im,1,imx)
# imy = zeros(im.shape)
# filters.sobel(im,0,imy)
# magnitude = sqrt(imx**2+imy**2)
sigma = 5 # standard deviation
imx = zeros(im.shape)
filters.gaussian_filter(im, (sigma,sigma), (0,1), imx)
imy = zeros(im.shape)
filters.gaussian_filter(im, (sigma,sigma), (1,0), imy)
magnitude = sqrt(imx**2+imy**2)
dirs = arctan2(imy, imx)
# Save as image
# pil_im = Image.fromarray(dirs)
# pil_im.convert("LA").save("dirs.png")
totalmag = 0.0
if out:
if args.format == "hslimage":
# Map direction to Hue, Magnitude to value
from math import pi
maxmag = amax(magnitude)
# height, width = magnitude.shape
im = Image.new("RGBA", (width, height))
# draw = ImageDraw.ImageDraw(im)
for y in range(height):
p = int(math.ceil(float(y)/height*100))
sys.stderr.write("\rCreating gradient HSL image... [{0}%]".format(p))
sys.stderr.flush()
for x in range(width):
d = dirs[y][x]
hue = ((d+pi) / (2 * pi)) * 360
m = magnitude[y][x]
value = (m/maxmag)
r, g, b = hsl_to_rgb(hue, 1.0, value)
im.putpixel((x, y), (r, g, b, 255))
# if args.svg and (x % args.svg_grid_size == 0) and (y % args.svg_grid_size == 0):
# x1, y1 = x, y
# x2 = x1 + (m * args.svg_mag_scale * math.cos(d))
# y2 = y1 + (m * args.svg_mag_scale * math.sin(d))
# print ("""<path
# style="fill:none;stroke:#00FFFF;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Send)"
# d="M {0},{1} {2},{3}"
# id="path2985"/>""".format(x1, y1, x2, y2), file=svgfile)
# totalmag += m
# draw.point((x, y), fill=(r,g,b,255))
sys.stderr.write("\n")
im.save(out)
elif args.format == "magimage":
pil_im = Image.fromarray(magnitude)
pil_im.convert("LA").save(out)
elif args.format == "json":
with open(out, "w") as f:
json.dump({
'dirs': dirs.tolist(),
'magnitudes': magnitude.tolist()
}, f)
if args.svg:
svgfile = open(args.svg, 'w')
print("""<svg version="1.1" baseProfile="full" width="{0[width]}" height="{0[height]}" xmlns="http://www.w3.org/2000/svg">
<defs
id="defs4">
<marker
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path3774"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#00FFFF;fill:#00FFFF;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
</defs>
<g
id="layer1">""".format({'width': width, 'height': height}), file=svgfile)
from math import pi
maxmag = amax(magnitude)
# height, width = magnitude.shape
im = Image.new("RGBA", (width, height))
# draw = ImageDraw.ImageDraw(im)
for y in range(0, height, args.svg_grid_size):
for x in range(0, width, args.svg_grid_size):
d = dirs[y][x]
hue = ((d+pi) / (2 * pi)) * 360
m = magnitude[y][x]
x1, y1 = x, y
x2 = x1 + (m * args.svg_mag_scale * math.cos(d))
y2 = y1 + (m * args.svg_mag_scale * math.sin(d))
print ("""<path
style="fill:none;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Send)"
d="M {0},{1} {2},{3}"
id="path2985"/>""".format(x1, y1, x2, y2), file=svgfile)
print ("""</g>
</svg>""", file=svgfile)
svgfile.close()
print (int(totalmag), file=sys.stdout)
# with open(os.path.join(path, base + ".gradient_mag.json"), "w") as f:
......@@ -11,7 +11,7 @@ import reportlab.lib.pagesizes
from reportlab.lib.units import inch, cm
from reportlab.pdfbase.ttfonts import TTFont, pdfmetrics
from reportlab.lib.utils import ImageReader
from reportlab.lib.colors import ghostwhite, grey, lightgrey
......@@ -69,6 +69,7 @@ ap.add_argument("--fontsize", type=float, default=14.0)
ap.add_argument("--groupborder", type=float, default=2.5, help="horizontal gap between groups")
ap.add_argument("--cellborder", type=float, default=0.10)
ap.add_argument("--pageborder", type=float, default=2.5)
ap.add_argument("--landscape", default=False, action="store_true")
ap.add_argument("data")
args = ap.parse_args()
......@@ -104,7 +105,11 @@ cellmargin = {
'bottom': args.cellborder*cm
}
groupborder = args.groupborder*cm
pagewidth, pageheight = pagesize
if args.landscape:
pageheight, pagewidth = pagesize
else:
pagewidth, pageheight = pagesize
cols = args.columns
usablewidth = pagewidth - pagemargin['left'] - pagemargin['right'] - 2*groupborder
cellwidth = usablewidth / cols
......@@ -119,7 +124,7 @@ groupcols = int(floor(cols / 3.0))
font = TTFont('LabelFont', args.font)
pdfmetrics.registerFont(font)
# PDF
canvas = Canvas(args.output, pagesize=pagesize)
canvas = Canvas(args.output, pagesize=(pagewidth, pageheight))
boxfill = 1,0,1
textcolor = 0,0,0
canvas.setStrokeColorRGB(0.0,0.0,0.0)
......@@ -127,14 +132,20 @@ canvas.setFont('LabelFont', args.fontsize)
print ("{0} items".format(len(data)), file=sys.stderr)
def drawImageBox (ipath, x, c, r, boxsize=100, drawBorder=False):
def drawImageBox (ipath, x, c, r, boxsize=100, drawBorder=False, valign="center"):
im = Image.open(ipath)
# boxsize sets the resolution of the image such that it fits in boxsize x boxsize pixels
im.thumbnail((boxsize, boxsize), Image.ANTIALIAS)
imw = (im.size[0]/boxsize) * ccw
imh = (im.size[1]/boxsize) * cch
# centering dx,dy
dx, dy = (ccw - imw) / 2, (cch - imh) / 2
if valign=="top":
dx, dy = (ccw - imw) / 2, (cch - imh)
elif valign=="center":
dx, dy = (ccw - imw) / 2, (cch - imh) / 2
else: # "bottom"
dx, dy = (ccw - imw) / 2, 0
cx = x + (c*cellwidth)
cy = pageheight - pagemargin['top'] - ((r+1)*cellheight)
# DRAW IMAGE
......@@ -143,11 +154,12 @@ def drawImageBox (ipath, x, c, r, boxsize=100, drawBorder=False):
cx+dx+cellmargin['left'],
cy+dy+cellmargin['bottom'],
width=imw,
height=imh
height=imh,
mask='auto' # https://stackoverflow.com/questions/1308710/transparency-in-pngs-with-reportlab-2-3#1625350
)
if drawBorder:
canvas.rect(cx, cy, cellwidth, cellheight)
return cx, cy, dx, dy
return cx, cy, dx, dy, imw, imh
r = 0
for sortkey in "name inventory image_filesize dimensions dating red green blue contours gradient".split():
......@@ -164,8 +176,6 @@ for sortkey in "name inventory image_filesize dimensions dating red green blue c
midpoint = len(sdata)//2
midstart = midpoint - (groupcols//2)
groups = sdata[0:groupcols], sdata[midstart:midstart+groupcols], sdata[-groupcols:]
# for x in groups:
# assert (len(x) == groupcols)
groupx = pagemargin['left']
fillDataBox = False
......@@ -173,48 +183,23 @@ for sortkey in "name inventory image_filesize dimensions dating red green blue c
c= 0
for i in group:
ipath = i['img']
drawImageBox(ipath, groupx, c, r+1)
# im = Image.open(ipath)
# im.thumbnail((100, 100), Image.ANTIALIAS)
# imw = (im.size[0]/100) * ccw
# imh = (im.size[1]/100) * cch
# # centering dx,dy
# dx, dy = (ccw - imw) / 2, (cch - imh) / 2
# cx = groupx + (c*cellwidth)
# cy = pageheight - pagemargin['top'] - ((r+1+1)*cellheight)
# # DRAW IMAGE
# canvas.drawImage(ImageReader(im), cx+dx+cellmargin['left'], cy+dy+cellmargin['bottom'], width=imw, height=imh)
# canvas.rect(cx, cy, cellwidth, cellheight)
# DRAW DATA BOX
# cy = pageheight - pagemargin['top'] - ((r+1)*cellheight)
cx, cy, dx, dy, imw, imh = drawImageBox(ipath, groupx, c, r+1, valign="top")
if 'img' in i[sortkey]:
drawImageBox(i[sortkey]['img'], groupx, c, r)
# add a fill option
# if fillDataBox:
# canvas.setFillColorRGB(*boxfill)
# canvas.rect(cx+dx+cellmargin['left'], cy+dy+cellmargin['bottom'], imw, imh, stroke=0, fill=1)
# drawTextCenteredInBox
# txt = i['FileModifyDate_parsed'].strftime("%Y-%m-%d %H:%M:%S")
drawImageBox(i[sortkey]['img'], groupx, c, r, valign="bottom")
txt = label(i[sortkey])
if txt:
cx = groupx + (c*cellwidth)
cy = pageheight - pagemargin['top'] - ((r+1)*cellheight)
canvas.setStrokeColor(lightgrey)
canvas.setLineWidth(0.05)
canvas.rect(cx+dx+cellmargin['left'],cy+cellmargin['bottom'],imw, imh)
canvas.setFillColorRGB(*textcolor)
# canvas.drawCentredString(cx+dx+cellmargin['left']+(imw/2), cy+dy+cellmargin['bottom']+(imh/2), "{0}".format(txt))
canvas.drawCentredString(cx+(cellwidth/2), cy+(cellheight/2), "{0}".format(txt))
# print("cx, cy", cx, cy, file=sys.stderr)
# canvas.drawCentredString(cx+(cellwidth/2), cy+(cellheight/2), "{0}".format(txt))
canvas.drawCentredString(cx+dx+cellmargin['left']+(imw/2), cy+cellmargin['bottom']+(imh/2), "{0}".format(txt))
c += 1
groupx += groupborder + (cellwidth*groupcols)
r += 2
# for i in range(1000):
#
# c.setFont('MyFontName', 72)
# # c.drawString(10*cm, 0.5*cm, "Page {0}".format(i))
# c.drawCentredString(A4[0]/2, A4[1]/2, "Page {0}".format(i))
canvas.showPage()
print("Saving to {0}".format(args.output), file=sys.stderr)
canvas.save()
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.