Module: Texel

Defined in:
lib/texel.rb,
lib/texel/gl.rb,
lib/texel/info.rb,
lib/texel/wgpu.rb,
lib/texel/codec.rb,
lib/texel/image.rb,
lib/texel/errors.rb,
lib/texel/native.rb,
lib/texel/version.rb,
lib/texel/registry.rb,
lib/texel/resampler.rb,
lib/texel/codecs/qoi.rb,
lib/texel/codecs/stb.rb,
lib/texel/half_float.rb,
lib/texel/pixel_data.rb,
lib/texel/source_reader.rb,
lib/texel/color_transform.rb,
lib/texel/image_transformations.rb,
ext/texel/texel_native.c

Defined Under Namespace

Modules: Codecs, ColorTransform, GL, HalfFloat, ImageTransformations, Native, NativeBridge, PixelData, Registry, Resampler, SourceReader, WGPU Classes: Codec, DecodeError, EncodeError, Error, FormatError, Image, Info, MissingCodecError

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.encode(image, format, **options) ⇒ Object

Raises:



39
40
41
42
43
44
45
46
# File 'lib/texel.rb', line 39

def encode(image, format, **options)
  raise FormatError, "expected a Texel::Image" unless image.is_a?(Image)

  normalized = normalize_format(format)
  encoded = String(Registry.codec_for!(normalized, operation: :encode).encode(image, normalized, **options))
  encoded = encoded.dup.force_encoding(Encoding::BINARY) unless encoded.encoding == Encoding::BINARY
  encoded.freeze
end

.info(source) ⇒ Object



33
34
35
36
37
# File 'lib/texel.rb', line 33

def info(source)
  input = SourceReader.read(source)
  format = detect_format!(input)
  Registry.codec_for!(format, operation: :decode).info(input.bytes, format: format)
end

.load(source, channels: nil, dtype: nil, flip_y: false, color_space: nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/texel.rb', line 20

def load(source, channels: nil, dtype: nil, flip_y: false, color_space: nil)
  validate_channels!(channels) if channels
  validate_dtype!(dtype) if dtype
  validate_color_space!(color_space) if color_space

  input = SourceReader.read(source)
  format = detect_format!(input)
  codec = Registry.codec_for!(format, operation: :decode)
  image = codec.decode(input.bytes, channels: channels, dtype: dtype, format: format)
  image = image.dup_with(color_space: color_space) if color_space
  flip_y ? image.flip_y : image
end

.load_all(paths, threads: 4, **options) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/texel.rb', line 59

def load_all(paths, threads: 4, **options)
  unless threads.is_a?(Integer) && threads.positive?
    raise FormatError, "threads must be a positive integer"
  end

  sources = paths.to_a
  return [] if sources.empty?

  queue = Queue.new
  sources.each_index { |index| queue << index }
  results = Array.new(sources.length)
  errors = Array.new(sources.length)
  workers = [threads, sources.length].min.times.map do
    Thread.new do
      loop do
        index = queue.pop(true)
        results[index] = load(sources[index], **options)
      rescue ThreadError
        break
      rescue StandardError => e
        errors[index] = e
      end
    end
  end
  workers.each(&:join)
  raise errors.compact.first if errors.any?

  results
end

.save(image, destination, format: nil, **options) ⇒ Object



48
49
50
51
52
53
54
55
56
57
# File 'lib/texel.rb', line 48

def save(image, destination, format: nil, **options)
  resolved_format = format || destination_format(destination)
  bytes = encode(image, resolved_format, **options)
  return write_io(destination, bytes) if destination.respond_to?(:write)

  File.binwrite(destination, bytes)
  destination
rescue SystemCallError => e
  raise EncodeError, "could not write image: #{e.message}"
end