Create Calendar with ImageMagick

用 ImageMagick 製作行事曆

【摘要】本文敘述用 ImageMagick 和 BASH 指令製作陰曆行事曆的圖片,並將之固定在桌面當桌布。


【目錄】

    【前言
    【輸入檔
    【指令檔
    【貼在桌面
    【後語

【前言】

一、一般月曆的第一天都是陽曆一號,再附上對照的陰曆。本例製作的月曆是用陰曆初一做開頭,以陽曆為對照。此外,還可以顯示簡單的記事、待辦事項之類的內容。

二、除了 BASH 和 ImageMagick 之外,還用到的程式有 Zenity 和 Linux 內建的 date

三、以下所提到的檔案都要放在同一個目錄裡。

四、一年前曾發表過「用ImageMagick 製作陰曆行事曆」,近日再度檢視修改,分享於此。


【輸入檔】

一、製作行事曆的原始資料當然是文字檔。本例特別採用 Linux 原有的 calendar 程式所規範的格式。如此一來,兩邊都可以用。


二、calendar 程式規定的格式是:

陽曆月(空格)陽曆日(跳格)說明

前兩欄是月和日(這當然是指陽曆日期),而且這兩欄要用空格(space)分開。接下來是跳格(tab)。其餘的內容都是該日的說明。也就是以第一個跳格為分界,左邊為日期,右邊是說明。

說明中可以再有跳格,但只做跳格用,沒有特別意義。


三、本例的格式是:

陽月(空格)陽日(跳格)陰月(跳格)陰日(跳格)假日(跳格)本月(跳格)記事

其中:
假日欄 是用來標示是否為假日;若是,用 0;若要上班上課,用 1。這是為了用不同的背景色。
本月欄 是為了用不同的字色(前景色)。本例所製作的月曆,每一週都是從週日開始,週六結束。所以第一週的前段可能是前一個月份的,而最後一週的後段可能是下個月份的。本月欄就是標出是否為當月;若是,用 1;若非,用 0。


四、此輸入檔可以有 # 開頭的註解和空白行。至於檔案的名稱,為了方便,也有一定格式:

陰曆年名-陰曆月份.txt


五、範例:庚子-2.txt

記事欄手動換行用 \\n;目的是把字縮小,不然會使用能填滿整個記事欄的最大字;另外也可以調整位置。

#庚子年二月
2 23	2	1	0	1	
2 24	2	2	1	1	
2 25	2	3	1	1	
2 26	2	4	1	1	
2 27	2	5	1	1	
2 28	2	6	0	1	\\n和平日
2 29	2	7	0	1	
3 1	2	8	0	1	
3 2	2	9	1	1	
3 3	2	10	1	1	
3 4	2	11	1	1	
3 5	2	12	1	1	驚蟄
3 6	2	13	1	1	
3 7	2	14	0	1	
3 8	2	15	0	1	\\n婦女節
3 9	2	16	1	1	
3 10	2	17	1	1	
3 11	2	18	1	1	
3 12	2	19	1	1	
3 13	2	20	1	1	
3 14	2	21	0	1	
3 15	2	22	0	1	
3 16	2	23	1	1	
3 17	2	24	1	1	
3 18	2	25	1	1	
3 19	2	26	1	1	
3 20	2	27	1	1	\\n春分
3 21	2	28	0	1	
3 22	2	29	0	1	
3 23	2	30	1	1	
3 24	3	1	1	0	
3 25	3	2	1	0	
3 26	3	3	1	0	
3 27	3	4	1	0	
3 28	3	5	0	0	

【指令檔】

此處以彩色版本為例。

庚子-2c

#!/bin/bash
 
 # 製作陰曆行事曆
 # 先確認年名 YearName
 # 輸入檔名稱格式:年名-陰曆月份.txt,如:庚子-3.txt
 # 如果是閏月,自行更名
 
 # 輸入檔欄位:陽月、陽日、陰月、陰日、假日、本月、記事
 #   假日:若是假日,用0;若非,用1
 #   本月:前後月用0;當月用1
 # 前後月要補滿整週
 
 # 年名
