diff --git a/_posts/2026-08-15-book-review-animal-farm.md b/_posts/2026-08-15-book-review-animal-farm.md new file mode 100644 index 0000000..f25e8a8 --- /dev/null +++ b/_posts/2026-08-15-book-review-animal-farm.md @@ -0,0 +1,70 @@ +--- +layout: post +title: "Book review 'Animal Farm'" +date: "2026-08-15 12:08:25 +0530" +tags: + - books +--- + + +![Street mural of a pig in a business suit, painted below the words Animal +Farm]({{ site.url }}{{ site.baseurl }}/assets/images/animal_farm_bookreview/title.jpg) + +*I read Animal Farm in 2017 and started this post the same year, then never finished it. Nearly nine years later, I have +finally found the time.* + + +### Introduction + +Animal Farm is one of the best books I read in 2017. George Orwell published it in 1945, and it remains one of his best +known and most influential works. He is a brilliant satirist, and his writing is easy to find relatable. In 2008 The +Times ranked him second on its list of "The 50 greatest British writers since 1945". + +The sentences are short and plain, and that plainness is doing real work. The book never tells you what to feel about +the farm. It reports what happens, calmly, until the reporting itself becomes the argument. It runs to fewer than 100 +pages and I finished it in two sittings. + +### Plot summary + +A group of animals lives on a farm under the rule of its owner. One night Old Major, an old pig, calls everyone to a +meeting. He explains what freedom would mean and points out that the animals of that farm choose neither their work nor +their food. He urges them to rebel, and names humans as the enemy. Old Major dies a few nights later, and that lecture +becomes his last words. The animals unite against their master and succeed in driving him off his own farm. + +One group of pigs declares itself the educated class and asks to be allowed to make every decision for the farm. Under +the leadership of two pigs the animals are happy, because for the first time they are working for fellow animals rather +than for people. The owner returns with a group of men to take revenge, and it is a pleasure to read how the animals +fight them off. They win the battle, and afterwards they add an amendment declaring humans their greatest enemy. + +The story takes many tragic turns from there. The pigs in leadership spend their effort on making their own lives more +comfortable and pay no attention to anyone else. Because they read better than the rest, they can describe growth that +never happened to animals who are barely literate or not literate at all, and that imaginary growth is enough to keep +the others believing. Meanwhile, a small dispute between the two leaders grows. Fearing for his control, one of them +drives the other off the farm with a pack of dogs he has raised in secret. The democracy turns into a dictatorship. + +The dictator announces that he will improve the farm, and convinces every animal to pour its effort into building a +windmill — effort that used to go into growing the animals' own food. A few more battles with humans follow, and they +wreck the mill and break the animals' morale. It is shocking to read how the leader sells off the best of the farm's +animals to fund his own comforts, until the independent farm depends on humans again and then goes bankrupt. The animals +keep faith that whatever their captain decides is in their favour. The struggle drags on, and in the end the humans +simply buy him, with a large bribe, to supply whatever the farm produces. + +### Closing thoughts + +The book has left a deep impression on me. I am thankful to my +guru [Xitij Shukla](https://www.linkedin.com/in/xitijshukla/), who encouraged me to read this book. Orwell's writing +impressed me so much that I bought another of his books, [1984](https://www.goodreads.com/book/show/40961427-1984). + + +### Links + +* [Goodreads](https://www.goodreads.com/book/show/170448.Animal_Farm) + +* [Amazon worldwide](https://www.amazon.com/Animal-Farm-George-Orwell/dp/0451526341) + +* [Amazon India](https://www.amazon.in/Animal-Farm-George-Orwell/dp/8193387643) + + +###### Proofreaders: +* [jesusinadidas](https://github.com/jesusinadidas) +* [AI - Anthropic's Opus 5](https://www.anthropic.com/news/claude-opus-5) \ No newline at end of file diff --git a/assets/images/animal_farm_bookreview/title.jpg b/assets/images/animal_farm_bookreview/title.jpg new file mode 100644 index 0000000..0b10e98 Binary files /dev/null and b/assets/images/animal_farm_bookreview/title.jpg differ diff --git a/scripts/optimize-images b/scripts/optimize-images index 76b557f..dfbcc7d 100755 --- a/scripts/optimize-images +++ b/scripts/optimize-images @@ -14,10 +14,17 @@ set -euo pipefail cd "$(dirname "$0")/.." # Budgets, in bytes. A photo is displayed at roughly 800px, so 1600px covers -# high-density screens with room to spare; 300 KB is comfortably above the -# largest photo once it has been through the pipeline below. +# high-density screens with room to spare. readonly MAX_PHOTO_BYTES=307200 # 300 KB — jpg, png -readonly MAX_PHOTO_EDGE=1600 + +# 1600px is where photos start, not where they have to end up. A busy photo can +# still miss the budget there: the Animal Farm mural lands at 403 KB, and no +# amount of re-running helps because the result is stable. So the encoder walks +# this ladder and keeps the widest size that fits. Narrowing beats lowering +# quality — at the sizes that do fit, 1200px/q80 holds edges that 1600px/q65 +# smears, for about the same bytes. +readonly PHOTO_EDGES="1600 1400 1200 1000" +readonly PHOTO_QUALITY=80 # Animated screencasts cost far more because they carry hundreds of frames. # Resizing is the only lever that helps them: palette reduction and lossy LZW @@ -79,14 +86,53 @@ require() { } } +# Write "$1" into "$2" at the widest ladder size that fits "$3" bytes, falling +# through to the narrowest if none do. Every attempt re-reads the untouched +# original, so a narrow attempt never stacks its loss on top of a wider one. +# +# sips resizes well but writes bulky JPEGs — on a 2048px photo its encoder +# produced 452 KB where cjpeg produces 262 KB from the same pixels. So sips only +# resizes, and cjpeg does the encoding. +encode_jpeg() { + local src=$1 dest=$2 budget=$3 edge base png + # sips picks its output format from the extension, so the scratch file needs + # one. mktemp owns the name without it; both get cleaned up below. + base=$(mktemp -t optimize-images) + png="$base.png" + + for edge in $PHOTO_EDGES; do + sips -Z "$edge" -s format png "$src" --out "$png" >/dev/null + cjpeg -quality "$PHOTO_QUALITY" -optimize -progressive "$png" > "$dest" + if [ "$(file_size "$dest")" -le "$budget" ]; then + break + fi + done + + rm -f "$base" "$png" +} + +# Same ladder for PNGs, which sips resizes in place without a separate encoder. +encode_png() { + local src=$1 dest=$2 budget=$3 edge + + for edge in $PHOTO_EDGES; do + cp "$src" "$dest" + sips -Z "$edge" "$dest" >/dev/null + if [ "$(file_size "$dest")" -le "$budget" ]; then + break + fi + done +} + optimize() { require sips "It ships with macOS." require cjpeg "Install with: brew install jpeg-turbo" require gifsicle "Install with: brew install gifsicle" - local file size budget tmp before after + local file size budget tmp before after stubborn before=0 after=0 + stubborn="" while IFS= read -r file; do size=$(file_size "$file") @@ -108,28 +154,44 @@ optimize() { mv "$tmp" "$file" ;; png|PNG) - sips -Z "$MAX_PHOTO_EDGE" "$file" >/dev/null + tmp=$(mktemp -t optimize-images) + encode_png "$file" "$tmp" "$budget" + mv "$tmp" "$file" ;; *) - # sips resizes well but writes bulky JPEGs — on a 2048px photo its - # encoder produced 452 KB where cjpeg produces 262 KB from the same - # pixels. So sips only resizes, and cjpeg does the encoding. tmp=$(mktemp -t optimize-images) - sips -Z "$MAX_PHOTO_EDGE" -s format png "$file" --out "$tmp.png" >/dev/null - cjpeg -quality 80 -optimize -progressive "$tmp.png" > "$tmp" + encode_jpeg "$file" "$tmp" "$budget" mv "$tmp" "$file" - rm -f "$tmp.png" ;; esac size=$(file_size "$file") after=$((after + size)) printf ' %-58s -> %8s\n' "$file" "$(human "$size")" + + if [ "$size" -gt "$budget" ]; then + stubborn="$stubborn $file — $(human "$size") (budget $(human "$budget")) +" + fi done < <(find "$IMAGE_DIR" -type f \ \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' \) \ | sort) printf '\n%s -> %s\n' "$(human "$before")" "$(human "$after")" + + # The ladder bottoms out, and some images will still not fit. Say so and fail. + # Exiting 0 here would be worse than useless: --check rejects the file anyway, + # and its advice is to run this script, which has already done all it can. + if [ -n "$stubborn" ]; then + cat >&2 <