sjpeg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e32ff2496989f7fdcf440d48449f1c9253a2ede2c910d6640a67d8273dc522be
4
+ data.tar.gz: 05ccb039b8365498d0ddd00538d8f11a3c98a06b302ee3e6b766b30c10e418e2
5
+ SHA512:
6
+ metadata.gz: 7943af367aee41ff9d5709449a51e9bf4e8345c02ce0ed7edfa149195ab7959b51751cf7088456115171cc875ab0266341a8f9a606fae8d2de25134cc7276e3e
7
+ data.tar.gz: 8c1f4951720b943c9c12020d32259f5c38d1c287a9360408bac99e550ffacda0b75d4813f8f41c66b694b9cdd2376687628ede91e5ae484bbce7c7fc5162c963
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.bundle
10
+ *.so
11
+ *.o
12
+ *.a
13
+ .rspec_status
14
+ Makefile
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sjpeg.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sjpeg (0.1.0)
5
+ ffi
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.3)
11
+ ffi (1.11.1)
12
+ rake (10.5.0)
13
+ rake-compiler (1.0.8)
14
+ rake
15
+ rspec (3.9.0)
16
+ rspec-core (~> 3.9.0)
17
+ rspec-expectations (~> 3.9.0)
18
+ rspec-mocks (~> 3.9.0)
19
+ rspec-core (3.9.0)
20
+ rspec-support (~> 3.9.0)
21
+ rspec-expectations (3.9.0)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.9.0)
24
+ rspec-mocks (3.9.0)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.9.0)
27
+ rspec-support (3.9.0)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ bundler (~> 2.0)
34
+ rake (~> 10.0)
35
+ rake-compiler
36
+ rspec (~> 3.0)
37
+ sjpeg!
38
+
39
+ BUNDLED WITH
40
+ 2.0.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Stefano Verna
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Sjpeg
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sjpeg`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'sjpeg'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install sjpeg
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/stefanoverna/sjpeg.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+ # ruby-sjpeg
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/extensiontask"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ Rake::ExtensionTask.new "sjpeg" do |ext|
10
+ ext.lib_dir = "lib/sjpeg"
11
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sjpeg"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,122 @@
1
+ // Copyright 2017 Google Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // Utility for writing bits
16
+ //
17
+ // Author: Skal (pascal.massimino@gmail.com)
18
+
19
+ #include "bit_writer.h"
20
+
21
+ #include <string.h>
22
+
23
+ #include "sjpeg.h"
24
+
25
+ namespace sjpeg {
26
+
27
+ ///////////////////////////////////////////////////////////////////////////////
28
+ // MemorySink
29
+
30
+ MemorySink::MemorySink(size_t expected_size)
31
+ : buf_(nullptr), pos_(0), max_pos_(0) {
32
+ // The following call can fail, with no harm: it'll be reported during the
33
+ // next call to Commit() if needed (we don't want to fail in a constructor).
34
+ (void)Commit(0, expected_size, &buf_);
35
+ }
36
+
37
+ MemorySink::~MemorySink() { Reset(); }
38
+
39
+ void MemorySink::Reset() {
40
+ delete[] buf_;
41
+ buf_ = nullptr;
42
+ pos_ = 0;
43
+ max_pos_ = 0;
44
+ }
45
+
46
+ void MemorySink::Release(uint8_t** buf_ptr, size_t* size_ptr) {
47
+ *buf_ptr = buf_;
48
+ *size_ptr = pos_;
49
+ buf_ = nullptr;
50
+ Reset();
51
+ }
52
+
53
+ bool MemorySink::Commit(size_t used_size, size_t extra_size, uint8_t** data) {
54
+ pos_ += used_size;
55
+ assert(pos_ <= max_pos_);
56
+ size_t new_size = pos_ + extra_size;
57
+ if (new_size > max_pos_) {
58
+ // TODO(skal): the x2 growth is probably over-shooting. Need to tune
59
+ // depending on use-case (ie.: what is the expected average final size?)
60
+ new_size += 256;
61
+ if (new_size < 2 * max_pos_) {
62
+ new_size = 2 * max_pos_;
63
+ }
64
+ uint8_t* const new_buf = new (std::nothrow) uint8_t[new_size];
65
+ if (new_buf == nullptr) return false;
66
+
67
+ if (pos_ > 0) memcpy(new_buf, buf_, pos_);
68
+ delete[] buf_;
69
+ buf_ = new_buf;
70
+ max_pos_ = new_size;
71
+ }
72
+ *data = buf_ + pos_;
73
+ return true;
74
+ }
75
+
76
+ ///////////////////////////////////////////////////////////////////////////////
77
+ // Sink factories
78
+
79
+ std::shared_ptr<ByteSink> MakeByteSink(std::string* const output) {
80
+ return std::shared_ptr<ByteSink>(new (std::nothrow) StringSink(output));
81
+ }
82
+
83
+ // specialization for vector<uint8_t>
84
+ template<>
85
+ std::shared_ptr<ByteSink> MakeByteSink(std::vector<uint8_t>* const output) {
86
+ return std::shared_ptr<ByteSink>(new (std::nothrow) VectorSink(output));
87
+ }
88
+
89
+ ///////////////////////////////////////////////////////////////////////////////
90
+ // BitWriter
91
+
92
+ BitWriter::BitWriter(ByteSink* const sink) : sink_(sink), buf_(nullptr) {
93
+ nb_bits_ = 0;
94
+ bits_ = 0x00000000U;
95
+ byte_pos_ = 0;
96
+ }
97
+
98
+ void BitWriter::Flush() {
99
+ // align and pad the bitstream
100
+ // nb_pad is the number of '1' bits we need to insert to reach a byte-aligned
101
+ // position. So nb_pad is 1,2..,7 when nb_bits_= 7,...2,1
102
+ const int nb_pad = (-nb_bits_) & 7;
103
+ if (nb_pad) {
104
+ PutBits((1 << nb_pad) - 1, nb_pad);
105
+ }
106
+ FlushBits();
107
+ }
108
+
109
+ ///////////////////////////////////////////////////////////////////////////////
110
+
111
+ void BitCounter::AddBits(const uint32_t bits, size_t nbits) {
112
+ size_ += nbits;
113
+ bit_pos_ += nbits;
114
+ bits_ |= bits << (32 - bit_pos_);
115
+ while (bit_pos_ >= 8) {
116
+ size_ += ((bits_ >> 24) == 0xff) ? 8 : 0;
117
+ bits_ <<= 8;
118
+ bit_pos_ -= 8;
119
+ }
120
+ }
121
+
122
+ } // namespace sjpeg
@@ -0,0 +1,169 @@
1
+ // Copyright 2017 Google Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // Utility for writing bits
16
+ //
17
+ // Author: Skal (pascal.massimino@gmail.com)
18
+
19
+ #ifndef SJPEG_BIT_WRITER_H_
20
+ #define SJPEG_BIT_WRITER_H_
21
+
22
+ #include <assert.h>
23
+ #include <stdint.h>
24
+ #include <string.h> // for memcpy
25
+
26
+ #include <string>
27
+ #include <vector>
28
+
29
+ #include "sjpeg.h"
30
+
31
+ namespace sjpeg {
32
+
33
+ ///////////////////////////////////////////////////////////////////////////////
34
+ // Memory-Sink
35
+
36
+ class MemorySink : public ByteSink {
37
+ public:
38
+ explicit MemorySink(size_t expected_size);
39
+ virtual ~MemorySink();
40
+ virtual bool Commit(size_t used_size, size_t extra_size, uint8_t** data);
41
+ virtual bool Finalize() { /* nothing to do */ return true; }
42
+ virtual void Reset();
43
+ void Release(uint8_t** buf_ptr, size_t* size_ptr);
44
+
45
+ private:
46
+ uint8_t* buf_;
47
+ size_t pos_, max_pos_;
48
+ };
49
+
50
+ ///////////////////////////////////////////////////////////////////////////////
51
+ // Sink for generic container
52
+ // Container must supply .resize() and [], and be byte-based.
53
+
54
+ template<class T> class Sink : public ByteSink {
55
+ public:
56
+ explicit Sink(T* const output) : ptr_(output), pos_(0) {}
57
+ virtual ~Sink() {}
58
+ virtual bool Commit(size_t used_size, size_t extra_size, uint8_t** data) {
59
+ pos_ += used_size;
60
+ assert(pos_ <= ptr_->size());
61
+ ptr_->resize(pos_ + extra_size);
62
+ if (ptr_->size() != pos_ + extra_size) return false;
63
+ *data = extra_size ? reinterpret_cast<uint8_t*>(&(*ptr_)[pos_]) : nullptr;
64
+ return true;
65
+ }
66
+ virtual bool Finalize() { ptr_->resize(pos_); return true; }
67
+ virtual void Reset() { ptr_->clear(); }
68
+
69
+ protected:
70
+ T* const ptr_;
71
+ size_t pos_;
72
+ };
73
+
74
+ typedef Sink<std::string> StringSink;
75
+ typedef Sink<std::vector<uint8_t> > VectorSink;
76
+
77
+ ///////////////////////////////////////////////////////////////////////////////
78
+ // BitWriter
79
+
80
+ class BitWriter {
81
+ public:
82
+ explicit BitWriter(ByteSink* const sink);
83
+
84
+ // Verifies the that output buffer can store at least 'size' more bytes.
85
+ // Also flushes the previously written data.
86
+ bool Reserve(size_t size) {
87
+ const bool ok = sink_->Commit(byte_pos_, size, &buf_);
88
+ if (!ok) sink_->Reset();
89
+ byte_pos_ = 0;
90
+ return ok;
91
+ }
92
+
93
+ // Make sure we can write 24 bits by flushing the past ones.
94
+ // WARNING! There's no check for buffer overwrite. Use Reserve() before
95
+ // calling this function.
96
+ void FlushBits() {
97
+ // worst case: 3 escaped codes = 6 bytes
98
+ while (nb_bits_ >= 8) {
99
+ const uint8_t tmp = bits_ >> 24;
100
+ buf_[byte_pos_++] = tmp;
101
+ if (tmp == 0xff) { // escaping
102
+ buf_[byte_pos_++] = 0x00;
103
+ }
104
+ bits_ <<= 8;
105
+ nb_bits_ -= 8;
106
+ }
107
+ }
108
+ // Writes the sequence 'bits' of length 'nb_bits' (less than 24).
109
+ // WARNING! There's no check for buffer overwrite. Use Reserve() before
110
+ // calling this function.
111
+ void PutBits(uint32_t bits, int nb) {
112
+ assert(nb <= 24 && nb > 0);
113
+ assert((bits & ~((1 << nb) - 1)) == 0);
114
+ FlushBits(); // make room for a least 24bits
115
+ nb_bits_+= nb;
116
+ bits_ |= bits << (32 - nb_bits_);
117
+ }
118
+ // Append one byte to buffer. FlushBits() must have been called before.
119
+ // WARNING! There's no check for buffer overwrite. Use Reserve() before
120
+ // calling this function.
121
+ // Also: no 0xff escaping is performed by this function.
122
+ void PutByte(uint8_t value) {
123
+ assert(nb_bits_ == 0);
124
+ buf_[byte_pos_++] = value;
125
+ }
126
+ // Same as multiply calling PutByte().
127
+ void PutBytes(const uint8_t* buf, size_t size) {
128
+ assert(nb_bits_ == 0);
129
+ assert(buf != NULL);
130
+ assert(size > 0);
131
+ memcpy(buf_ + byte_pos_, buf, size);
132
+ byte_pos_ += size;
133
+ }
134
+
135
+ // Handy helper to write a packed code in one call.
136
+ void PutPackedCode(uint32_t code) { PutBits(code >> 16, code & 0xff); }
137
+
138
+ // Write pending bits, and align bitstream with extra '1' bits.
139
+ void Flush();
140
+
141
+ // To be called last.
142
+ bool Finalize() { return Reserve(0) && sink_->Finalize(); }
143
+
144
+ private:
145
+ ByteSink* sink_;
146
+
147
+ int nb_bits_; // number of unwritten bits
148
+ uint32_t bits_; // accumulator for unwritten bits
149
+ size_t byte_pos_; // write position, in bytes
150
+ uint8_t* buf_; // destination buffer (don't access directly!)
151
+ };
152
+
153
+ // Class for counting bits, including the 0xff escape
154
+ struct BitCounter {
155
+ BitCounter() : bits_(0), bit_pos_(0), size_(0) {}
156
+
157
+ void AddPackedCode(const uint32_t code) { AddBits(code >> 16, code & 0xff); }
158
+ void AddBits(const uint32_t bits, size_t nbits);
159
+ size_t Size() const { return size_; }
160
+
161
+ private:
162
+ uint32_t bits_;
163
+ size_t bit_pos_;
164
+ size_t size_;
165
+ };
166
+
167
+ } // namespace sjpeg
168
+
169
+ #endif // SJPEG_BIT_WRITER_H_