Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions _posts/2026-08-15-book-review-animal-farm.md
Original file line number Diff line number Diff line change
@@ -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)
Binary file added assets/images/animal_farm_bookreview/title.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
84 changes: 73 additions & 11 deletions scripts/optimize-images
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand All @@ -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 <<EOF

Still over budget after every size available:

$stubborn
Crop these, or replace them with a lighter image.
EOF
return 1
fi
}

case "${1:-}" in
Expand Down
Loading