]> git.tdb.fi Git - libs/gui.git/commitdiff
Split image loading into headers and pixels
authorMikko Rasa <tdb@tdb.fi>
Sun, 7 Feb 2021 16:13:51 +0000 (18:13 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 7 Feb 2021 16:13:51 +0000 (18:13 +0200)
14 files changed:
source/graphics/bmploader.cpp
source/graphics/bmploader.h
source/graphics/devil/devilloader.cpp
source/graphics/devil/devilloader.h
source/graphics/image.cpp
source/graphics/image.h
source/graphics/imageloader.cpp
source/graphics/imageloader.h
source/graphics/jpeg/jpegloader.cpp
source/graphics/jpeg/jpegloader.h
source/graphics/png/pngloader.cpp
source/graphics/png/pngloader.h
source/graphics/quartz/quartzloader.cpp
source/graphics/quartz/quartzloader.h

index 39629f714e776e3a8d1bfa954fe60007c1a3be3f..d88e2aa6435f36f3c908bf3c274a9799a5b2339e 100644 (file)
@@ -29,7 +29,8 @@ namespace Graphics {
 
 BmpLoader::BmpLoader(IO::Base &i, unsigned sb):
        io(i),
-       sig_bytes(sb)
+       sig_bytes(sb),
+       invert_row_order(false)
 {
        // Image data location is stored at offset 10 and can't be skipped
        if(sig_bytes>10)
@@ -44,7 +45,7 @@ bool BmpLoader::detect(const std::string &sig)
        return !sig.compare(0, sizeof(bmp_sig), bmp_sig, sizeof(bmp_sig));
 }
 
-void BmpLoader::load_(Image::Data &data)
+void BmpLoader::load_headers_(Image::Data &data)
 {
        char bm_header[14];
        read_full(io, bm_header+sig_bytes, sizeof(bm_header)-sig_bytes);
@@ -92,8 +93,13 @@ void BmpLoader::load_(Image::Data &data)
                skip -= size;
        }
 
+       invert_row_order = (height<0);
+}
+
+void BmpLoader::load_pixels_(Image::Data &data)
+{
        data.pixels = new char[data.stride*data.height];
-       if(height<0)
+       if(invert_row_order)
        {
                for(unsigned y=0; y<data.height; ++y)
                        read_full(io, data.pixels+(data.height-1-y)*data.stride, data.stride);
index 9ae8f4e7c21bbd0d7a8312281c539170e87ec52f..60be2dc14cf066a87450eefba6e05613109cbc89 100644 (file)
@@ -11,6 +11,7 @@ class BmpLoader: public ImageLoader
 private:
        IO::Base &io;
        unsigned sig_bytes;
+       bool invert_row_order;
 
 public:
        BmpLoader(IO::Base &, unsigned = 0);
@@ -18,7 +19,8 @@ public:
        static unsigned get_signature_size() { return 2; }
        static bool detect(const std::string &);
 
-       virtual void load_(Image::Data &);
+       virtual void load_headers_(Image::Data &);
+       virtual void load_pixels_(Image::Data &);
 };
 
 } // namespace Graphics
index 423b108a5bf6ad13d960099c03070cfe2e30b96b..a6693080748a001b87612615920e477e642b1018 100644 (file)
@@ -101,7 +101,7 @@ bool DevilLoader::detect(const string &sig)
        return type!=IL_TYPE_UNKNOWN;
 }
 
-void DevilLoader::load_(Image::Data &data)
+void DevilLoader::load_headers_(Image::Data &data)
 {
        ilSetRead(0, 0, eof, get, read, seek, tell);
        ilBindImage(id);
@@ -125,13 +125,21 @@ void DevilLoader::load_(Image::Data &data)
        data.width = ilGetInteger(IL_IMAGE_WIDTH);
        data.height = ilGetInteger(IL_IMAGE_HEIGHT);
        data.stride = data.width*ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL);
+
+       ilBindImage(0);
+       ilResetRead();
+}
+
+void DevilLoader::load_pixels_(Image::Data &data)
+{
+       ilBindImage(id);
+
        unsigned data_size = data.stride*data.height;
        data.pixels = new char[data_size];
        ILubyte *il_data = ilGetData();
        copy(il_data, il_data+data_size, data.pixels);
 
        ilBindImage(0);
-       ilResetRead();
 }
 
 } // namespace Graphics
index 3cba0d5a56f358c7b13a4832698798efe4051b89..01c26b1ead1282351343fdeda60c559a14dbae90 100644 (file)
@@ -19,7 +19,8 @@ public:
        static unsigned get_signature_size() { return 128; }
        static bool detect(const std::string &);
 
