Author: AlbrechtS
Date: 2010-12-16 12:23:57 -0800 (Thu, 16 Dec 2010)
New Revision: 8048
Log:
This new fl_read_image() function for Windows is *much* faster than
reading individual pixels as before (STR #2387), but there is still
room for improvement...


Modified:
   branches/branch-1.3/CHANGES
   branches/branch-1.3/src/fl_read_image_win32.cxx

Modified: branches/branch-1.3/CHANGES
===================================================================
--- branches/branch-1.3/CHANGES 2010-12-16 10:28:27 UTC (rev 8047)
+++ branches/branch-1.3/CHANGES 2010-12-16 20:23:57 UTC (rev 8048)
@@ -1,5 +1,6 @@
 CHANGES IN FLTK 1.3.0
 
+       - Much faster fl_read_image() for Windows (STR #2387).
        - Added general Options dialog (STR #2471)
        - Fixed Compiling with mingw-w64 (STR #2308).
        - Fixed crashes when detecting illegal utf 8 sequences

Modified: branches/branch-1.3/src/fl_read_image_win32.cxx
===================================================================
--- branches/branch-1.3/src/fl_read_image_win32.cxx     2010-12-16 10:28:27 UTC 
(rev 8047)
+++ branches/branch-1.3/src/fl_read_image_win32.cxx     2010-12-16 20:23:57 UTC 
(rev 8048)
@@ -36,11 +36,9 @@
              int   w,          // I - Width of area to read
              int   h,          // I - Height of area to read
              int   alpha) {    // I - Alpha value for image (0 for none)
-  int  x, y;                   // Looping vars
+
   int  d;                      // Depth of image
-  uchar        *ptr;                   // Pointer in image data
 
-
   // Allocate the image data array as needed...
   d = alpha ? 4 : 3;
 
@@ -49,24 +47,87 @@
   // Initialize the default colors/alpha in the whole image...
   memset(p, alpha, w * h * d);
 
-  // Grab all of the pixels in the image, one at a time...
-  // MRS: there has to be a better way than this!
-  for (y = 0, ptr = p; y < h; y ++) {
-    for (x = 0; x < w; x ++, ptr += d) {
-      COLORREF c = GetPixel(fl_gc, X + x, Y + y);
+  // Grab all of the pixels in the image...
 
-      ptr[0] = (uchar)c;
-      c >>= 8;
-      ptr[1] = (uchar)c;
-      c >>= 8;
-      ptr[2] = (uchar)c;
+  // Assure that we are not trying to read non-existing data. If it is so, the
+  // function should still work, but the out-of-bounds part of the image is
+  // untouched (initialized with the alpha value or 0 (black), resp.).
+
+  int ww = w; // We need the original width for output data line size
+
+  int shift_x = 0; // X target shift if X modified
+  int shift_y = 0; // Y target shift if X modified
+
+  if (X < 0) {
+    shift_x = -X;
+    w += X;
+    X = 0;
+  }
+  if (Y < 0) {
+    shift_y = -Y;
+    h += Y;
+    Y = 0;
+  }
+
+  if (h < 1 || w < 1) return p;                // nothing to copy
+
+  int line_size = ((3*w+3)/4) * 4;     // each line is aligned on a DWORD (4 
bytes)
+  uchar *dib = new uchar[line_size*h]; // create temporary buffer to read DIB
+
+  // fill in bitmap info for GetDIBits
+
+  BITMAPINFO   bi;
+  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+  bi.bmiHeader.biWidth = w;
+  bi.bmiHeader.biHeight = -h;          // negative => top-down DIB
+  bi.bmiHeader.biPlanes = 1;
+  bi.bmiHeader.biBitCount = 24;                // 24 bits RGB
+  bi.bmiHeader.biCompression = BI_RGB;
+  bi.bmiHeader.biSizeImage = 0;
+  bi.bmiHeader.biXPelsPerMeter = 0;
+  bi.bmiHeader.biYPelsPerMeter = 0;
+  bi.bmiHeader.biClrUsed = 0;
+  bi.bmiHeader.biClrImportant = 0;
+
+  // copy bitmap from original DC (Window, Fl_Offscreen, ...)
+
+  HDC hdc = CreateCompatibleDC(fl_gc);
+  HBITMAP hbm = CreateCompatibleBitmap(fl_gc,w,h);
+
+  int save_dc = SaveDC(hdc);                   // save context for cleanup
+  SelectObject(hdc,hbm);                       // select bitmap
+  BitBlt(hdc,0,0,w,h,fl_gc,X,Y,SRCCOPY);       // copy image section to DDB
+
+  // copy RGB image data to the allocated DIB
+
+  GetDIBits(hdc, hbm, 0, h, dib, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
+
+  // finally copy the image data to the user buffer
+
+  for (int j = 0; j<h; j++) {
+    const uchar *src = dib + j * line_size;                    // source line
+    uchar *tg = p + (j + shift_y) * d * ww + shift_x * d;      // target line
+    for (int i = 0; i<w; i++) {
+      uchar b = *src++;
+      uchar g = *src++;
+      *tg++ = *src++;  // R
+      *tg++ = g;       // G
+      *tg++ = b;       // B
+      if (alpha)
+       *tg++ = alpha;  // alpha
     }
   }
 
+  // free used GDI and other structures
+
+  RestoreDC(hdc,save_dc);      // reset DC
+  DeleteDC(hdc);
+  DeleteObject(hbm);
+  delete[] dib;                // delete DIB temporary buffer
+
   return p;
 }
 
-
 //
 // End of "$Id$".
 //

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to