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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
//
// Internal (Image) Reader class for the Fast Light Tool Kit (FLTK).
//
// Copyright 2020-2021 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
//
// Include necessary header files...
//
#include "Fl_Image_Reader.h"
#include <FL/fl_utf8.h>
#include <FL/fl_string_functions.h>
#include <stdlib.h>
#include <string.h>
/*
This internal (undocumented) class reads data chunks from a file or from
memory in LSB-first byte order.
This class is used in Fl_GIF_Image and Fl_BMP_Image to avoid code
duplication and may be extended to be used in similar cases. Future
options might be to read data in MSB-first byte order or to add more
methods.
*/
// Initialize the reader to access the file system, filename is copied
// and stored.
int Fl_Image_Reader::open(const char *filename) {
if (!filename)
return -1;
name_ = fl_strdup(filename);
if ((file_ = fl_fopen(filename, "rb")) == NULL) {
return -1;
}
is_file_ = 1;
return 0;
}
// Initialize the reader for memory access, name is copied and stored.
int Fl_Image_Reader::open(const char *imagename, const unsigned char *data, const size_t datasize) {
if (imagename)
name_ = fl_strdup(imagename);
if (data) {
start_ = data_ = data;
is_data_ = 1;
end_ = start_ + datasize;
return 0;
}
return -1;
}
// Initialize the reader for memory access, name is copied and stored.
// Deprecated, DO NOT USE! Buffer overruns will not be checked!
// Please use instead:
// Fl_Image_Reader::open(const char *imagename, const unsigned char *data, const size_t datasize)
int Fl_Image_Reader::open(const char *imagename, const unsigned char *data) {
if (imagename)
name_ = fl_strdup(imagename);
if (data) {
start_ = data_ = data;
is_data_ = 1;
return 0;
}
return -1;
}
// Close and destroy the reader
Fl_Image_Reader::~Fl_Image_Reader() {
if (is_file_ && file_) {
fclose(file_);
}
if (name_)
free(name_);
}
// Read a single byte from memory or a file
uchar Fl_Image_Reader::read_byte() {
if (error()) // don't read after read error or EOF
return 0;
if (is_file_) {
int ret = getc(file_);
if (ret < 0) {
if (feof(file_))
error_ = 1;
else if (ferror(file_))
error_ = 2;
else
error_ = 3; // unknown error
return 0;
}
return ret;
} else if (is_data_) {
if (data_ < end_)
return *data_++;
error_ = 1; // EOF
return 0;
}
error_ = 3; // undefined mode
return 0;
}
// Read a 16-bit unsigned integer, LSB-first
unsigned short Fl_Image_Reader::read_word() {
unsigned char b0, b1; // Bytes from file or memory
b0 = read_byte();
b1 = read_byte();
if (error())
return 0;
return ((b1 << 8) | b0);
}
// Read a 32-bit unsigned integer, LSB-first
unsigned int Fl_Image_Reader::read_dword() {
unsigned char b0, b1, b2, b3; // Bytes from file or memory
b0 = read_byte();
b1 = read_byte();
b2 = read_byte();
b3 = read_byte();
if (error())
return 0;
return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
}
// Move the current read position to a byte offset from the beginning
// of the file or the original start address in memory.
// This method clears the error flag if the position is valid.
// If reading from memory and (start_ + n) overflows, then the result is undefined.
void Fl_Image_Reader::seek(unsigned int n) {
error_ = 0;
if (is_file_) {
int ret = fseek(file_, n, SEEK_SET);
if (ret < 0)
error_ = 2; // read / position error
return;
} else if (is_data_) {
if (start_ + n <= end_)
data_ = start_ + n;
else
error_ = 2; // read / position error
return;
}
// unknown mode (not initialized ?)
error_ = 3;
}
// Get the current read position as a byte offset from the
// beginning of the file or the original start address in memory.
// This method does neither affect the error flag nor is it affected
// by the current error status. If reading from a file, this may
// return -1 or any error code from ftell().
long Fl_Image_Reader::tell() const {
if (is_file_) {
return ftell(file_);
} else if (is_data_) {
return long(data_ - start_);
}
return 0;
}
|