-       virtual void load_(Image::Data &);
+       virtual void load_headers_(Image::Data &);
+       virtual void load_pixels_(Image::Data &);
 };
 
 } // namespace Graphics
index 50e85dfe0981ca9b4ae1362d0de0fdc8439872f1..fcfd222c165e7d6472fa4fdf4b6ea1c34d02ae68 100644 (file)
@@ -67,9 +67,17 @@ void Image::load_io(IO::Seekable &io)
 
 void Image::load(ImageLoader &loader)
 {
-       data = Data();
+       if(loader.get_state()==ImageLoader::INITIAL)
+               data = Data();
        loader.load(data);
 }
 
+void Image::load_headers(ImageLoader &loader)
+{
+       if(loader.get_state()==ImageLoader::INITIAL)
+               data = Data();
+       loader.load_headers(data);
+}
+
 } // namespace Graphics
 } // namespace Msp
index 86cfa4589824d9413fbb5996f6e695d4a2e8a93f..7b5236ecd4f30c151c9c42148e955086c73cc17b 100644 (file)
@@ -35,6 +35,7 @@ public:
        void load_file(const std::string &);
        void load_io(IO::Seekable &);
        void load(ImageLoader &);
+       void load_headers(ImageLoader &);
 
        PixelFormat get_format() const { return data.fmt; }
        unsigned get_width() const { return data.width; }
index 2c6ce217381f4dcbf1f33bec50104eeee6c1987c..fa6fcf802b2a57eb6d852e34c6363d375e521ba4 100644 (file)
@@ -89,10 +89,21 @@ void ImageLoader::load(Image::Data &data)
        if(state>=FINISHED)
                throw logic_error("already loaded");
 
-       load_(data);
+       if(state<HEADERS_LOADED)
+               load_headers_(data);
+       load_pixels_(data);
        state = FINISHED;
 }
 
+void ImageLoader::load_headers(Image::Data &data)
+{
+       if(state>=HEADERS_LOADED)
+               throw logic_error("headers already loaded");
+
+       load_headers_(data);
+       state = HEADERS_LOADED;
+}
+
 ImageLoader::Registry &ImageLoader::get_registry()
 {
        static Registry registry;
index cb3f54ac204f303afe23e5bfc30b111ece28f33a..1ad6cc8c895aad812264df8663920cd6a56f6528 100644 (file)
@@ -27,6 +27,7 @@ public:
        enum State
        {
                INITIAL,
+               HEADERS_LOADED,
                FINISHED
        };
 
@@ -74,8 +75,10 @@ public:
        static ImageLoader *open_io(IO::Seekable &);
 
        virtual void load(Image::Data &);
+       virtual void load_headers(Image::Data &);
 protected:
-       virtual void load_(Image::Data &) = 0;
+       virtual void load_headers_(Image::Data &) = 0;
+       virtual void load_pixels_(Image::Data &) = 0;
 
 public:
        State get_state() const { return state; }
index f61f651d5db13104c6ec6e54c397d5d10929d3fc..4dd9440f7856d2731585acc5db4aef8325bb83ac 100644 (file)
@@ -119,7 +119,7 @@ bool JpegLoader::detect(const string &sig)
        return !sig.compare(0, sizeof(jpeg_sig), jpeg_sig, sizeof(jpeg_sig));
 }
 
-void JpegLoader::load_(Image::Data &data)
+void JpegLoader::load_headers_(Image::Data &data)
 {
        if(setjmp(priv->err_mgr.jmp))
                throw bad_image_data(priv->err_mgr.message);
@@ -132,7 +132,10 @@ void JpegLoader::load_(Image::Data &data)
        data.height = priv->jpeg.output_height;
        data.stride = priv->jpeg.output_width*priv->jpeg.output_components;
        data.fmt = RGB;
+}
 
+void JpegLoader::load_pixels_(Image::Data &data)
+{
        data.pixels = new char[data.stride*data.height];
        JSAMPROW rows[8];
        while(priv->jpeg.output_scanline<data.height)
index bf902d64c5b9b90f0ef95d241c6f4a7f7e28efde..a18d37e81bb10a8de2225ef8c686fa631576bda7 100644 (file)
@@ -20,7 +20,8 @@ public:
        static unsigned get_signature_size() { return 3; }
        static bool detect(const std::string &);
 
-       virtual void load_(Image::Data &);
+       virtual void load_headers_(Image::Data &);
+       virtual void load_pixels_(Image::Data &);
 };
 
 } // namespace Graphics
index 16ad36bbeb4bd3e7e53463d1ab056340e4a7dfe4..190d3cf297488e10977884080c5ad847b8645099 100644 (file)
@@ -29,6 +29,7 @@ struct PngLoader::Private
        std::string message;
        png_struct *png;
        png_info *info;
