↑ ↑ ↓ ↓ ← → ← → B A Start

Luma

Нашел на /r/proceduralgeneration пост в котором некто написал фильтр для изображений, который превращает исходное изображение в условно абстрактное. Код был написан на Lua, я же решил переписать предложенный метод на Go. Во-первых я никогда не писал что-то связанное с обработкой изображений на гошке, а во-вторых почему бы и нет.

package main

import (
	"image"
	"image/color"
	"image/jpeg"
	"os"
	"sort"
)

func main() {
	file, err := os.Open("in.jpg")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	image.RegisterFormat("jpeg", "jpeg", jpeg.Decode, jpeg.DecodeConfig)

	img, _, err := image.Decode(file)
	if err != nil {
		panic(err)
	}

	rec := img.Bounds()
	cimg := image.NewRGBA(rec)

	m := make([]color.Color, rec.Dy())
	for x := 0; x < rec.Dx(); x++ {
		for y := 0; y < rec.Dy(); y++ {
			m[y] = img.At(x, y)
		}

		sort.SliceStable(m, func(i, j int) bool {
			return luma(m[i]) < luma(m[j])
		})

		for y := range m {
			cimg.Set(x, y, m[y])
		}
	}

	out, err := os.Create("out.jpg")
	if err != nil {
		panic(err)
	}

	err = jpeg.Encode(out, cimg, &jpeg.Options{Quality: 80})
	if err != nil {
		panic(err)
	}
}

func luma(c color.Color) float32 {
	r, g, b, _ := c.RGBA()

	return 0.2126*float32(r>>8) +
		0.7152*float32(g>>8) +
		0.0722*float32(b>>8)
}

TL;DR Что тут происходит? Берем пиксельную сетку изображения, делим на столбцы и в каждом из столбцов сортируем пиксели по относительной яркости.

Для вычисления относительной яркости нужно взять каждый пиксель, разложить на RGB цвета и умножить их на коэффициенты. Почему именно такие коэффициенты лучше почитать в статье на хабре. Результат выходит приличный, для изображений содержащих большой однородный задний фон.

Luma

Второй интересный момент момент это то, как в Go реализованы возвращаемые значения цветов. Все цвета хранятся в uint32 в диапазоне от 0 до 0xFFFF, что позволяет хранить эффективные значения для 16-битного диапазона. Как обычно, самый исчерпывающий ответ о том как это работает можно найти на SO, где же еще. Но так как формула относительной яркости работает с 8-битными значениями, то конвертируем 16-битное представление обратно в 8 бит используя битовый сдвиг вправо.

Pad - pastebin без стероидов

В то время когда к интернету подключена каждая кофеварка, sharing небольших текстовых данных между MacOS и Linux или между iPhone и Windows все еще превращается в «танцы с бубнами». Можно конечно отправить письмо самому себе, как в средневековье. А если получатель кто-то другой, то на сцену выходит Pastebin со своими непомерными требованиями к заголовкам, типу контента, уровню видимости и капчей. Можно попроще?

Встречайте Pad — сервис где не нужно ничего заполнять, выбираешь ссылку и вставляешь текст в textarea и открываешь ссылку на другом устройстве. Сервис, как сейчас принято, написан на Go, а для стораджа используется BoltDb, это такая встраиваемая key/value база данных. Завернуто это, как полагается, в Docker, куда уж без него. Исходники можно посмотреть на Github.

Книги о Биткоине и не только

Книги о криптовалютах выходят пачками, каждую неделю и читать их все не хватит никаких сил. Из тех что я успел прочитать собрал подборку из пяти хороших и не очень.

«Эпоха криптовалют», Пол Винья

Рассуждения о природе денег, прогнозы о возможном влиянии криптовалют на экономику и пара заметок о сомнительных стартапах. Авторы «Эпохи криптовалют» – обозреватели Wall Street Journal сделали все, чтобы ни у кого не было желания дочитать книгу до конца. А отсутствие технических деталей и минимальное погружение в хронологию событий делает книгу не стоящей времени потраченного на чтение.

«Биткоин. Графический роман о криптовалюте»

Как продать комикс в котором группа мужиков гоняется за бомжом по городу? Сделать предположение что это не бомж, а предполагаемый Сатоши Накамото, мужиков поменять на наемников и агентов спецслужб. А еще нужен хакер, который будет спасать бомжа, вот 100-страничный комикс и готов. Понятно что издатели хотели хайпануть на теме криптовалют и печатают любой бред, если в названии присутствует слово Биткоин.

«Цифровое Золото», Натаниэль Поппер

Хронология событий связанных с Биткоином в период между 2008 и 2014 годами, начиная с Адама Бэка и Хэла Финни и заканчивая падением Mt.Gox и Silkroad. Истории органично переплетены, и рассказывают о ключевых личностях стоявших у истоков протокола, первых майнерах и первых инвесторах. В книге нет технических деталей но отсутствие таковых даже идет ей на пользу. Однозначно, одна из моих любимых книг в 2017 году.

«Mastering Bitcoin», Andreas M. Antonopoulos

Алгоритмы, спецификации и как протокол работает изнутри. Мало воды и много примеров кода на c++ и python. Абсолютный must read для как разработчиков, так и просто любопытных. Книга выпущена под лицензией Creative Commons и доступна для публичного скачивания на русском языке.

«Киберпреступник №1. История создателя подпольной сетевой империи», Ник Билтон

