This repository has been archived by the owner on Jan 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 17
/
rle.hh
102 lines (93 loc) · 2.34 KB
/
rle.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* Copyright © 2010 Jakub Wilk <[email protected]>
*
* This file is part of pdf2djvu.
*
* pdf2djvu is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* pdf2djvu is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#ifndef PDF2DJVU_RLE_H
#define PDF2DJVU_RLE_H
#include <cassert>
#include <ostream>
/* Support for RLE formats.
* Please refer to csepdjvu(1) for the format specification.
*/
namespace rle
{
class R4
{
protected:
std::ostream &stream;
unsigned int x, width, height;
unsigned int run_length;
int last_pixel;
public:
template <typename T> R4(std::ostream &, T width, T height);
void operator <<(int pixel);
template <typename T> void output_run(T);
};
}
template <typename T>
rle::R4::R4(std::ostream &stream, T width_, T height_)
: stream(stream),
x(0), width(width_), height(height_),
run_length(0),
last_pixel(0)
{
assert(width_ > 0);
assert(height_ > 0);
assert(static_cast<T>(this->width) == width_);
assert(static_cast<T>(this->height) == height_);
this->stream << "R4 " << this->width << " " << this->height << " ";
}
void rle::R4::operator <<(int pixel)
{
pixel = !!pixel;
this->x++;
assert(this->x > 0);
if (this->last_pixel != pixel)
{
this->output_run(this->run_length);
this->run_length = 1;
this->last_pixel = pixel;
}
else
this->run_length++;
if (this->x == this->width)
{
this->output_run(this->run_length);
this->last_pixel = 0;
this->x = 0;
this->run_length = 0;
}
}
template <typename T>
void rle::R4::output_run(T length_)
{
unsigned int length = length_;
static const unsigned int max_length = 0x3FFF;
assert(length_ >= 0);
assert(static_cast<T>(length) == length_);
assert(length <= this->width);
while (length > max_length)
{
this->stream.write("\xFF\xFF", 3);
length -= max_length;
}
if (length >= 192)
{
this->stream
<< static_cast<char>(0xC0 + (length >> 8))
<< static_cast<char>(length & 0xFF);
}
else
this->stream << static_cast<char>(length);
}
#endif
// vim:ts=2 sts=2 sw=2 et