Bari Wolf Meta Data
Author: | Mitch Richling |
Updated: | 2023-10-11 |
Copyright 2023 Mitch Richling. All rights reserved.
Table of Contents
- 1. FAQ
- 1.1. Misc
- 1.2. Organizational Questions
- 1.2.1. Q: Do you use a DB to track your collection?
- 1.2.2. Q: May I download your data and/or code?
- 1.2.3. Q: What are those weird titles? The ones that look like "
bwID....
"? - 1.2.4. Q: What do the inventory ID tags mean?
- 1.2.5. Q: How do you keep track of the last number used for each prefix?
- 1.2.6. Q: How do you keep track of the physical locations of items?
- 1.2.7. Q: What about when you move things around in your album?
- 1.2.8. Q: What about when you want to change the name of a stamp image?
- 1.2.9. Q: Those scripts are great, but what about when things go wrong?
- 1.2.10. Q: How do you keep track of stamp image files?
- 1.3. Creating images & stuff
- 1.3.1. Q: How do you make the "design" cropped images?
- 1.3.2. Q: How do you make plate flaw images?
- 1.3.3. Q: How do you make those 300 & 90 DPI thumbnails?
- 1.3.4. Q: How do you create those sideways image labels?
- 1.3.5. Q: How do you create the dummy stamp images?
- 1.3.6. Q: How do you create the section images?
- 1.3.7. Q: How do you create the separator bar image?
- 1.3.8. Q: How do you create stamp Sheet Labels?
- 1.3.9. Q: How do you stamp album page and row labels?
- 1.3.10. Q: How to you overlay position numbers on stamp images?
- 1.3.11. Q: How do you make an image of a sheet from individual stamps?
- 1.3.12. How were the background types images created
- 1.3.13. Your raw scans are
.tif
files, but they show up as.png
in the data directory. How?
- 2. To Do
- 3. Change Log
- 3.1. 2023-10-11
- 3.2. 2023-10-04
- 3.3. 2023-09-17
- 3.4. 2023-07-24
- 3.5. 2023-03-26
- 3.6. 2023-02-19
- 3.7. 2023-02-18
- 3.8. 2022-12-05
- 3.9. 2022-12-01
- 3.10. 2022-11-30
- 3.11. 2022-11-29
- 3.12. 2022-11-26
- 3.13. 2022-11-24
- 3.14. 2022-11-23
- 3.15. 2022-11-21
- 3.16. 2022-11-20
- 3.17. 2022-11-17
- 3.18. 2022-11-16
- 3.19. 2022-11-15
- 3.20. 2022-11-11
- 3.21. 2022-11-09
- 3.22. 2022-11-08
- 3.23. 2022-11-07
- 3.24. 2022-11-06
- 3.25. 2022-11-05
1. FAQ
1.1. Misc
1.1.1. Q: What is PhilaJ?
Read all about it https://richmit.github.io/imagej/PhilaJ.html.
1.1.2. Q: What is with the crazy DPI of 2398?
When set to 2400 DPI, my scanner produces images that are 2410 DPI horizontally by 2398 DPI vertically at the center of the platen. The vertical DPI is consistent across the entire platen, but the horizontal DPI is variable. So I scan everything on the middle third of my scanner platen. Then I pull the images into ImageJ/Fiji and use PhilaJ to resize the images so the pixels are square – which produces a uniform 2398 DPI image. This process also creates the 300 DPI thumbnails.
1.1.3. Q: Isn't 2400 DPI excessive?
The "cost" of scanning at 2400 DPI isn't high – it takes a tiny bit longer to scan and disk space is cheap. The benefit to linear measurement accuracy is well worth the cost in my estimation. If I didn't have access to lots of storage space I might feel differently. It also makes fly-specking easier.
1.1.4. Q: Are your perforation measurements really accurate to 3 decimal places?
No.
They are good to about 1 decimal place, and most of the error is human derived.
1.1.5. Q: Can I use your color measurements with my scanner to identify shades?
No.
With regard to color my scanner is very precise but also not very accurate. On the accuracy front, my scanner is not color calibrated making measurements difficult to translate to other scanners. On the precision front, I take periodic measurements of a "standard" target to insure that the measurement variance is minimal – in fact the drift has been so small as to be difficult to measure. So my color measurements are very useful for me in that they allow me to compare shades, but probably not very useful to you. Sorry about that.
1.2. Organizational Questions
1.2.1. Q: Do you use a DB to track your collection?
Not for my Bari Wolf collection – everything is in org-mode
files. Stamp data are located in album.org
& stock.org
while a few auxiliary data tables
may be found in data.org
. In addition, some elisp
code may be found in code.org
, and some macros may be found in macros.org
. For details about how
to download this stuff, see the question Q: May I download your data and/or code?
1.2.2. Q: May I download your data and/or code?
Yes. The org-mode
files, generated HTML
, and images are linked downloads page. If you just want to import into Excel one of the
auxiliary data tables in data.org
, then you can copy a table from the HTML version of data.org
and paste it directly into Excel.
If you publish anything using this material, then please also publish with it a link to this site:
https://www.mitchr.me/SS/philBariWolf/index.html
1.2.3. Q: What are those weird titles? The ones that look like "bwID....
"?
Those are inventory IDs. I assign one to each item in my collection. They all look like this:
bwID<TAG><ITEM_NUMBER>p<PLATE_POSITION> | | || | | |+- This is the position number on the plate. It is 3 digits, zero padded if required. Only exists if "p" is given. | | +-- The "p" is optional. It is used to indicate that a plate position is known, and follows. | +--------------- This is a three digit item number -- zero padded if required. +-------------------- This is a descriptive tag that identifies the type of object.
1.2.4. Q: What do the inventory ID tags mean?
For info about IDs in general, see the question Q: What are those weird titles? The ones that look like "bwID…."?.
Prefix | Description |
---|---|
esy | Essay |
p2s | Printed on both sides |
samp | Overprint: Specimens |
pdue | Overprint: Postage Due |
repb | overprint: REPUBBLICA |
ovrc | overprint: Red Cross |
misbg | Missing background |
misfg | Missing foreground |
bh | Background Horizontal |
dbl | Double impression |
idbl | Double impression with one inverted |
drkw | Color: dark wolf |
drkb | Color: dark burelage |
shade | Color: shade |
sgl | Typical examples |
imph | imperforate horizontally |
impv | Imperforate_Vertically |
imp | Imperforate |
imps | Imperforate One Side |
ps | Perforate One Side |
ruf | Rough Perforations |
pfrk | Perforation Freaks |
qbu | Block of 4 with all burelage – Not Watermarked |
qbw | Block of 4 with all burelage – Watermarked |
pf | Plate Flaw |
sheetw | Watermarked Full Sheet |
sheetu | Unwatermarked Full Sheet |
1.2.5. Q: How do you keep track of the last number used for each prefix?
The code.org
file has a little bit of code that will find the largest IDs for each prefix.
1.2.6. Q: How do you keep track of the physical locations of items?
I keep track of where things are physically located by assigning each inventory ID a location code that looks like this:
Ap##r#c# | | | | | | | +- Column number ..... One digit | | +--- Row number ........ One digit | +------ Page number ....... Two digits +-------- The album/book .... "C" for my main collection & "S" for my stock book.
The data.org
file has a table mapping inventory ID to physical location.
1.2.7. Q: What about when you move things around in your album?
I have a script for that:
#!/usr/bin/env ruby require 'fileutils' require 'set' require 'optparse' require 'optparse/time' #--------------------------------------------------------------------------------------------------------------------------------------------------------------- # Print stuff to STDOUT immediatly -- important on windows $stdout.sync = true #--------------------------------------------------------------------------------------------------------------------------------------------------------------- debug = false; takeAction = true; printRules = false; opts = OptionParser.new do |opts| opts.banner = "Usage: rearrangeAlbum.rb [options] <rules>" opts.separator "" opts.separator "Options:" opts.on("-h", "--help", "Show this message") { puts opts; exit } opts.on("-d", "--debug", "Debug") { |v| debug = true; } opts.on("-p", "--print", "Print Rules") { |v| printRules = true; } opts.on("-n", "--dry-run", "Don't do anything") { |v| takeAction = false; } opts.separator " " opts.separator " Move Rules " opts.separator " - Ap#r#c#=Ap#r#c# ... Replace first position with second " opts.separator " - Ap#r#c#/Ap#r#c# ... Swap positions " opts.separator " - Ap#r#=Ap#r# ....... Replace first row with second " opts.separator " - Ap#r#/Ap#r# ....... Swap rows positions " opts.separator " - Ap#r#c#+ .......... Increment column numbers (insert a column after p#r#c#)" opts.separator " - Ap#r#+ ............ Increment row numbers (insert a row after p#r#) " opts.separator " - Ap#+ .............. Increment page numbers (insert a page after p#) " opts.separator "" end opts.parse!(ARGV) ruleStrings = ARGV.clone # Files with content to process -- we only edit one file... ;) orgFiles = Dir.glob('data.org'); if (debug) then puts("DEBUG: ORG FILES: #{orgFiles.inspect}"); end # Known locations locRe = Regexp.new('(([CS])p(\d{1,3})r(\d{1,2})c(\d{1,2}))'); knownLocs = Set.new; orgFiles.each do |fileName| open(fileName, "rb") do |iFile| fileData = iFile.read() fileData.scan(locRe) do |mDat| knownLocs.add(mDat[0]); end end end if (debug) then puts("DEBUG: KNOWN LOCATIONS: #{knownLocs.inspect}"); end moveSwapRule = Regexp.new('^([CS])p(\d{1,3})r(\d{1,2})(c(\d{1,2})){0,1}(=|/)([CS])p(\d{1,3})r(\d{1,2})(c(\d{1,2})){0,1}$'); incrementRule = Regexp.new('^([CS])p(\d{1,3})(r(\d{1,2})|r(\d{1,2})c(\d{1,2})){0,1}([+-])$'); moveRules = Hash.new; ruleStrings.each do |ruleString| if (mDat=ruleString.match(moveSwapRule)) then lhsA = mDat[1]; lhsP = mDat[2]; lhsR = mDat[3]; lhsC = mDat[5]; opr = mDat[6]; rhsA = mDat[7]; rhsP = mDat[8]; rhsR = mDat[9]; rhsC = mDat[11]; if ((lhsC.nil? || rhsC.nil?) && ( !(lhsC.nil? && rhsC.nil?))) then puts("ERROR: Malformed rule: '#{ruleString}'"); exit(1); end knownLocs.each do |loc| locMatchDat = loc.match(locRe); locA = locMatchDat[2]; locP = locMatchDat[3]; locR = locMatchDat[4]; locC = locMatchDat[5]; if ((lhsA == locA) && (lhsP == locP) && (lhsR == locR) && (lhsC.nil? || (lhsC == locC))) then if (moveRules.member?(loc)) then puts("ERROR: Move klobbers '#{loc}': '#{ruleString}'"); exit(1); end moveRules[loc] = "#{rhsA}p#{rhsP}r#{rhsR}c#{rhsC || locC}"; end if (opr == "/") then if ((rhsA == locA) && (rhsP == locP) && (rhsR == locR) && (rhsC.nil? || (rhsC == locC))) then if (moveRules.member?(loc)) then puts("ERROR: Move klobbers '#{loc}': '#{ruleString}'"); exit(1); end moveRules[loc] = "#{lhsA}p#{lhsP}r#{lhsR}c#{lhsC || locC}"; end end end elsif (mDat=ruleString.match(incrementRule)) then # inc rule lhsA = mDat[1]; lhsP = mDat[2]; lhsR = mDat[4] || mDat[5]; lhsC = mDat[6]; opr = mDat[7]; lhsP = lhsP.to_i; lhsR = (lhsR.nil? ? lhsR : lhsR.to_i); lhsC = (lhsC.nil? ? lhsC : lhsC.to_i); delt = (opr == "+" ? +1 : -1); knownLocs.each do |loc| locMatchDat = loc.match(locRe); locA = locMatchDat[2]; locP = locMatchDat[3].to_i; locR = locMatchDat[4].to_i; locC = locMatchDat[5].to_i; newA = locA; newP = locP; newR = locR; newC = locC; if (!lhsC.nil?) then newC = ( ((locC >= lhsC) && (locR == lhsR) && (locP == lhsP) && (locA == lhsA)) ? newC+delt : newC); elsif (!lhsR.nil?) then newR = ( ((locR >= lhsR) && (locP == lhsP) && (locA == lhsA)) ? newR+delt : newR); else newP = ( ((locP >= lhsP) && (locA == lhsA)) ? newP+delt : newP); end if ((newP != locP) || (newR != locR) || (newC != locC)) then if ((newP == 0) || (newR == 0) || (newC == 0)) then puts("ERROR: Move to zero! '#{loc}': '#{ruleString}'"); exit(1); end if (moveRules.member?(loc)) then puts("ERROR: Move klobbers '#{loc}': '#{ruleString}'"); exit(1); end moveRules[loc] = "#{newA}p#{'%02d' % newP}r#{newR}c#{newC}"; end end else puts("ERROR: Move rule invalid: '#{ruleString}'"); exit(1); end end # All the move rules if (printRules || debug) then moveRules.each do |from, to| if (debug) then puts("DEBUG: MOVE RULE: '#{from}' -> '#{to}'"); else puts("INFO: MOVE RULE: '#{from}' -> '#{to}'"); end end end # Move regular expression -- matches all the "from" IDs moveRulesRe = Regexp.new('(' + moveRules.keys.join('|') + ')'); if (debug) then puts("DEBUG: MOVE RULES RE: '#{moveRulesRe.inspect}'"); end # Backup file name ext backupExt = ".bak-" + Time.now.strftime('%Y%m%d%H%M%S') puts("INFO: BACKUP EXT: '#{backupExt}'"); # Make sure none of the backup files already exists orgFiles.each do |file| backupFileName = file + backupExt; if (FileTest.exist?(backupFileName)) then puts("ERROR: Backup file already exists: '#{backupFileName}'"); exit(1); end end # Make backups (org) orgFiles.each do |file| backupFileName = file + backupExt; if (takeAction) then if (debug) then puts("DEBUG: Make backup: '#{file}'"); end FileUtils.copy(file, backupFileName); if ( !(FileTest.exist?(backupFileName))) then puts("ERROR: Backup file could not be created: '#{backupFileName}'"); exit(1); end else if (debug) then puts("DEBUG: (SKIP) Make backup: '#{file}'"); end end end # Remove origional files orgFiles.each do |file| if (takeAction) then FileUtils.rm(file); if (debug) then puts("DEBUG: Delete original: '#{file}'"); end if (FileTest.exist?(file)) then puts("ERROR: Failed to remove origional: '#{file}'"); exit(1); end else if (debug) then puts("DEBUG: (SKIP) Delete original: '#{file}'"); end end end # Process org files orgFiles.each do |file| backupFileName = file + backupExt; if (takeAction) then fileChanged = false; open(backupFileName, "rb") do |iFile| fileData = iFile.read(); newFileData = fileData.gsub(moveRulesRe, moveRules); fileChanged = (fileData != newFileData); open(file, "wb") do |oFile| oFile.write(newFileData) end end puts("INFO: edit: #{file.inspect} #{(fileChanged == false ? '(NO CHANGE)' : '(CHANGED)')}"); if (debug) then puts("DEBUG: Process Org File: '#{file}'"); end else puts("INFO: SKIP edit: #{file.inspect}"); if (debug) then puts("DEBUG: (SKIP) Process Org File: '#{file}'"); end end end
1.2.8. Q: What about when you want to change the name of a stamp image?
I have a script for that too:
#!/usr/bin/env ruby require 'set' require 'fileutils' require 'optparse' require 'optparse/time' #--------------------------------------------------------------------------------------------------------------------------------------------------------------- # Print stuff to STDOUT immediatly -- important on windows $stdout.sync = true puts(ARGV.inspect) #--------------------------------------------------------------------------------------------------------------------------------------------------------------- patternFrom = nil; patternTo = nil; patternFilter = nil; contentFilter = nil; debug = false; takeAction = true; noKlober = true; magicFromRe = false; opts = OptionParser.new do |opt| opt.banner = "Usage: renameFile.rb <options>" opt.separator "" opt.separator "Options:" opt.on("-h", "--help", "Show this message") { puts opt; exit; } opt.on("-f regex", "--from regex", "From regex") { |v| patternFrom = v; } opt.on("-t regex", "--to string", "To String") { |v| patternTo = v; } opt.on("-f regex", "--filter regex", "Filter regex") { |v| patternFilter = v; } opt.on("-e regex", "--edit regex", "Edit files matching regex") { |v| contentFilter = v; } opt.separator " Only operate on files matching filter " opt.on("-d", "--debug", "Debug") { |v| debug = true; } opt.on("-n", "--dry-run", "Don't do anything") { |v| takeAction = false; } opt.on("-k", "--klobber", "Clobber files if required") { |v| noKlober = false; } opt.on("-m", "--magic", "Magically re-ize --from") { |v| magicFromRe = false; } opt.separator " SAME THING: " opt.separator " - ./renameFile.rb --from 'p1s(.)r1c1' --to 'bwIDfoo001-\\1' " opt.separator " - ./renameFile.rb --magic --from 'p1s2r1c1' --to 'bwIDfoo001-\\2' " opt.separator " " opt.separator "Rename files: " opt.separator " If provided, --filter specifies eligible files that might be renamed. If not " opt.separator " provided, then all files in the current working directory are considered " opt.separator " eligible. If a eligible file matches the --from regex, the matching part is " opt.separator " replaced by the --to string. Any files that match the --content regex are " opt.separator " edited so that any string matching one of the renamed files is transformed into " opt.separator " the the new name. Note files matching --content regex are NEVER eligible for " opt.separator " being renamed. " opt.separator " " end opts.parse!(ARGV) if (patternTo.nil?) then puts("ERROR: Missing argument: --to!"); exit(1); end if (patternFrom.nil?) then puts("ERROR: Missing argument: --from!"); exit(1); end if (debug) then puts("DEBUG: Options: patternFrom #{patternFrom.inspect} "); puts("DEBUG: Options: patternTo #{patternTo.inspect} "); puts("DEBUG: Options: patternFilter #{patternFilter.inspect}"); puts("DEBUG: Options: contentFilter #{contentFilter.inspect}"); puts("DEBUG: Options: debug #{debug.inspect} "); puts("DEBUG: Options: takeAction #{takeAction.inspect} "); puts("DEBUG: Options: noKlober #{noKlober.inspect} "); puts("DEBUG: Options: magicFromRe #{magicFromRe.inspect} "); end oldStyleLocNumRe = /^p([0-9]+)s([X0-9])r([0-9])c([0-9])$/; if (magicFromRe && (tmp = patternFrom.match(oldStyleLocNumRe))) then patternFrom = "p(#{tmp[1]})s([X0-9])r(#{tmp[3]})c(#{tmp[4]})"; end patternFrom = Regexp.new(patternFrom); if (debug) then puts("DEBUG: patternFrom: #{patternFrom.inspect}"); puts("DEBUG: patternTo: #{patternTo.inspect}"); end # Find files that we need to move filesToMove = Hash.new(); targetFiles = Hash.new(); Dir.foreach('.') do |fileName| if ( !(fileName.match(/(^\.|\.\.|.bak-[0-9]+)$/))) then if (patternFilter.nil? || fileName.match(patternFilter)) then if (fileName.match(patternFrom)) then if ( contentFilter.nil? || ( !(fileName.match(contentFilter)))) then newFileName = fileName.gsub(patternFrom, patternTo); filesToMove[fileName] = newFileName; if (FileTest.exist?(newFileName)) then if (noKlober) then puts("ERROR: File would get clobbered: '#{newFileName}' by '#{fileName}'!"); exit(1); else puts("WARNING: File will get clobbered: '#{newFileName}' by '#{fileName}'!"); end end if (targetFiles.member?(newFileName)) then puts("ERROR: File would get clobbered: '#{newFileName}' mapped to both '#{fileName}' and '#{targetFiles[newFileName]}'!"); exit(1); end targetFiles[newFileName] = fileName; else if ( !(patternFrom.nil?)) then puts("WARNING: File not being renamed because it matched --content regex: '#{fileName}'!"); end end end end end end if (filesToMove.empty?) then puts("ERROR: No files found mattching pattern"); exit(1); end if (debug) then puts("DEBUG: filesToMove: #{filesToMove.inspect}"); end # Create regex we use for editing org files later targetRegex = Regexp.union(*filesToMove.keys) if (debug) then puts("DEBUG: targetRegex: #{targetRegex.inspect}"); end # Find files we *might* need to edit filesToEdit = Set.new(); if ( !(contentFilter.nil?)) then Dir.foreach('.') do |fileName| if (fileName.match(contentFilter)) then filesToEdit.add(fileName); end end end if (debug) then puts("DEBUG: filesToEdit: #{filesToEdit.inspect}"); end # Need a nice backup extention backupTim = Time.now.strftime('%Y%m%d%H%M%S'); backupExt = ".bak-#{backupTim}" puts("INFO: Backup Time Stamp: #{backupTim}"); if (debug) then puts("DEBUG: backupExt: #{backupExt.inspect}"); end # Backup all the files we might modify or move allFiles = filesToMove.keys + filesToEdit.to_a; if (debug) then puts("DEBUG: allFiles: #{allFiles.inspect}"); end allFiles.each do |fileName| backupFileName = fileName + backupExt; if (FileTest.exist?(backupFileName)) then puts("ERROR: Backup file already exists: '#{backupFileName}'!"); exit(1); end if (takeAction) then FileUtils.cp(fileName, backupFileName); if (debug) puts("DEBUG: backup file: #{fileName.inspect} => #{backupFileName.inspect}"); end if ( !(FileTest.exist?(backupFileName))) then puts("ERROR: Backup file could not be created: '#{backupFileName}'!"); exit(1); end else if (debug) puts("DEBUG: SKIP backup file: #{fileName.inspect} => #{backupFileName.inspect}"); end end end filesToMove.each do |fileName, newFileName| backupFileName = fileName + backupExt; if (takeAction) then puts("INFO: move: #{fileName.inspect} => #{newFileName.inspect}"); FileUtils.rm(fileName); if (debug) puts("DEBUG: remove origional file: #{fileName.inspect}"); end if (FileTest.exist?(fileName)) then puts("ERROR: failed to remove origional file: '#{fileName}'!"); exit(1); end FileUtils.cp(backupFileName, newFileName); if (debug) puts("DEBUG: cp backup to new file name: #{backupFileName.inspect} => #{newFileName.inspect}"); end if ( !(FileTest.exist?(newFileName))) then puts("ERROR: Failed to copy back to new file name: '#{fileName}' => '#{newFileName}'!"); exit(1); end else puts("INFO: SKIP move: #{fileName.inspect} => #{newFileName.inspect}"); if (debug) puts("DEBUG: SKIP cp backup file to new name: #{backupFileName.inspect} => #{newFileName.inspect}"); end end end filesToEdit.each do |fileName| if (takeAction) then changed = nil; leftovr = nil; backupFileName = fileName + backupExt; open(backupFileName, "rb") do |inFile| fileData = inFile.read; changed = fileData.gsub!(targetRegex, filesToMove) leftovr = fileData.match(patternFrom) open(fileName, "wb") do |outFile| outFile.write(fileData); end end changed = (changed.nil? ? '(NO CHANGE)' : '(CHANGED)'); leftovr = (leftovr.nil? ? '' : " -- WARNING: Still matches #{patternFrom.inspect}"); puts("INFO: edit: #{fileName.inspect} #{changed} #{leftovr}"); if (debug) puts("DEBUG: edit file: #{fileName.inspect}"); end else puts("INFO: SKIP edit: #{fileName.inspect}"); if (debug) puts("DEBUG: SKIP edit file: #{fileName.inspect}"); end end end
1.2.9. Q: Those scripts are great, but what about when things go wrong?
The scripts make backups before they do anything. I have to admit I have needed to restore enough that I have a script to make it easy to restore from those backup files. Here it is:
#!/bin/sh BKPFX="$1" for f in *.bak-$1; do if [ -e "$f" ]; then nf=$(echo $f | sed "s/\.bak-$1$//") echo cp $f $nf cp $f $nf fi done
1.2.10. Q: How do you keep track of stamp image files?
I use a naming convention to keep track of stamp images:
Name | Description |
---|---|
INVID-1-scan_2398dpi.png |
Side one raw scan data |
INVID-2-scan_2398dpi.png |
Side two raw scan data |
INVID-1_2398dpi.png |
Side one |
INVID-2_2398dpi.png |
Side two |
INVID-1-pflaws_2398dpi.png |
Side one plate flaws |
INVID-2-pflaws_2398dpi.png |
Side two plate flaws |
INVID-X-front-back_2398dpi.png |
Side one and side two superimposed |
INVID-1-overprint_2398dpi.png |
Side one overprint |
INVID-1-faults_2398dpi.png |
Side one Faults |
INVID-1-cancel_2398dpi.png |
Side one cancel |
INVID-1-design_2398dpi.png |
Side one cropped to design + 1mm border |
INVID-1-expertmark_2398dpi.png |
Side one expert marks (like signatures) |
INVID-2-expertmark_2398dpi.png |
Side two expert marks (like signatures) |
INVID-1-stack.tif |
Stack of side one design files |
INVID-1.tif |
Side one raw scan |
INVID-1.tif |
Side two raw scan |
The "INVID
" is an inventory number or an inventory number followed by a position (like "p144
"). The master images are 2398dpi, but secondary images are
generated at "300dpi
" and "90dpi
".
I also have a script that identifies image files not used by any org-mode
file:
#!/usr/bin/env ruby require 'set' require 'fileutils' # Find every png file in the current working directory that is not on # the ignore list, and list the files not found in any org file in the # current working directory. debug = false; ignore = Regexp.union(/^STAMP-MIA-[12]_.*\.png$/, # MIA images for missing stamps /^background_T[1234]_t\.png$/, # Source images /^background_types\.png$/, # Source image /^bwIDsheet[uw]001p[0-9]{3}-1-design_(300|2398)dpi\.png$/, # Larger "design" images /^bwIDsheet[uw]001p[0-9]{3}-1_(90|300)dpi\.png$/, # Smaller "stamp" images /^PFTHM-HWW[0-1][0-9]_300dpi\.png$/, # Larger HM plate flaw images /^bwID.*-[12]-pflaws_90dpi.png$/, # 90 DPI previews of plate flaws /^bwID.*-2_90dpi.png$/, # 90 DPI previews of side 2 /^bwID.*-1-overprint_90dpi.png$/, # 90 DPI previews of overprints /^bwID.*-1-cancel_90dpi.png$/, # 90 DPI previews of cancels /^bwID.*-[12]-expertmark_90dpi.png$/, # 90 DPI previews of expert marks /^bwID.*-[12]-faults_90dpi.png$/, # 90 DPI previews of faults /^bwID.*-X-front-back_90dpi.png$/ # 90 DPI previews of front/back composites ); # Find all the PNG files allPNGfiles = Set.new(); Dir.foreach('.') do |fileName| if (fileName.match(/\.png$/)) then allPNGfiles.add(fileName); end end if (allPNGfiles.empty?) then puts("ERROR: No PNG files found"); exit(1); end if (debug) then puts("DEBUG: allPNGfiles: #{allPNGfiles.inspect}"); end # Filter out the ignored ones # We do this as a separate step so we can see the delta filteredPNGfiles = Set.new(); allPNGfiles.each do |fileName| if ( !(fileName.match(ignore))) then filteredPNGfiles.add(fileName) end end if (debug) then puts("DEBUG: filteredPNGfiles: #{allPNGfiles.inspect}"); end # Find files we need to search filesToSearch = Set.new(); Dir.foreach('.') do |fileName| if (fileName.match(/\.*.org$/)) then filesToSearch.add(fileName); end end if (debug) then puts("DEBUG: filesToSearch: #{filesToSearch.inspect}"); end # Figure out which png files were used usedPNGfiles = Set.new(); filesToSearch.each do |fileName| open(fileName, "rb") do |inFile| fileData = inFile.read; filteredPNGfiles.each do |fn| if (fileData.match(fn)) then usedPNGfiles.add(fn); end end end end # Compute the set difference, and display unused files. filteredPNGfiles.subtract(usedPNGfiles).each do |fileName| puts(fileName) end
1.3. Creating images & stuff
1.3.1. Q: How do you make the "design" cropped images?
I use PhilaJ. See the following question: Q: What is PhilaJ?.
1.3.2. Q: How do you make plate flaw images?
I use PhilaJ. See the following question: Q: What is PhilaJ?.
1.3.3. Q: How do you make those 300 & 90 DPI thumbnails?
I use PhilaJ. See the following question: Q: What is PhilaJ?.
They can also be created on the command line from the 300 DPI images like this:
for f in bwID*_300dpi.png; do nfn=${f/300/90} if [ ! -e $nfn -o $f -nt $nfn ]; then convert $f -resize 30% ${f/300/90} fi done
1.3.4. Q: How do you create those sideways image labels?
for a in 'EXPERT MARK' 'FAULT' 'BACK' 'CANCEL' 'COMPOSITE' \ 'FRONT' 'OVERPRINT' 'HANDSTAMP' 'PLATE FLAWS FRONT' 'OBLIQUE' \ 'PLATE FLAWS BACK' 'SHEET VISUAL INDEX' 'CERT'; do fn='ANNO-'`echo "$a" | tr ' ' '_'`'.png' if [ ! -e $fn ]; then echo MAKE $fn convert -size 350x50 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "$a" -rotate 270 $fn fi done
1.3.5. Q: How do you create the dummy stamp images?
fn='STAMP-MIA-1_300dpi.png' convert -size 340x380 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "MIA" $fn fn='STAMP-MIA-1_90dpi.png' convert -size 103x115 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "MIA" $fn fn='STAMP-MIA-1_2398dpi.png' convert -size 2730x3060 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "MIA" $fn fn='STAMP-MIA-2_300dpi.png' convert -size 340x380 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "MIA" $fn fn='STAMP-MIA-2_90dpi.png' convert -size 103x115 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "MIA" $fn fn='STAMP-MIA-2_2398dpi.png' convert -size 2730x3060 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "MIA" $fn
1.3.6. Q: How do you create the section images?
for a in 'Printed Both Sides' 'All Four Burelage Types' \ 'Interesting Plate Flaws' 'Large Multiples' 'Overprints & Handstamps' \ 'Color Varieties - Shades' 'Color Varieties - Dark Wolf' 'Color Varieties - Dark Burelage' \ 'Missing Foreground' 'Missing Background' 'Double Impressions' 'Inverted Double Impressions' \ 'Colors & Shades' 'Typical Examples' 'Perforation Oddities' \ 'Perforation Oddities - Imperforate Horizontally' 'Perforation Oddities - Imperforate Vertically' \ 'Perforation Oddities - Imperforate One Side' 'Perforation Oddities - Imperforate' \ 'Perforation Oddities - Rough Perforations' 'Essay' 'Perforation Oddities - Freaks' \ 'Perforation Oddities - Perforate One Side' 'Background Horizontal'; do fn='HEAD-'`echo "$a" | tr ' ' '_'`'.png' if [ -e $fn ]; then echo SKIP $fn else echo MAKE $fn convert -size 1224x50 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "$a" $fn fi done
1.3.7. Q: How do you create the separator bar image?
if [ -e HEAD-BREAK.png ]; then echo SKIP HEAD-BREAK.png else echo MAKE HEAD-BREAK.png convert -size 1024x50 xc:black HEAD-BREAK.png fi
1.3.8. Q: How do you create stamp Sheet Labels?
for a in $(seq 10 10 150); do pos=$(printf '%03d' $a) fn="SHEET150V-$pos.png" convert -size 90x104 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "$pos" $fn done for a in $(seq 12 12 168); do pos=$(printf '%03d' $a) fn="SHEET168V-$pos.png" convert -size 90x104 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "$pos" $fn done for a in $(seq 1 12); do pos=$(printf '%03d' $a) fn="SHEET168H-$pos.png" convert -size 90x104 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "$pos" $fn done for a in $(seq 1 10); do pos=$(printf '%03d' $a) fn="SHEET150H-$pos.png" convert -size 90x104 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "$pos" $fn done convert -size 90x104 xc:black SHEET150X-XXX.png convert -size 90x104 xc:black SHEET168X-XXX.png
1.3.9. Q: How do you stamp album page and row labels?
for a in $(seq 1 9); do row=$(printf '%d' $a) fn="ROW-$row.png" if [ -e $fn ]; then echo SKIP $fn else echo MAKE $fn convert -size 90x104 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "ROW\n$row" $fn fi done for a in $(seq 1 30); do page=$(printf '%02d' $a) fn="PAGE-$page.png" if [ -e $fn ]; then echo SKIP $fn else echo MAKE $fn convert -size 1224x50 xc:black -pointsize 30 -gravity center -fill red -annotate 0 "PAGE: $a" $fn fi done
1.3.10. Q: How to you overlay position numbers on stamp images?
# For sheet001 for f in bwIDsheetw001p*-1-design_90dpi.png; do p=$(echo $f | sed 's/^.*001p//; s/-.*$//') nf=PNO-$f if [ -e $nf ]; then echo SKIP $nf else echo MAKE $nf convert $f -pointsize 50 -gravity center -fill red -annotate 0 $p $nf fi done #for sheet002 for f in bwIDsheetu001p*-1-design_90dpi.png; do p=$(echo $f | sed 's/^.*002p//; s/-.*$//') nf=PNO-$f if [ -e $nf ]; then echo SKIP $nf else echo MAKE $nf convert $f -pointsize 50 -gravity center -fill red -annotate 0 $p $nf fi done
1.3.11. Q: How do you make an image of a sheet from individual stamps?
Note the stamps must be cropped correctly for this to work – they all need to be about the same size.
magick montage -mode concatenate -tile 10x15 -resize 50% bwIDsheetw001p*-1-design_90dpi.png bwIDsheetw001-1_90dpi.png magick montage -mode concatenate -tile 12x14 -resize 50% bwIDsheetu001p*-1-design_90dpi.png bwIDsheetu001-1_90dpi.png
1.3.12. How were the background types images created
I took an image of a stamp with just a background, and annotated the important bits. Then I flipped it around to create the four orientations. This crated the high resolution versions. Then I created the thumbnails like this:
for f in background_T?.png; do f_preview=${f/.png/_p.png} if [ -e "$f_preview" ]; then echo SKIP PREVIEW $f else echo MAKE PREVIEW $f convert $f -resize 20% $f_preview fi; f_thumb=${f/.png/_t.png} if [ -e "$f_thumb" ]; then echo SKIP THUMB $f else echo MAKE THUMB $f convert $f -resize 5% $f_thumb fi; done
1.3.13. Your raw scans are .tif
files, but they show up as .png
in the data directory. How?
I convert them after I process the images. I don't do that with ImageJ/Fiji, but with ImageMagick from the command line.
time ls *.tif | grep -v stack.tif | xargs -P 8 -I{} sh -c 'echo {}; convert {} $(echo {} | sed "s/\.tif$/-scan.png/;")';
2. To Do
I don't plan on ever being "done" with this project, but here are a few of the higher priority things on my list:
- Items with missing data:
- bwIDmisbg004-2_2398dpi.png: Add expert mark image
- bwIDdbl005-2_2398dpi.png: Add expert mark image
- bwIDidbl001-2_2398dpi.png: Add expert mark image
- bwIDdrkw001-2_2398dpi.png: Add expert mark image
- bwIDimp003-2_2398dpi.png: Add expert mark image
- bwIDimp001-2_2398dpi.png: Add expert mark image
- bwIDsheetw001p089-1_2398dpi.png: Rescan
- bwIDimps001-2_2398dpi.png: Add sheet location
- bwIDsgl071-1_2398dpi.png: Add cancel image
- Plate flaws stuff
- Add little thumbnails to my plate flaw table
- Visual guide to plate flaws
- Sections with plate flaw number
- Has a list of basic plate flaw data along with thumbnail
- All thumbnails of stamps with the same flaw – which link to plate flaw image
- Sections with plate flaw number
- Data to add
- Paper thickness data
- Centering data
- Scarcity and pricing data
- Plate flaws
3. Change Log
3.1. 2023-10-11
- Added bwIDp2s019 (page 4, row 5, column 1)
- Added bwIDps001 (page 10, row 2, column 1)
- Moved items on page 4, row 3 up to row 2 (rearrangeAlbum.rb -p Cp04r3=Cp04r2)
- Additional notes on printing variations
- Better Bush cross reference for printing variations
- Made section images and page images wider to accomidate wider page
3.2. 2023-10-04
- Moved items on page 4 down one row (rearrangeAlbum.rb -p Cp04r2+)
- Moved items on page 3, row 5 to page 4 row 1 (rearrangeAlbum.rb -p Cp03r5=Cp04r1)
- Moved items on page 3, row 3 & 4 down one row (rearrangeAlbum.rb -p Cp03r3+)
- Added new category of stamps: ps – Perforate One Side
- Added new category of stamps: bh – Background Horizontal
- Fixed some typos in the album-org table
- Added new stamp: bwIDp2s018 to page 3, row 3
- Added new stamp: bwIDbh001 to page 2, row 2
- New printed both sides variety:
dWdB0WnB
- Updated "My Potential Plate Flaw List" to include sheet type instead of watermark
3.3. 2023-09-17
- Added bwIDpfrk001 to album
- Moved everything on page 11 to 12, and everything on page 10 to 11
- Created new catalog number category: bwIDpfrk for freak perfs
- Add new plate flaw: pf0038
- Put all the code in git
- Converted scan data from TIFF to PNG
3.4. 2023-07-24
- Added bwIDimpv004 to album
- Moved bwIDimpv003 to stock
- Added bwIDidbl003 to album
- Added bwIDp2s017 to album
- Fixed bug with sheet index links
3.5. 2023-03-26
- Fixed a ton of misspellings & a few factual errors. Thank you, Carl Scheriani!
3.6. 2023-02-19
- Added paper thickness measurements to bwIDesy001 & bwIDesy002
- Added paper thickness measurement notes to notes.html
3.7. 2023-02-18
- Added bwIDesy002
3.8. 2022-12-05
- Raw scan data converted to PNG
- Updated naming scheme for raw scan data: Q: How do you keep track of stamp image files?
3.9. 2022-12-01
- Added bwIDsgl078
- Updated measurements & graphs
- bwIDsamp008: Added plate flaw section
- bwIDmisbg006: Added plate flaw section
- bwIDsamp008:
- Corrected overprint selection & image
- Fixed plate flaw preview label
- Cleaned up ANNO- & HEAD- code
- Removed unused ANNO- & HEAD-images
- Removed unused stamp images
- Removed temporary images
- Added measurement data for perfs & paper size. measurements.html
- Fixed a bug with the download page
- Added a history section to the notes.html file
3.10. 2022-11-30
- Many burelage tables are now fully automated based on DATA tables. Woot!
- Sheet image with 150 & 168 overlapped showing types with sheets in color
- Sheet image with 150 & 168 overlapped showing blocks of 4 with all four burelage types
- Sheet image with 150 & 168 overlapped showing horizontal strips of 4 with all four burelage types
- Sheet image with 150 & 168 overlapped showing vertical strips of 4 with all four burelage types
- Table showing information for blocks of 4 with all four burelage types
- Table showing information for horizontal strips of 4 with all four burelage types
- Table showing information for vertical strips of 4 with all four burelage types
- Added examples showing how to find sheet location given a block of stamps with known burelage types
- Added side illuminated, rough perforation pic to notes.org
- Added full sized image links to perforation examples in notes.org
3.11. 2022-11-29
- Fixed a bug with rearrangeAlbum.rb
- virtstock.html & virtalbum.html have a much better layout
- Content generation is now fully automatic for the following:
- Moved back to 1024px layout except for sheetu001.html
- Moved code & data to external files.
3.12. 2022-11-26
- Some clean-up – album vs stock book
- Added section about rough perforations in notes.org
3.13. 2022-11-24
- Renamed sheet001 and sheet002 to sheetw001 and sheetu001
- Renamed bwIDqbw* to bwIDqbu*
3.14. 2022-11-23
- Added: bwIDpf006, bwIDpf007, bwIDpf008, bwIDsgl070, bwIDsgl071, bwIDsgl072, bwIDsgl073, bwIDsgl074, bwIDsgl075, bwIDsgl076, bwIDsgl076, bwIDsgl077, bwIDruf004, bwIDshade013, bwIDshade014, bwIDshade015
- Started work on Burelage code.
3.15. 2022-11-21
- Several updates to the FAQ
- New macro for color measurement results – allows me to have all the data in the org file, and only present the bits we want in HTML.
- New measurements for color that include "Jue" – "Hue" mapped to [-180, 180]. The "J" is pronounced like "H" – in an honor of the way it sounds in some Spanish words. With this change, I think I have a good way to document shades.
- Fixed virtalbum.org – it was sorting incorrectly.
3.16. 2022-11-20
- Answered several new questions in the FAQ.
- Cleaned up and published the
unlinkedImages.rb
script. - Added code to separate the "main collection" from "stock".
- The script
rearrangeAlbum.rb
now can move pages/rows/columns to the left. - Move to 1250 px wide layout.
- Using a macro for catalog perforations now – more accurate and less typing.
- Added downloads page.
3.17. 2022-11-17
- Tons of code changes in the background
- Added a 168 sheet! Woot!
- data is now in data.org
- Raw scan data is included now
- Added plate flaw lists from FM & HWW.
3.18. 2022-11-16
- Added: bwIDesy001, bwIDp2s013, bwIDp2s014, bwIDp2s015, bwIDmisfg004
- Added two pages to start of album.
- notes.org now uses DB elisp library in album.org.
- Added "REPUBBLICA" and "Red Cross" sections to notes.
3.19. 2022-11-15
- Added: bwIDqbn004, bwIDqbn005, bwIDqbn006, bwIDimps002, bwIDimps003, bwIDsamp007, bwIDsamp008, bwIDsamp009, bwIDsamp010, bwIDovrc001, & bwIDdbl006.
- Moved around samp stamps to make room on page.
3.20. 2022-11-11
- Added scan of back of bwIDimps001
- Added scan of back of bwIDpf005
- Added "paper cropped" scans for sheet001.
- Added "paper cropped" images for burelage quads from sheet001.
- sheet001 stamp links now go to "paper cropped" images.
- Did scans for remainder of collection
3.21. 2022-11-09
- Changed plate flaw docs to new format
- Added several new plate flaws to document
- Added burelage types and identified plate location for bwIDpf005
- Added plate flaw image for bwIDimps001
- Decided on naming convention for "design cropped images"
- Renamed all the "design cropped images"
3.22. 2022-11-08
- Added bwIDpf005
- Added bwIDimps001
- Added two new pages after page 7
- Moved bwIDruf001, bwIDruf002, bwIDruf003 to page 8
3.23. 2022-11-07
- Plate flaws
- Updated position lists for pf0004 pf0005
- Added pf0009 – need to document rest of these in my collection
- Scanned and measured (both in cache directory)
- Imperf at top
- Block of four with odd plate flaw
3.24. 2022-11-06
- Announced website on stampcommunity: https://www.stampcommunity.org/topic.asp?TOPIC_ID=82346
- Announced on the AMG club forum too: https://amgcc.clubexpress.com/
- Announced website on r/philately: reddit link
- Added overprint content to notes.
- Still need to do "repubblica" and "Red Cross" sections.
- DB updates
- New tables for print components
- Started auto-generating the print varieties table from DB
3.25. 2022-11-05
- Initial upload of content
- Collection Status:
- I have about 2/3 of my total collection is scanned so far
- Most of them have perf measurements
- Lots of plate flaws to document
- Paper measurements are missing
- Design measurements are missing
- DB Status:
- I have data tables organized for the collection and plate flaws
- I have much more data entry for plate flaws & stamp data
- I'm using the DB to generate the index, plate flaws, and sheet images
- The plan is to use it for individual stamp records eventually