<commit_before>require "identiconify/version"
require "chunky_png"
require "siphash"

module Identiconify
  class Identicon
    HASH_KEY = "61616f73646a6173646a616f7369646a"

    attr_reader :string, :square_size, :row_count, :width, :inverse_offset

    def initialize(string, options={})
      @string = string
      @width = options.fetch(:width) { 250 }
      @row_count = 5
      @square_size = @width / @row_count
      # Since we can't draw subpixels we need to calculate how much we have to
      # offset the inverted version of the identicon to not create gaps or
      # overlaps in the middle of the image.
      @inverse_offset = @width - @square_size * @row_count
    end

    def column_count
      row_count.even? ? row_count/2 : row_count/2+1
    end

    def to_png_blob
      hash = SipHash.digest(HASH_KEY, string)

      # Use the three first bytes of the hash to generate a color
      r = hash & 0xff
      g = (hash >> 8) & 0xff
      b = (hash >> 16) & 0xff
      a = 0xff
      color = ChunkyPNG::Color.rgba(r,g,b,a)
      bg_color = ChunkyPNG::Color::TRANSPARENT

      # Remove the used three bytes
      hash >>= 24

      png = ChunkyPNG::Image.new(width, width, bg_color)
      0.upto(row_count-1).each do |row|
        0.upto(column_count-1).each do |column|
          if hash & 1 == 1
            x0 = column*square_size
            y0 = row*square_size
            x1 = (column+1)*square_size-1
            y1 = (row+1)*square_size-1
            png.rect(x0, y0, x1, y1, color, color)

            # Inverse the x coordinates making the image mirrored vertically
            x0 = width-(column+1)*square_size-inverse_offset
            x1 = width-column*square_size-inverse_offset-1
            png.rect(x0, y0, x1, y1, color, color)
          end
          hash >>= 1
        end
      end
      png.to_blob :color_mode => ChunkyPNG::COLOR_INDEXED
    end
  end
end<commit_msg>Added the option to make black and white identicons<commit_after>require "identiconify/version"
require "chunky_png"
require "siphash"

module Identiconify
  class Identicon
    HASH_KEY = "61616f73646a6173646a616f7369646a"

    attr_reader :string,
                :square_size,
                :row_count,
                :width,
                :inverse_offset,
                :style

    def initialize(string, options={})
      @string = string
      @width = options.fetch(:width) { 250 }
      @row_count = 5
      @square_size = @width / @row_count
      # Since we can't draw subpixels we need to calculate how much we have to
      # offset the inverted version of the identicon to not create gaps or
      # overlaps in the middle of the image.
      @inverse_offset = @width - @square_size * @row_count
      @style = options.fetch(:style) { :default }.to_sym
    end

    def column_count
      row_count.even? ? row_count/2 : row_count/2+1
    end

    def color_for_hash(hash)
      # Use the three first bytes of the hash to generate a color
      r = hash & 0xff
      g = (hash >> 8) & 0xff
      b = (hash >> 16) & 0xff
      a = 0xff
      transform_color ChunkyPNG::Color.rgba(r,g,b,a)
    end

    def transform_color(color)
      if style == :bw
        ChunkyPNG::Color.to_grayscale(color)
      else
        color
      end
    end

    def to_png_blob
      hash = SipHash.digest(HASH_KEY, string)

      
      color = color_for_hash(hash)
      bg_color = ChunkyPNG::Color::TRANSPARENT

      # Remove the used three color bytes
      hash >>= 24

      png = ChunkyPNG::Image.new(width, width, bg_color)
      0.upto(row_count-1).each do |row|
        0.upto(column_count-1).each do |column|
          if hash & 1 == 1
            x0 = column*square_size
            y0 = row*square_size
            x1 = (column+1)*square_size-1
            y1 = (row+1)*square_size-1
            png.rect(x0, y0, x1, y1, color, color)

            # Inverse the x coordinates making the image mirrored vertically
            x0 = width-(column+1)*square_size-inverse_offset
            x1 = width-column*square_size-inverse_offset-1
            png.rect(x0, y0, x1, y1, color, color)
          end
          hash >>= 1
        end
      end
      png.to_blob :color_mode => ChunkyPNG::COLOR_INDEXED
    end
  end
end
{'fraction_non_alphanumeric': 0.09191609710110771, 'fraction_numerical': 0.03299552203629508, 'mean_word_length': 2.1507052709725314, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2086985', 'n_tokens_mistral': 1498, 'n_tokens_neox': 1380, 'n_words': 376}