sjpeg 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +40 -0
- data/LICENSE.txt +21 -0
- data/README.md +40 -0
- data/Rakefile +11 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/sjpeg/bit_writer.cc +122 -0
- data/ext/sjpeg/bit_writer.h +169 -0
- data/ext/sjpeg/colors_rgb.cc +691 -0
- data/ext/sjpeg/dichotomy.cc +290 -0
- data/ext/sjpeg/enc.cc +2132 -0
- data/ext/sjpeg/extconf.rb +3 -0
- data/ext/sjpeg/fdct.cc +627 -0
- data/ext/sjpeg/headers.cc +218 -0
- data/ext/sjpeg/jpeg_tools.cc +274 -0
- data/ext/sjpeg/libsjpeg.pc.in +11 -0
- data/ext/sjpeg/score_7.cc +6220 -0
- data/ext/sjpeg/sjpeg.h +353 -0
- data/ext/sjpeg/sjpegi.h +427 -0
- data/ext/sjpeg/yuv_convert.cc +698 -0
- data/lib/sjpeg/version.rb +3 -0
- data/lib/sjpeg.rb +35 -0
- data/sjpeg.gemspec +36 -0
- metadata +143 -0
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
data/Gemfile
ADDED
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
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,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_
|