История Росса Ульбрихта и сайта Silk Road как захватывающий детектив от начала и до конца. Особенно интересно читать и паралельно изучать огромный архив документов связанных с делом Silk Road. Росс не давал интервью при написании книги, так что некоторые из его поступков описаны по косвенным признакам, а его внутренний кофликт можно списать на фантазии автора.

Релизим Go приложения на Github

Написав очередную поделку на Go решил поделиться с сообществом, а чтобы никто не компилировал ее у себя дома можно воспользоваться тем скудным механизмом релизов, что предлагает Github. Но собирать и заливать артефакты сборки руками это не наш путь, ищем готовые решения. Собираем список качеств для такого инструмента:

  • Сборка бинарников под Linux/Mac, с установкой значений для ldflags флагов;
  • Автоматическая генерация описания релиза из сообщений к коммитам;
  • Единообразие - чтобы не собирать релиз из палок и веревок.

Вооружившись списком идем на Github в поисках подходящего инструмента.

aktau/github-release

Простой как дверь, не умеет ничего кроме заведения нового или редактирования существующего релиза. И даже не умеет, создавая релиз, заливать в него файлы пачкой, страдай заливая по одному файлу.

Имея такой скудный набор функций заставляет помнить тонну флагов, без которых отказывается работать. Не умеет сам билдить и не предлагает примеров по построению такого процесса. Выбирать такой инструмент смысла нет, несмотря на такое количество звезд на Github.

$ github-release release \
    --user aktau \
    --repo gofinance \
    --tag v0.1.0 \
    --name "the wolf of source street" \
    --description "Not a movie, contrary to popular opinion. Still, my first release!" \

$ github-release upload \
    --user aktau \
    --repo gofinance \
    --tag v0.1.0 \
    --name "gofinance-osx-amd64" \
    --file bin/darwin/amd64/gofinance

tcnksm/ghr

Сам автор сравнивает свой инструмент с предыдущим кандидатом говоря, что его поделка еще проще. Местами он проще и умеет читать из файла .git/config название репозитория для создания релиза, а еще умеет заливать все файлы разом в параллель. На этом плюсы заканчиваются, сборка релиза и описание остаются без внимания.

$ ghr -b "Release description" v0.1.0 pkg/

c4milo/github-release

Похож на ghr но не умеет читать настройки из git. Единственный из претендентов кто решил помочь советом как из gox и Makefile сделать готовый релиз и залить на Github, собрав при этом описание из сообщений к коммитам.

$ gox -ldflags "-X main.Version=v0.1.0" \
    -osarch="darwin/amd64" \
    -os="linux" \
    -output "dist/{{.Dir}}_$(VERSION)_{{.OS}}_{{.Arch}}/$(NAME)" \
    ./...

$ github-release \
    c4milo/release \
    v0.1.0 \
    "$$(git rev-parse --abbrev-ref HEAD)" \
    "**Changelog**<br/>$$(git log $$comparison --oneline --no-merges)" \
    "dist/*";

goreleaser/goreleaser

Просто комбайн, умеет много и при этом тщательно это скрывает. Редкий случай когда такой монстр может быть таким простым в управлении. Конфигурация по сборке хранится в файле .goreleaser.yml, а потому для сборки флагами можно пренебречь. Умеет собирать, запаковывать и заливать билды под все платформы, генерить описание из сообщений к коммитам и даже делать формулы для Homebrew.

Но есть и минусы - излишня любовь к саморекламе, описания к релизам будут содержать подпись «Automated with GoReleaser…». А еще у него сносит башню если текущий git HEAD не указывает на тег с номеров версии. Но если смириться с этим, то вариантов выбирать что-то отличное от goreleaser просто нет.

Ledger HW.1

На волне криптохайпа захотелось приобрести себе аппаратный Bitcoin кошелек. Но прикинув цены на Trezor и Ledger Nano S купил младшую модель Ledger HW.1 за $20, пользоваться я им конечно не буду.

Главная фишка аппаратных кошельков хранение приватных ключей без подключения к интернету и апаратная рандомизация seed при создании ключа. Большинство из них имеют экран для отображения информации о транзакциях и коды вторых факторов при подключении к компьютеру, Ledger HW.1 конечно не имеет.

Ledger HW.1

В упаковке помимо usb стика лежала карта второго фактора авторизации и бумажка для записи мнемонической фразы от кошелька. Вместо инструкции по применению лежала памятка с адресом https://www.ledgerwallet.com/start.

Ledger HW.1

Первое разочарование постигло когда оказалось, что для взаимодействия с кошельком кроме расширения для Chrome ничего другого нет. Кошелек рассчитан на простого обывателя, а параноики с Tails и Tor должны страдать. Можно конечно воспользоваться библиотекой на питоне, которая умеет читать и писать на стик, но никакой вменяемой документации или примеров использования нет.

Поскольку на сайте Ledger кроме красивых картинок невозможно найти список коинов, которые поддерживает HW.1, то второе разочарование постигло когда подключенный стик просил выбрать Bitcoin или Bitcoin Cash и оказалось, что ничего другого он не умеет, а все разнообразие альтоинов поддерживает только более продвинутая (читай — дорогая) линейка кошельков. Выбираем Bitcoin segwit2x, вводим второй фактор с карточки и кошелек готов к работе.

Ledger HW.1

Выводы такие, за $20 можно поиграться и посмотреть, что из себя представляют аппаратные кошельки. Но если рассматривать его как параноидальное место для хранения накоплений, то лучше приобрести Trezor или KeepKey.