YearName="庚子"
 
 # 詞語色;為了加粗,內外都用且同色
ColorWordFill="#0c0"
ColorWordStroke="#0c0"
 
 # 月名欄背景色
ColorMonthBg="#ee6"
 # 月名字色
ColorMonth="#c0c"
 # 月名字體(可用字體見 convert -list font)
FontMonth="AR-PL-UKai-TW"
 # 月名字體大小
PointMonth=28
 # 月名欄尺寸 (月名欄寬=週名欄寬x7+框寬x12)
SizeMonth="1062x40"
 # 月名欄框色
ColorMonthFrame="#880"
 # 月名欄框寬
BorderMonth=1
 
 # 週名欄背景色
ColorWeekBg="#f84"
 # 週名字色
ColorWeek="#fff"
 # 週名字體
FontWeek="AR-PL-UKai-TW"
 # 週名字體大小
PointWeek=20
 # 週名欄尺寸 (週名欄寬=陰曆日期欄寬+陽曆日期欄寬)(週名欄高=字體大小+8)
SizeWeek="150x28"
 # 週名欄框色
ColorWeekFrame="#880"
 # 週名欄框寬
BorderWeek=1
 
 # 陰曆日期字體
FontDayLunar="Noto-Sans-CJK-TC-Black"
 # 陽曆日期字體
FontDaySolar="Noto-Sans-CJK-TC-Bold"
 # 陰曆日期字體大小
PointDayLunar=24
 # 陽曆日期字體大小
PointDaySolar=16
 # 陰曆日期欄尺寸 (陰曆日期欄高=陽曆日期欄高)
SizeDayLunar="54x24"
 # 陽曆日期欄尺寸
SizeDaySolar="96x24"
 # 日期欄框色
ColorDayFrame="#880"
 # 日期欄框寬
BorderDay=1
 
 # 記事欄字體
FontNote="AR-PL-UMing-TW"
 # 記事欄字體大小用 +pointsize 取消,以便自動調整
 # 記事欄尺寸 (記事欄寬=週名欄寬)
SizeNote="150x64"
 
 # 月名欄只做當月的,但因為輸入檔可能有前後月的資料,所以必需知道月名欄是否做過
FlagMonth=0
 # 計算所做的日數,每滿七天,就合成一週
CounterDay=1
 # 計算一個月的週數
CounterWeek=1
 
 # 以上是基本的設定值,以下開始製作
 
 # 詢問欲製作的陰曆月份
MonthName=$(zenity --entry --title "輸入月份" --text "欲製作的陰曆月份(1..12)是:")
 
 # 若選[Cancel],即中斷程式
if [ -z ${MonthName} ]
then
  exit
fi
 
 # 輸入檔名稱;也檢查輸入的月份,若不合理,即中斷程式
if [ ${MonthName} -ge 1 -a ${MonthName} -le 12 ]
then
  FileName="${YearName}-${MonthName}.txt"
else
  exit
fi
 
 # 詞語
convert -background ${ColorMonthBg} -fill ${ColorWordFill} -font ${FontMonth} -strokewidth 1 -stroke ${ColorWordStroke} -size ${SizeMonth} -gravity Center caption:"一年之計在於春      一日之計在於晨" -bordercolor ${ColorMonthFrame} -border ${BorderMonth} words.png
 
 # 週名欄;用 +append 選項橫向合併;因為是固定的,所以先做
convert -background ${ColorWeekBg} -fill ${ColorWeek} -font ${FontWeek} -pointsize ${PointWeek} -size ${SizeWeek} -gravity Center label:日 label:一 label:二 label:三 label:四 label:五 label:六 -bordercolor ${ColorWeekFrame} -border ${BorderWeek} +append weekname.png
 
 # 開始讀入資料,製作月曆的日與週
