octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: reading jpegs faster


From: David Grundberg
Subject: Re: reading jpegs faster
Date: Mon, 08 Feb 2010 11:21:28 +0100
User-agent: Thunderbird 2.0.0.23 (X11/20090812)

David Grundberg wrote:
John W. Eaton wrote:
On 22-Jan-2010, David Grundberg wrote:

| Okay. Now I got it down to 1.3 seconds. That's 130% compared to the | jpgread performance, instead of the previous 900%. Needs polish, but it | works.

Thanks for looking at this problem.

| +        P *vec = reinterpret_cast<P *> (im.fortran_vec ());

I don't think this cast is needed, given that P appears to always be
the same as the element type of IM.  So you could use the element_type
typedef from the class T and eliminate the template parameter P:

  template <class T, unsigned int D>
  octave_value_list
  read_images (const std::vector<Magick::Image>& imvec,
               const Array<int>& frameidx, unsigned int depth)
  {
    octave_value_list retval (3, Matrix ());

    T im;

    typedef typename T::element_type P;

      ...

          P *vec = im.fortran_vec ();

         ...

          case 1:
output = read_images<boolNDArray, 1> (imvec, frameidx, depth);
            break;

          ...

jwe

Thanks for the hint. I've been thinking on how to do that.

David


The attached changeset implements fortran_vec pointer arithmetics for all non-paletted images.

David
# HG changeset patch
# User David Grundberg <address@hidden>
# Date 1265623865 -3600
# Node ID ae93309f3d8896c7beb04cdd4ed4a83a32a6a1da
# Parent  272179888089ab8ce3c36139c6d474c67aae1e02
imread: Make reading non-indexed images faster

diff -r 272179888089 -r ae93309f3d88 src/ChangeLog
--- a/src/ChangeLog     Mon Feb 08 01:36:18 2010 -0500
+++ b/src/ChangeLog     Mon Feb 08 11:11:05 2010 +0100
@@ -1,3 +1,11 @@
+2010-02-08  David Grundberg  <address@hidden>
+
+       * DLD-FUNCTIONS/__magick_read__.cc (read_images): Reimplement
+       copying with direct fortran_vec manipulation, avoiding indexing
+       operations.  Replace scale_quantum_to_depth calls with simple
+       arithmetics.
+       (scale_quantum_to_depth): Remove function.
+
 2010-02-08  John W. Eaton  <address@hidden>
 
        * ov-class.cc (Fclass): If more than 1 argument, check that
diff -r 272179888089 -r ae93309f3d88 src/DLD-FUNCTIONS/__magick_read__.cc
--- a/src/DLD-FUNCTIONS/__magick_read__.cc      Mon Feb 08 01:36:18 2010 -0500
+++ b/src/DLD-FUNCTIONS/__magick_read__.cc      Mon Feb 08 11:11:05 2010 +0100
@@ -2,6 +2,7 @@
 
 Copyright (C) 2002, 2009 Andy Adler
 Copyright (C) 2008 Thomas L. Scofield
+Copyright (C) 2010 David Grundberg
 
 This file is part of Octave.
 
@@ -34,13 +35,6 @@
 #ifdef HAVE_MAGICK
 
 #include <Magick++.h>
-
-unsigned int
-scale_quantum_to_depth (const Magick::Quantum& quantum, unsigned int depth)
-{
-  return (static_cast<unsigned int> (static_cast<double> (quantum)
-                                     / MaxRGB * ((1 << depth) - 1)));
-}
 
 octave_value_list
 read_indexed_images (std::vector<Magick::Image>& imvec,
@@ -195,6 +189,8 @@
 read_images (const std::vector<Magick::Image>& imvec,
              const Array<int>& frameidx, unsigned int depth)
 {
+  typedef typename T::element_type P;
+
   octave_value_list retval (3, Matrix ());
 
   T im;
@@ -210,123 +206,155 @@
   idim(2) = 1;
   idim(3) = nframes;
 
-  Array<int> idx (dim_vector (4));
-
   Magick::ImageType type = imvec[0].type ();
+  const int divisor = (((1 << QuantumDepth) - 1) / ((1 << depth) - 1));
 
   switch (type)
     {
     case Magick::BilevelType:
     case Magick::GrayscaleType:
-      im = T (idim);
-      for (int frame = 0; frame < nframes; frame++)
-        {
-          const Magick::PixelPacket *pix
-            = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
+      {
+        im = T (idim);
+        P *vec = im.fortran_vec ();
 
-          int i = 0;
-          idx(2) = 0;
-          idx(3) = frame;
+        for (int frame = 0; frame < nframes; frame++)
+          {
+            const Magick::PixelPacket *pix
+              = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
 
-          for (int y = 0; y < rows; y++)
-            {
-              idx(0) = y;
-              for (int x = 0; x < columns; x++)
-                {
-                  idx(1) = x;
-                  im(idx) = scale_quantum_to_depth (pix[i++].red, depth);
-                }
-            }
+            P *rbuf;
+            rbuf = vec;
+            for (int y = 0; y < rows; y++)
+              {
+                for (int x = 0; x < columns; x++)
+                  {
+                    *rbuf = pix->red / divisor;
+                    pix++;
+                    rbuf += rows;
+                  }
+                rbuf -= rows * columns - 1;
+              }
+
+            // Next frame.
+            vec += rows * columns * idim(2);
+          }
         }
       break;
 
     case Magick::GrayscaleMatteType:
-      idim(2) = 2;
-      im = T (idim);
-      for (int frame = 0; frame < nframes; frame++)
-        {
-          const Magick::PixelPacket *pix
-            = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
+      {
+        idim(2) = 2;
+        im = T (idim);
+        P *vec = im.fortran_vec ();
 
-          int i = 0;
-          idx(3) = frame;
+        for (int frame = 0; frame < nframes; frame++)
+          {
+            const Magick::PixelPacket *pix
+              = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
 
-          for (int y = 0; y < rows; y++)
-            {
-              idx(0) = y;
-              for (int x = 0; x < columns; x++)
-                {
-                  idx(1) = x;
-                  idx(2) = 0;
-                  im(idx) = scale_quantum_to_depth (pix[i].red, depth);
-                  idx(2) = 1;
-                  im(idx) = scale_quantum_to_depth (pix[i].opacity, depth);
-                  i++;
-                }
-            }
+            P *rbuf, *obuf;
+            rbuf = vec;
+            obuf = vec + rows * columns;
+            for (int y = 0; y < rows; y++)
+              {
+                for (int x = 0; x < columns; x++)
+                  {
+                    *rbuf = pix->red / divisor;
+                    *obuf = pix->opacity / divisor;
+                    pix++;
+                    rbuf += rows;
+                    obuf += rows;
+                  }
+                rbuf -= rows * columns - 1;
+                obuf -= rows * columns - 1;
+              }
+
+            // Next frame.
+            vec += rows * columns * idim(2);
+          }
         }
       break;
 
     case Magick::PaletteType:
     case Magick::TrueColorType:
-      idim(2) = 3;
-      im = T (idim);
-      for (int frame = 0; frame < nframes; frame++)
-        {
-          const Magick::PixelPacket *pix
-            = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
+      {
+        idim(2) = 3;
+        im = T (idim);
+        P *vec = im.fortran_vec ();
 
-          int i = 0;
-          idx(3) = frame;
+        for (int frame = 0; frame < nframes; frame++)
+          {
+            const Magick::PixelPacket *pix
+              = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
 
-          for (int y = 0; y < rows; y++)
-            {
-              idx(0) = y;
-              for (int x = 0; x < columns; x++)
-                {
-                  idx(1) = x;
-                  idx(2) = 0;
-                  im(idx) = scale_quantum_to_depth (pix[i].red, depth);
-                  idx(2) = 1;
-                  im(idx) = scale_quantum_to_depth (pix[i].green, depth);
-                  idx(2) = 2;
-                  im(idx) = scale_quantum_to_depth (pix[i].blue, depth);
-                  i++;
-                }
-            }
+            P *rbuf, *gbuf, *bbuf;
+            rbuf = vec;
+            gbuf = vec + rows * columns;
+            bbuf = vec + rows * columns * 2;
+            for (int y = 0; y < rows; y++)
+              {
+                for (int x = 0; x < columns; x++)
+                  {
+                    *rbuf = pix->red / divisor;
+                    *gbuf = pix->green / divisor;
+                    *bbuf = pix->blue / divisor;
+                    pix++;
+                    rbuf += rows;
+                    gbuf += rows;
+                    bbuf += rows;
+                  }
+                rbuf -= rows * columns - 1;
+                gbuf -= rows * columns - 1;
+                bbuf -= rows * columns - 1;
+              }
+
+            // Next frame.
+            vec += rows * columns * idim(2);
+          }
         }
       break;
 
     case Magick::PaletteMatteType:
     case Magick::TrueColorMatteType:
     case Magick::ColorSeparationType:
-      idim(2) = 4;
-      im = T (idim);
-      for (int frame = 0; frame < nframes; frame++)
-        {
-          const Magick::PixelPacket *pix
-            = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
+      {
+        idim(2) = 4;
+        im = T (idim);
+        P *vec = im.fortran_vec ();
 
-          int i = 0;
-          idx(3) = frame;
+        for (int frame = 0; frame < nframes; frame++)
+          {
+            const Magick::PixelPacket *pix
+              = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
 
-          for (int y = 0; y < rows; y++)
-            {
-              idx(0) = y;
-              for (int x = 0; x < columns; x++)
-                {
-                  idx(1) = x;
-                  idx(2) = 0;
-                  im(idx) = scale_quantum_to_depth (pix[i].red, depth);
-                  idx(2) = 1;
-                  im(idx) = scale_quantum_to_depth (pix[i].green, depth);
-                  idx(2) = 2;
-                  im(idx) = scale_quantum_to_depth (pix[i].blue, depth);
-                  idx(2) = 3;
-                  im(idx) = scale_quantum_to_depth (pix[i].opacity, depth);
-                  i++;
-                }
-            }
+            P *rbuf, *gbuf, *bbuf, *obuf;
+            rbuf = vec;
+            gbuf = vec + rows * columns;
+            bbuf = vec + rows * columns * 2;
+            obuf = vec + rows * columns * 3;
+            for (int y = 0; y < rows; y++)
+              {
+                for (int x = 0; x < columns; x++)
+                  {
+                    *rbuf = pix->red / divisor;
+                    *gbuf = pix->green / divisor;
+                    *bbuf = pix->blue / divisor;
+                    *obuf = pix->opacity / divisor;
+                    pix++;
+                    rbuf += rows;
+                    gbuf += rows;
+                    bbuf += rows;
+                    obuf += rows;
+                  }
+                rbuf -= rows * columns - 1;
+                gbuf -= rows * columns - 1;
+                bbuf -= rows * columns - 1;
+                obuf -= rows * columns - 1;
+              }
+
+            // Next frame.
+            vec += rows * columns * idim(2);
+          }
         }
       break;
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]