Skip to content

Commit 13b9388

Browse files
authored
Merge pull request #50 from lordnn/master
Speedup RAS loading. Fixed 32-bpp odd width images loading.
2 parents 95af9eb + 0a86fa5 commit 13b9388

1 file changed

Lines changed: 88 additions & 38 deletions

File tree

Source/Plugins/PluginRAS.cpp

Lines changed: 88 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -90,41 +90,88 @@ 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 (sz_ < 1) {
102+
return false;
103+
}
104+
pos_ = 0;
105+
}
106+
res = cache_[pos_++];
107+
return true;
108+
}
109+
110+
bool read_proc(void *buffer, unsigned size, unsigned count) {
111+
return 0 < io_->read_proc(buffer, size, count, handle_);
112+
}
113+
114+
private:
115+
uint8_t cache_[1024];
116+
FreeImageIO *io_{};
117+
fi_handle handle_{};
118+
uint32_t pos_{}, sz_{};
119+
};
120+
121+
static bool
122+
ReadData(CachedIO &cio, uint8_t *buf, uint32_t length, FIBOOL rle) {
95123
// Read either Run-Length Encoded or normal image data
96124

97-
static uint8_t repchar, remaining= 0;
125+
static uint8_t repchar{};
126+
static uint32_t remaining{};
98127

99128
if (rle) {
100129
// Run-length encoded read
101130

102-
while (length--) {
131+
while (length) {
103132
if (remaining) {
104-
remaining--;
105-
*(buf++)= repchar;
133+
const auto len{ std::min(remaining, length) };
134+
std::memset(buf, repchar, len);
135+
buf += len;
136+
length -= len;
137+
remaining -= len;
106138
} else {
107-
io->read_proc(&repchar, 1, 1, handle);
139+
if (!cio.getByte(repchar)) {
140+
break;
141+
}
108142

109143
if (repchar == RESC) {
110-
io->read_proc(&remaining, 1, 1, handle);
144+
uint8_t tmp{};
145+
if (!cio.getByte(tmp)) {
146+
break;
147+
}
111148

112-
if (remaining == 0) {
149+
if (0 == tmp) {
113150
*(buf++)= RESC;
151+
--length;
114152
} else {
115-
io->read_proc(&repchar, 1, 1, handle);
116-
117-
*(buf++)= repchar;
153+
if (!cio.getByte(repchar)) {
154+
break;
155+
}
156+
157+
remaining = tmp + 1;
158+
const auto len{ std::min(remaining, length) };
159+
std::memset(buf, repchar, len);
160+
buf += len;
161+
length -= len;
162+
remaining -= len;
118163
}
119164
} else {
120165
*(buf++)= repchar;
166+
--length;
121167
}
122168
}
123169
}
170+
return 0 == length;
124171
} else {
125172
// Normal read
126173

127-
io->read_proc(buf, length, 1, handle);
174+
return cio.read_proc(buf, length, 1);
128175
}
129176
}
130177

@@ -195,8 +242,8 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
195242
SUNHEADER header; // Sun file header
196243
uint16_t linelength; // Length of raster line in bytes
197244
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
245+
bool rle{}; // true if RLE file
246+
bool isRGB{}; // true if file type is RT_FORMAT_RGB
200247
uint8_t fillchar;
201248

202249
uint8_t *bits{}; // Pointer to dib data
@@ -206,7 +253,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
206253
return nullptr;
207254
}
208255

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

211258
try {
212259
// Read SUN raster header
@@ -231,9 +278,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
231278
if (header.magic != RAS_MAGIC) {
232279
throw FI_MSG_ERROR_MAGIC_NUMBER;
233280
}
234-
if (header.width > 65500 || header.height > 65500) {
235-
throw FI_MSG_ERROR_DIB_MEMORY;
236-
}
281+
if (header.width > 65500 || header.height > 65500) {
282+
throw FI_MSG_ERROR_DIB_MEMORY;
283+
}
237284

238285
// Allocate a new DIB
239286
std::unique_ptr<FIBITMAP, decltype(&FreeImage_Unload)> dib(nullptr, &FreeImage_Unload);
@@ -244,10 +291,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
244291
break;
245292

246293
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:
294+
case 32:
251295
dib.reset(FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK));
252296
break;
253297
}
@@ -258,9 +302,6 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
258302

259303
// Check the file format
260304

261-
rle = FALSE;
262-
isRGB = FALSE;
263-
264305
switch (header.type) {
265306
case RT_OLD:
266307
case RT_STANDARD:
@@ -271,11 +312,11 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
271312
break;
272313

273314
case RT_BYTE_ENCODED:
274-
rle = TRUE;
315+
rle = true;
275316
break;
276317

277318
case RT_FORMAT_RGB:
278-
isRGB = TRUE;
319+
isRGB = true;
279320
break;
280321

281322
default:
@@ -360,21 +401,26 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
360401
linelength = (uint16_t)header.width;
361402
}
362403

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

365406
// Read the image data
366407

367408
switch (header.depth) {
368409
case 1:
369410
case 8:
370411
{
412+
CachedIO cio(io, handle);
371413
for (y = 0; y < header.height; y++) {
372414
bits = FreeImage_GetScanLine(dib.get(), header.height - 1 - y);
373415

374-
ReadData(io, handle, bits, linelength, rle);
416+
if (!ReadData(cio, bits, linelength, rle)) {
417+
break;
418+
}
375419

376420
if (fill) {
377-
ReadData(io, handle, &fillchar, fill, rle);
421+
if (!ReadData(cio, &fillchar, fill, rle)) {
422+
break;
423+
}
378424
}
379425
}
380426

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

434+
CachedIO cio(io, handle);
388435
for (y = 0; y < header.height; y++) {
389436
bits = FreeImage_GetScanLine(dib.get(), header.height - 1 - y);
390437

391-
ReadData(io, handle, buf.get(), header.width * 3, rle);
438+
if (!ReadData(cio, buf.get(), header.width * 3, rle)) {
439+
break;
440+
}
392441

393442
const auto *bp = buf.get();
394443

@@ -411,7 +460,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
411460
}
412461

413462
if (fill) {
414-
ReadData(io, handle, &fillchar, fill, rle);
463+
if (!ReadData(cio, &fillchar, fill, rle)) {
464+
return nullptr;
465+
}
415466
}
416467
}
417468

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

476+
CachedIO cio(io, handle);
425477
for (y = 0; y < header.height; y++) {
426478
bits = FreeImage_GetScanLine(dib.get(), header.height - 1 - y);
427479

428-
ReadData(io, handle, buf.get(), header.width * 4, rle);
480+
if (!ReadData(cio, buf.get(), header.width * 4, rle)) {
481+
break;
482+
}
429483

430484
const auto *bp = buf.get();
431485

@@ -450,10 +504,6 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
450504
bp += 4;
451505
}
452506
}
453-
454-
if (fill) {
455-
ReadData(io, handle, &fillchar, fill, rle);
456-
}
457507
}
458508

459509
break;

0 commit comments

Comments
 (0)