while read SolarMonth SolarDay LunarMonth LunarDay OnOff Current Event
do
 
  # 略過#註解和空白行
  if [ "${SolarMonth:0:1}" = "#" -o "${SolarMonth}" = "" ]
  then
    continue
  fi
 
  # 記事字色;非當月的字調暗
  if [ ${Current} -eq 1 ]
  then
    ColorDay="#66f"
    ColorNote="#880"
  else
    ColorDay="#aaf"
    ColorNote="#aa0"
  fi
 
  # 月名欄
  # 尋找陰曆日期為 1,且尙未做過月名欄
  if [ ${LunarDay} -eq 1 -a ${FlagMonth} -eq 0 ]
  then
    convert -background ${ColorMonthBg} -fill ${ColorMonth} -font ${FontMonth} -pointsize ${PointMonth} -size ${SizeMonth} -gravity Center label:"${YearName}年 ${LunarMonth} 月" -bordercolor ${ColorMonthFrame} -border ${BorderMonth} monthname.png
    # 做過必需記錄,不然可能被改成下個月的
    FlagMonth=1
    # 輸出檔名要用,先存起來,不然也可能被改成下個月的
    Month=${LunarMonth}
  fi
 
  # 一日
  # 假日用不同底色
  if [ ${OnOff} -eq 0 ]
  then
    ColorNoteBg="#fca"
  else
    ColorNoteBg="#ffc"
  fi
 
  # 今日日期用不同色(如果記事欄也用,會蓋過假日色)
  # 比較讀入的陽曆月日和系統的月日;相同時,改顏色;不然,沿用記事欄的顏色
  if [ "${SolarMonth}/${SolarDay}" = "$(date +%-m/%-d)" ]
  then
    ColorDayBg="#f22"
  else
    ColorDayBg="#afa"
  fi
 
  # 一日
  # (左上陰曆日)(右上陽曆月/日)用 +append 橫併,再與下方記事欄用 -append 縱併
  convert -background ${ColorDayBg} -fill ${ColorDay} -font ${FontDayLunar} -pointsize ${PointDayLunar} -size ${SizeDayLunar} -gravity Center label:"${LunarDay}" -font ${FontDaySolar} -pointsize ${PointDaySolar} -size ${SizeDaySolar} -gravity East label:"${SolarMonth}/${SolarDay} " +append -background ${ColorNoteBg} -fill ${ColorNote} -font ${FontNote} +pointsize -size ${SizeNote} -gravity Center caption:"${Event}" -append day-${CounterDay}.png
 
  # 一週 (每七日用 +append 橫向合併)
  if [ ${CounterDay} -eq 7 ]
  then
    convert day-*.png -bordercolor ${ColorDayFrame} -border ${BorderDay} +append week-${CounterWeek}.png
    # 日計數歸零
    CounterDay=0
    # 週計數增1
    (( CounterWeek += 1 ))
  fi
 
  # 日計數增1
  (( CounterDay += 1 ))
 
done < ${FileName}
 
 # 一個月
convert words.png monthname.png weekname.png week-*.png -append -bordercolor ${ColorMonthFrame} -border 3 ${YearName}-${Month}.png
 
 # 刪暫存檔
rm words.png monthname.png weekname.png week-*.png day-*.png
 
exit

說明

【貼在桌面】

因本例的系統是用 FluxBox 做視窗管理員,所以可以很輕易地將做出來的月曆圖片設為桌面背景圖片(桌布 wallpaper)。

fbsetbg -c 圖檔路徑

  -c:將圖片置中


【後語】

一、可以將此 BASH 檔設為可執行,以方便製作月曆。

二、當要修改行事曆時,先修改輸入檔,然後重做新的月曆。這些步驟可以再寫成一個簡單的 BASH 檔,並設為可執行。如果用習慣了,不用 5 秒就可以做出新的月曆並設為桌布。

三、只要稍加修改,即可做出陽曆的月曆,但是輸入檔就要大幅修改成以陽曆為主了。


發表留言