PPM translator: use a buffer for reading

Reading the file 1 byte at a time from a BFile is very inefficient.
Add a buffer, which makes things a lot faster (parsing a 200x200 image
used to run for a few seconds with 100% CPU use).

Change-Id: Ie2eea819475c9301fbb6102c41fa05ec2d2ca343
Reviewed-on: https://review.haiku-os.org/c/906
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Adrien Destugues 2019-01-26 20:33:01 +01:00 committed by waddlesplash
parent 58913f60e8
commit 71aec29751

View File

@ -4,11 +4,9 @@
*/ */
/* Parse the ASCII and raw versions of PPM. */ /* Parse the ASCII and raw versions of PPM. */
/* Note that the parsing of ASCII is very inefficient, because BFile */
/* does not buffer data. We should wrap a buffering thing around */
/* the input or output when they are in ASCII mode. */
#include <Bitmap.h> #include <Bitmap.h>
#include <BufferedDataIO.h>
#include <ByteOrder.h> #include <ByteOrder.h>
#include <Catalog.h> #include <Catalog.h>
#include <CheckBox.h> #include <CheckBox.h>
@ -204,6 +202,7 @@ public:
fclose(f); fclose(f);
} }
} }
~PrefsLoader() ~PrefsLoader()
{ {
/* No need writing settings if there aren't any */ /* No need writing settings if there aren't any */
@ -242,16 +241,13 @@ status_t copy_data(BDataIO* in, BDataIO* out, int rowbytes, int out_rowbytes,
int height, int max, bool in_ascii, bool out_ascii, color_space in_space, int height, int max, bool in_ascii, bool out_ascii, color_space in_space,
color_space out_space); color_space out_space);
/* Return B_NO_TRANSLATOR if not handling this data. */ /* Return B_NO_TRANSLATOR if not handling this data. */
/* Even if inputFormats exists, may be called for data without hints */ /* Even if inputFormats exists, may be called for data without hints */
/* If outType is not 0, must be able to export in wanted format */ /* If outType is not 0, must be able to export in wanted format */
status_t status_t
Identify(/* required */ Identify(BPositionIO* inSource, const translation_format* inFormat,
BPositionIO* inSource, BMessage* ioExtension, translator_info* outInfo, uint32 outType)
const translation_format* inFormat, /* can beNULL */
BMessage* ioExtension, /* can be NULL */
translator_info* outInfo, uint32 outType)
{ {
dprintf(("PPMTranslator: Identify()\n")); dprintf(("PPMTranslator: Identify()\n"));
/* Silence compiler warnings. */ /* Silence compiler warnings. */
@ -629,11 +625,8 @@ private:
/* settings that is atomically copied into the translator function */ /* settings that is atomically copied into the translator function */
/* as a local when translation starts. */ /* as a local when translation starts. */
/* Store your settings wherever you feel like it. */ /* Store your settings wherever you feel like it. */
status_t status_t
MakeConfig(/* optional */ MakeConfig(BMessage* ioExtension, BView** outView, BRect* outExtent)
BMessage* ioExtension, /* can be NULL */
BView** outView, BRect* outExtent)
{ {
PPMView* v PPMView* v
= new PPMView(B_TRANSLATE("PPMTranslator Settings"), B_WILL_DRAW); = new PPMView(B_TRANSLATE("PPMTranslator Settings"), B_WILL_DRAW);
@ -651,10 +644,8 @@ MakeConfig(/* optional */
/* Copy your current settings to a BMessage that may be passed */ /* Copy your current settings to a BMessage that may be passed */
/* to BTranslators::Translate at some later time when the user wants to */ /* to BTranslators::Translate at some later time when the user wants to */
/* use whatever settings you're using right now. */ /* use whatever settings you're using right now. */
status_t status_t
GetConfigMessage(/* optional */ GetConfigMessage(BMessage* ioExtension)
BMessage* ioExtension)
{ {
status_t err = B_OK; status_t err = B_OK;
const char* name = B_TRANSLATOR_EXT_BITMAP_COLOR_SPACE; const char* name = B_TRANSLATOR_EXT_BITMAP_COLOR_SPACE;
@ -985,6 +976,10 @@ copy_data(BDataIO* in, BDataIO* out, int rowbytes, int out_rowbytes, int height,
{ {
dprintf(("copy_data(%d, %d, %d, %d, %x, %x)\n", rowbytes, out_rowbytes, dprintf(("copy_data(%d, %d, %d, %d, %x, %x)\n", rowbytes, out_rowbytes,
height, max, in_space, out_space)); height, max, in_space, out_space));
// We will be reading 1 char at a time, so use a buffer
BBufferedDataIO inBuffer(*in, 65536, false);
/* We read/write one scanline at a time. */ /* We read/write one scanline at a time. */
unsigned char* data = (unsigned char*) malloc(rowbytes); unsigned char* data = (unsigned char*) malloc(rowbytes);
unsigned char* out_data = (unsigned char*) malloc(out_rowbytes); unsigned char* out_data = (unsigned char*) malloc(out_rowbytes);
@ -1001,9 +996,9 @@ copy_data(BDataIO* in, BDataIO* out, int rowbytes, int out_rowbytes, int height,
/* There is no data format conversion, so we can just copy data. */ /* There is no data format conversion, so we can just copy data. */
while ((height-- > 0) && !err) { while ((height-- > 0) && !err) {
if (in_ascii) { if (in_ascii) {
err = read_ascii_line(in, max, data, rowbytes); err = read_ascii_line(&inBuffer, max, data, rowbytes);
} else { } else {
err = in->Read(data, rowbytes); err = inBuffer.Read(data, rowbytes);
if (err == rowbytes) { if (err == rowbytes) {
err = B_OK; err = B_OK;
} }