Skip to content

Commit c083693

Browse files
committed
Speedup RAS loading. Fixed 32-bpp odd width images loading.
1 parent d7a6ab7 commit c083693

1 file changed

Lines changed: 96 additions & 39 deletions

File tree

Source/Plugins/PluginRAS.cpp

Lines changed: 96 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -90,41 +90,92 @@ typedef struct tagSUNHEADER {
9090
// Internal functions
9191
// ==========================================================
9292

93-
static void
94-
ReadData(FreeImageIO *io, fi_handle handle, uint8_t *buf, uint32_t length, FIBOOL rle) {
93+
class CachedIO {
94+
public:
95+
CachedIO(FreeImageIO *io, fi_handle handle) : io_{ io }, handle_{ handle } {
96+
}
97+
98+
bool getByte(uint8_t &res) {
99+
if (sz_ <= pos_) {
100+
sz_ = io_->read_proc(cache_, 1, std::size(cache_), handle_);
101+
#if 1
102+
if (sz_ < 1) {
103+
return false;
104+
}
105+
#else
106+
sz_ = std::size(cache_);
107+
#endif
108+
pos_ = 0;
109+
}
110+
res = cache_[pos_++];
111+
return true;
112+
}
113+
114+
bool read_proc(void *buffer, unsigned size, unsigned count) {
115+
return 0 < io_->read_proc(buffer, size, count, handle_);
116+
}
117+
118+
private:
119+
uint8_t cache_[1024];
120+
FreeImageIO *io_{};
121+
fi_handle handle_{};
122+
uint32_t pos_{}, sz_{};
123+
};
124+
125+
static bool
126+
ReadData(CachedIO &cio, uint8_t *buf, uint32_t length, FIBOOL rle) {
95127
// Read either Run-Length Encoded or normal image data
96128

97-
static uint8_t repchar, remaining= 0;
129+
static uint8_t repchar{};
130+
static uint32_t remaining{};
98131

99132
if (rle) {
100133
// Run-length encoded read
101134

102-
while (length--) {
135+
while (length) {
103136
if (remaining) {
104-
remaining--;
105-
*(buf++)= repchar;
137+
const auto len{ std::min(remaining, length) };
138+
std::memset(buf, repchar, len);
139+
buf += len;
140+
length -= len;
141+
remaining -= len;
106142
} else {
107-
io->read_proc(&repchar, 1, 1, handle);
143+
if (!cio.getByte(repchar)) {
144+
break;
145+
}
108146

109147
if (repchar == RESC) {
110-
io->read_proc(&remaining, 1, 1, handle);
148+
uint8_t tmp{};
149+
if (!cio.getByte(tmp)) {
150+
break;
151+
}
111152

112-
if (remaining == 0) {
153+
if (0 == tmp) {
113154
*(buf++)= RESC;
155+
--length;
114156
} else {
115-
io->read_proc(&repchar, 1, 1, handle);
116-
117-
*(buf++)= repchar;
157+
if (!cio.getByte(repchar)) {
158+
break;
159+
}
160+
161+
remaining = tmp + 1;
162+
const auto len{ std::min(remaining, length) };
163+
std::memset(buf, repchar, len);
164+
buf += len;
165+
length -= len;
166+
remaining -= len;
118167
}
119168
} else {
120169
*(buf++)= repchar;
170+
--length;
121171
}
122172
}
123173
}
174+
return 0 == length;
124175
} else {
125176
// Normal read
126177

127-
io->read_proc(buf, length, 1, handle);
178+
return cio.read_proc(buf, length, 1);
128179
}
129180
}
130181

@@ -195,18 +246,18 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
195246
SUNHEADER header; // Sun file header
196247
uint16_t linelength; // Length of raster line in bytes
197248
uint16_t fill; // Number of fill bytes per raster line
198-
FIBOOL rle; // TRUE if RLE file
199-
FIBOOL isRGB; // TRUE if file type is RT_FORMAT_RGB
249+
bool rle{}; // true if RLE file
250+
bool isRGB{}; // true if file type is RT_FORMAT_RGB
200251
uint8_t fillchar;
201252

202253
uint8_t *bits{}; // Pointer to dib data
203-
uint16_t x, y;
254+
uint32_t x, y;
204255

205256
if (!handle) {
206257
return nullptr;
207258
}
208259

209-
FIBOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
260+
const bool header_only{ (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS };
210261

211262
try {
212263
// Read SUN raster header
@@ -231,9 +282,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
231282
if (header.magic != RAS_MAGIC) {
232283
throw FI_MSG_ERROR_MAGIC_NUMBER;
233284
}
234-
if (header.width > 65500 || header.height > 65500) {
235-
throw FI_MSG_ERROR_DIB_MEMORY;
236-
}
285+
/*if (header.width > 65500 || header.height > 65500) {
286+
throw FI_MSG_ERROR_DIB_MEMORY;
287+
}*/
237288

238289
// Allocate a new DIB
239290
std::unique_ptr<FIBITMAP, decltype(&FreeImage_Unload)> dib(nullptr, &FreeImage_Unload);
@@ -244,10 +295,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
244295
break;
245296

246297
case 24:
247-
dib.reset(FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK));
248-
break;
249-
250-
case 32:
298+
case 32:
251299
dib.reset(FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK));
252300
break;
253301
}
@@ -256,10 +304,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
256304
throw FI_MSG_ERROR_DIB_MEMORY;
257305
}
258306

259-
// Check the file format
307+
header.width = FreeImage_GetWidth(dib.get());
308+
header.height = FreeImage_GetHeight(dib.get());
260309

261-
rle = FALSE;
262-
isRGB = FALSE;
310+
// Check the file format
263311

264312
switch (header.type) {
265313
case RT_OLD:
@@ -271,11 +319,11 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
271319
break;
272320

273321
case RT_BYTE_ENCODED:
274-
rle = TRUE;
322+
rle = true;
275323
break;
276324

277325
case RT_FORMAT_RGB:
278-
isRGB = TRUE;
326+
isRGB = true;
279327
break;
280328

281329
default:
@@ -360,21 +408,26 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
360408
linelength = (uint16_t)header.width;
361409
}
362410

363-
fill = (linelength % 2) ? 1 : 0;
411+
fill = (linelength & 1) ? 1 : 0;
364412

365413
// Read the image data
366414

367415
switch (header.depth) {
368416
case 1:
369417
case 8:
370418
{
419+
CachedIO cio(io, handle);
371420
for (y = 0; y < header.height; y++) {
372421
bits = FreeImage_GetScanLine(dib.get(), header.height - 1 - y);
373422

374-
ReadData(io, handle, bits, linelength, rle);
423+
if (!ReadData(cio, bits, linelength, rle)) {
424+
break;
425+
}
375426

376427
if (fill) {
377-
ReadData(io, handle, &fillchar, fill, rle);
428+
if (!ReadData(cio, &fillchar, fill, rle)) {
429+
break;
430+
}
378431
}
379432
}
380433

@@ -385,10 +438,13 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
385438
{
386439
auto buf = std::make_unique<uint8_t[]>(header.width * 3);
387440

441+
CachedIO cio(io, handle);
388442
for (y = 0; y < header.height; y++) {
389443
bits = FreeImage_GetScanLine(dib.get(), header.height - 1 - y);
390444

391-
ReadData(io, handle, buf.get(), header.width * 3, rle);
445+
if (!ReadData(cio, buf.get(), header.width * 3, rle)) {
446+
break;
447+
}
392448

393449
const auto *bp = buf.get();
394450

@@ -411,7 +467,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
411467
}
412468

413469
if (fill) {
414-
ReadData(io, handle, &fillchar, fill, rle);
470+
if (!ReadData(cio, &fillchar, fill, rle)) {
471+
return nullptr;
472+
}
415473
}
416474
}
417475

@@ -422,10 +480,13 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
422480
{
423481
auto buf = std::make_unique<uint8_t[]>(header.width * 4);
424482

483+
CachedIO cio(io, handle);
425484
for (y = 0; y < header.height; y++) {
426485
bits = FreeImage_GetScanLine(dib.get(), header.height - 1 - y);
427486

428-
ReadData(io, handle, buf.get(), header.width * 4, rle);
487+
if (!ReadData(cio, buf.get(), header.width * 4, rle)) {
488+
break;
489+
}
429490

430491
const auto *bp = buf.get();
431492

@@ -450,10 +511,6 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
450511
bp += 4;
451512
}
452513
}
453-
454-
if (fill) {
455-
ReadData(io, handle, &fillchar, fill, rle);
456-
}
457514
}
458515

459516
break;

0 commit comments

Comments
 (0)