+       int interlace;
 };
 
 
@@ -54,13 +55,10 @@ bool PngLoader::detect(const std::string &sig)
        return !png_sig_cmp(reinterpret_cast<png_byte *>(const_cast<char*>(sig.data())), 0, sig.size());
 }
 
-void PngLoader::load_(Image::Data &data)
+void PngLoader::load_headers_(Image::Data &data)
 {
-       png_byte **rows = 0;
-
        if(setjmp(png_jmpbuf(priv->png)))
        {
-               delete[] rows;
                throw bad_image_data(priv->message);
        }
 
@@ -69,8 +67,7 @@ void PngLoader::load_(Image::Data &data)
        png_uint_32 height;
        int depth;
        int color;
-       int interlace;
-       png_get_IHDR(priv->png, priv->info, &width, &height, &depth, &color, &interlace, 0, 0);
+       png_get_IHDR(priv->png, priv->info, &width, &height, &depth, &color, &priv->interlace, 0, 0);
        unsigned nchans = png_get_channels(priv->png, priv->info);
 
        if(depth!=8)
@@ -89,10 +86,21 @@ void PngLoader::load_(Image::Data &data)
        case PNG_COLOR_TYPE_RGB_ALPHA:  data.fmt = RGBA; break;
        default: throw unsupported_image_format("unknown color type");
        }
+}
+
+void PngLoader::load_pixels_(Image::Data &data)
+{
+       png_byte **rows = 0;
+
+       if(setjmp(png_jmpbuf(priv->png)))
+       {
+               delete[] rows;
+               throw bad_image_data(priv->message);
+       }
 
        data.pixels = new char[data.stride*data.height];
 
-       if(interlace==PNG_INTERLACE_ADAM7)
+       if(priv->interlace==PNG_INTERLACE_ADAM7)
        {
                // ADAM7 requires all rows to be loaded at once
                unsigned n_passes = png_set_interlace_handling(priv->png);
index 21c1c72346d23c399dbb08b4a84686f4c0990f75..7c9390f23f79c4222972f211eeb87d1ad4561bd7 100644 (file)
@@ -20,7 +20,8 @@ public:
        static unsigned get_signature_size() { return 8; }
        static bool detect(const std::string &);
 
-       virtual void load_(Image::Data &);
+       virtual void load_headers_(Image::Data &);
+       virtual void load_pixels_(Image::Data &);
 };
 
 } // namespace Graphics
index 472e066f49665a64356cf1c50d93fba878589487..e025b66cf4786b852ed2a176ed0ee49b7e7d977c 100644 (file)
@@ -109,16 +109,6 @@ void QuartzLoader::load_(Image::Data &data)
                }
                else
                        throw unsupported_image_format("unknown colorspace");
-
-               CGDataProviderRef dp = CGImageGetDataProvider(image);
-               CFDataRef image_data = CGDataProviderCopyData(dp);
-               data.pixels = new char[data.height*data.stride];
-               unsigned offset = (alpha==kCGImageAlphaNoneSkipFirst);
-               CFRange range = CFRangeMake(offset, CFDataGetLength(image_data)-offset);
-               CFDataGetBytes(image_data, range, reinterpret_cast<UInt8 *>(data.pixels));
-               CFRelease(image_data);
-
-               CFRelease(image);
        }
        catch(...)
        {
@@ -127,5 +117,18 @@ void QuartzLoader::load_(Image::Data &data)
        }
 }
 
+void QuartzLoader::load_(Image::Data &data)
+{
+       CGDataProviderRef dp = CGImageGetDataProvider(image);
+       CFDataRef image_data = CGDataProviderCopyData(dp);
+       data.pixels = new char[data.height*data.stride];
+       unsigned offset = (alpha==kCGImageAlphaNoneSkipFirst);
+       CFRange range = CFRangeMake(offset, CFDataGetLength(image_data)-offset);
+       CFDataGetBytes(image_data, range, reinterpret_cast<UInt8 *>(data.pixels));
+       CFRelease(image_data);
+
+       CFRelease(image);
+}
+
 } // namespace Graphics
 } // namespace Msp
index cf4a4479968eb5622576b0dd48605b5977a05beb..3e856a98fdeb37ce6685f84457fa245ad6e92b00 100644 (file)
@@ -22,7 +22,8 @@ public:
        static unsigned get_signature_size() { return 12; }
        static bool detect(const std::string &);
 
-       virtual void load_(Image::Data &);
+       virtual void load_headers_(Image::Data &);
+       virtual void load_pixels_(Image::Data &);
 };
 
 } // namespace Graphics