<commit_before>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/renderer_host/media/screen_capture_device.h"

#include "base/basictypes.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::InvokeWithoutArgs;
using ::testing::SaveArg;

namespace content {

namespace {

const int kTestFrameWidth1 = 100;
const int kTestFrameHeight1 = 100;
const int kTestFrameWidth2 = 200;
const int kTestFrameHeight2 = 150;
const int kBufferSize = kTestFrameWidth2 * kTestFrameHeight2 * 4;

const int kFrameRate = 30;

class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
 public:
  MOCK_METHOD0(ReserveOutputBuffer, scoped_refptr<media::VideoFrame>());
  MOCK_METHOD0(OnError, void());
  MOCK_METHOD1(OnFrameInfo, void(const media::VideoCaptureCapability& info));
  MOCK_METHOD6(OnIncomingCapturedFrame, void(const uint8* data,
                                             int length,
                                             base::Time timestamp,
                                             int rotation,
                                             bool flip_vert,
                                             bool flip_horiz));
  MOCK_METHOD2(OnIncomingCapturedVideoFrame,
      void(const scoped_refptr<media::VideoFrame>& frame,
           base::Time timestamp));
};

// TODO(sergeyu): Move this to a separate file where it can be reused.
class FakeScreenCapturer : public webrtc::ScreenCapturer {
 public:
  FakeScreenCapturer()
      : callback_(NULL),
        frame_index_(0) {
  }
  virtual ~FakeScreenCapturer() {}

  // VideoFrameCapturer interface.
  virtual void Start(Callback* callback) OVERRIDE {
    callback_ = callback;
  }

  virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE {
    webrtc::DesktopSize size;
    if (frame_index_ % 2 == 0) {
      size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1);
    } else {
      size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2);
    }
    frame_index_++;
    callback_->OnCaptureCompleted(new webrtc::BasicDesktopFrame(size));
  }

  virtual void SetMouseShapeObserver(
      MouseShapeObserver* mouse_shape_observer) OVERRIDE {
  }

 private:
  Callback* callback_;
  int frame_index_;
};

class ScreenCaptureDeviceTest : public testing::Test {
 public:
  virtual void SetUp() OVERRIDE {
    worker_pool_ = new base::SequencedWorkerPool(3, "TestCaptureThread");
  }

 protected:
  scoped_refptr<base::SequencedWorkerPool> worker_pool_;
};

}  // namespace

TEST_F(ScreenCaptureDeviceTest, Capture) {
  ScreenCaptureDevice capture_device(
      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
  media::VideoCaptureCapability caps;
  base::WaitableEvent done_event(false, false);
  int frame_size;

  MockFrameObserver frame_observer;
  EXPECT_CALL(frame_observer, OnFrameInfo(_))
      .WillOnce(SaveArg<0>(&caps));
  EXPECT_CALL(frame_observer, OnError())
      .Times(0);
  EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
      .WillRepeatedly(DoAll(
          SaveArg<1>(&frame_size),
          InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));

  capture_device.Allocate(640, 480, kFrameRate, &frame_observer);
  capture_device.Start();
  EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
  capture_device.Stop();
  capture_device.DeAllocate();

  EXPECT_GT(caps.width, 0);
  EXPECT_GT(caps.height, 0);
  EXPECT_EQ(kFrameRate, caps.frame_rate);
  EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
  EXPECT_FALSE(caps.interlaced);

  EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}

// Test that screen capturer can handle resolution change without crashing.
TEST_F(ScreenCaptureDeviceTest, ScreenResolutionChange) {
  FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();

  ScreenCaptureDevice capture_device(
      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
  capture_device.SetScreenCapturerForTest(
      scoped_ptr<webrtc::ScreenCapturer>(mock_capturer));

  media::VideoCaptureCapability caps;
  base::WaitableEvent done_event(false, false);
  int frame_size;

  MockFrameObserver frame_observer;
  EXPECT_CALL(frame_observer, OnFrameInfo(_))
      .WillOnce(SaveArg<0>(&caps));
  EXPECT_CALL(frame_observer, OnError())
      .Times(0);
  EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
      .WillRepeatedly(DoAll(
          SaveArg<1>(&frame_size),
          InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));

  capture_device.Allocate(kTestFrameWidth1, kTestFrameHeight1,
                          kFrameRate, &frame_observer);
  capture_device.Start();
  // Capture first frame.
  EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
  done_event.Reset();
  // Capture second frame.
  EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
  capture_device.Stop();
  capture_device.DeAllocate();

  EXPECT_EQ(kTestFrameWidth1, caps.width);
  EXPECT_EQ(kTestFrameHeight1, caps.height);
  EXPECT_EQ(kFrameRate, caps.frame_rate);
  EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
  EXPECT_FALSE(caps.interlaced);

  EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}

}  // namespace content
<commit_msg>media: Use a FakeScreenCapturer for a test.<commit_after>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/renderer_host/media/screen_capture_device.h"

#include "base/basictypes.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::InvokeWithoutArgs;
using ::testing::SaveArg;

namespace content {

namespace {

const int kTestFrameWidth1 = 100;
const int kTestFrameHeight1 = 100;
const int kTestFrameWidth2 = 200;
const int kTestFrameHeight2 = 150;
const int kBufferSize = kTestFrameWidth2 * kTestFrameHeight2 * 4;

const int kFrameRate = 30;

class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
 public:
  MOCK_METHOD0(ReserveOutputBuffer, scoped_refptr<media::VideoFrame>());
  MOCK_METHOD0(OnError, void());
  MOCK_METHOD1(OnFrameInfo, void(const media::VideoCaptureCapability& info));
  MOCK_METHOD6(OnIncomingCapturedFrame, void(const uint8* data,
                                             int length,
                                             base::Time timestamp,
                                             int rotation,
                                             bool flip_vert,
                                             bool flip_horiz));
  MOCK_METHOD2(OnIncomingCapturedVideoFrame,
      void(const scoped_refptr<media::VideoFrame>& frame,
           base::Time timestamp));
};

// TODO(sergeyu): Move this to a separate file where it can be reused.
class FakeScreenCapturer : public webrtc::ScreenCapturer {
 public:
  FakeScreenCapturer()
      : callback_(NULL),
        frame_index_(0) {
  }
  virtual ~FakeScreenCapturer() {}

  // VideoFrameCapturer interface.
  virtual void Start(Callback* callback) OVERRIDE {
    callback_ = callback;
  }

  virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE {
    webrtc::DesktopSize size;
    if (frame_index_ % 2 == 0) {
      size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1);
    } else {
      size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2);
    }
    frame_index_++;
    callback_->OnCaptureCompleted(new webrtc::BasicDesktopFrame(size));
  }

  virtual void SetMouseShapeObserver(
      MouseShapeObserver* mouse_shape_observer) OVERRIDE {
  }

 private:
  Callback* callback_;
  int frame_index_;
};

class ScreenCaptureDeviceTest : public testing::Test {
 public:
  virtual void SetUp() OVERRIDE {
    worker_pool_ = new base::SequencedWorkerPool(3, "TestCaptureThread");
  }

 protected:
  scoped_refptr<base::SequencedWorkerPool> worker_pool_;
};

}  // namespace

// There is currently no screen capturer implementation for ozone. So disable
// the test that uses a real screen-capturer instead of FakeScreenCapturer.
// http://crbug.com/260318
#if defined(USE_OZONE)
#define MAYBE_Capture DISABLED_Capture
#else
#define MAYBE_Capture Capture
#endif
TEST_F(ScreenCaptureDeviceTest, MAYBE_Capture) {
  ScreenCaptureDevice capture_device(
      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
  media::VideoCaptureCapability caps;
  base::WaitableEvent done_event(false, false);
  int frame_size;

  MockFrameObserver frame_observer;
  EXPECT_CALL(frame_observer, OnFrameInfo(_))
      .WillOnce(SaveArg<0>(&caps));
  EXPECT_CALL(frame_observer, OnError())
      .Times(0);
  EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
      .WillRepeatedly(DoAll(
          SaveArg<1>(&frame_size),
          InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));

  capture_device.Allocate(640, 480, kFrameRate, &frame_observer);
  capture_device.Start();
  EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
  capture_device.Stop();
  capture_device.DeAllocate();

  EXPECT_GT(caps.width, 0);
  EXPECT_GT(caps.height, 0);
  EXPECT_EQ(kFrameRate, caps.frame_rate);
  EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
  EXPECT_FALSE(caps.interlaced);

  EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}

// Test that screen capturer can handle resolution change without crashing.
TEST_F(ScreenCaptureDeviceTest, ScreenResolutionChange) {
  FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();

  ScreenCaptureDevice capture_device(
      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
  capture_device.SetScreenCapturerForTest(
      scoped_ptr<webrtc::ScreenCapturer>(mock_capturer));

  media::VideoCaptureCapability caps;
  base::WaitableEvent done_event(false, false);
  int frame_size;

  MockFrameObserver frame_observer;
  EXPECT_CALL(frame_observer, OnFrameInfo(_))
      .WillOnce(SaveArg<0>(&caps));
  EXPECT_CALL(frame_observer, OnError())
      .Times(0);
  EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
      .WillRepeatedly(DoAll(
          SaveArg<1>(&frame_size),
          InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));

  capture_device.Allocate(kTestFrameWidth1, kTestFrameHeight1,
                          kFrameRate, &frame_observer);
  capture_device.Start();
  // Capture first frame.
  EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
  done_event.Reset();
  // Capture second frame.
  EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
  capture_device.Stop();
  capture_device.DeAllocate();

  EXPECT_EQ(kTestFrameWidth1, caps.width);
  EXPECT_EQ(kTestFrameHeight1, caps.height);
  EXPECT_EQ(kFrameRate, caps.frame_rate);
  EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
  EXPECT_FALSE(caps.interlaced);

  EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}

}  // namespace content
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cursor.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 12:16:20 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _SV_TIMER_HXX
#include <timer.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <settings.hxx>
#endif
#ifndef _SV_WINDOW_HXX
#include <window.hxx>
#endif
#ifndef _SV_WINDOW_H
#include <window.h>
#endif
#ifndef _TL_POLY_HXX
#include <tools/poly.hxx>
#endif
#ifndef _SV_CURSOR_HXX
#include <cursor.hxx>
#endif

// =======================================================================

struct ImplCursorData
{
    AutoTimer       maTimer;            // Timer
    Point           maPixPos;           // Pixel-Position
    Point           maPixRotOff;        // Pixel-Offset-Position
    Size            maPixSize;          // Pixel-Size
    long            mnPixSlant;         // Pixel-Slant
    short           mnOrientation;      // Pixel-Orientation
    unsigned char   mnDirection;        // indicates writing direction
    USHORT          mnStyle;            // Cursor-Style
    BOOL            mbCurVisible;       // Ist Cursor aktuell sichtbar
    Window*         mpWindow;           // Zugeordnetes Windows
};

// =======================================================================

static void ImplCursorInvert( ImplCursorData* pData )
{
    Window* pWindow  = pData->mpWindow;
    BOOL    bMapMode = pWindow->IsMapModeEnabled();
    pWindow->EnableMapMode( FALSE );
    USHORT nInvertStyle;
    if ( pData->mnStyle & CURSOR_SHADOW )
        nInvertStyle = INVERT_50;
    else
        nInvertStyle = 0;

    Rectangle aRect( pData->maPixPos, pData->maPixSize );
    if ( pData->mnDirection || pData->mnOrientation || pData->mnPixSlant )
    {
        Polygon aPoly( aRect );
        if( aPoly.GetSize() == 5 )
        {
            aPoly[1].X() += 1;  // include the right border
            aPoly[2].X() += 1;
            if ( pData->mnPixSlant )
            {
                Point aPoint = aPoly.GetPoint( 0 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 0 );
                aPoly.SetPoint( aPoint, 4 );
                aPoint = aPoly.GetPoint( 1 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 1 );
            }

            // apply direction flag after slant to use the correct shape
            if ( pData->mnDirection )
            {
                Point pAry[7];
                int delta = 3*aRect.getWidth()+1;
                if( pData->mnDirection == CURSOR_DIRECTION_LTR )
                {
                    // left-to-right
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = pAry[1];
                    pAry[2].X() += delta;
                    pAry[3] =  pAry[1];
                    pAry[3].Y() += delta;
                    pAry[4] = aPoly.GetPoint( 2 );
                    pAry[5] = aPoly.GetPoint( 3 );
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                else if( pData->mnDirection == CURSOR_DIRECTION_RTL )
                {
                    // right-to-left
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = aPoly.GetPoint( 2 );
                    pAry[3] = aPoly.GetPoint( 3 );
                    pAry[4] = pAry[0];
                    pAry[4].Y() += delta;
                    pAry[5] =  pAry[0];
                    pAry[5].X() -= delta;
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                aPoly = Polygon( 7, pAry);
            }

            if ( pData->mnOrientation )
                aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
            pWindow->Invert( aPoly, nInvertStyle );
        }
    }
    else
        pWindow->Invert( aRect, nInvertStyle );
    pWindow->EnableMapMode( bMapMode );
}

// -----------------------------------------------------------------------

void Cursor::ImplDraw()
{
    if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
    {
        Window* pWindow         = mpData->mpWindow;
        mpData->maPixPos        = pWindow->LogicToPixel( maPos );
        mpData->maPixSize       = pWindow->LogicToPixel( maSize );
        mpData->mnPixSlant      = pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
        mpData->mnOrientation   = mnOrientation;
        mpData->mnDirection     = mnDirection;
        long nOffsetY           = pWindow->LogicToPixel( Size( 0, mnOffsetY ) ).Height();

        // Position um den Offset korrigieren
        mpData->maPixPos.Y() -= nOffsetY;
        mpData->maPixRotOff = mpData->maPixPos;
        mpData->maPixRotOff.Y() += nOffsetY;

        // Wenn groesse 0 ist, nehmen wir die breite, die in den
        // Settings eingestellt ist
        if ( !mpData->maPixSize.Width() )
            mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();

        // Ausgabeflaeche berechnen und ausgeben
        ImplCursorInvert( mpData );
        mpData->mbCurVisible = TRUE;
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplRestore()
{
    if ( mpData && mpData->mbCurVisible )
    {
        ImplCursorInvert( mpData );
        mpData->mbCurVisible = FALSE;
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplShow( BOOL bDrawDirect )
{
    if ( mbVisible )
    {
        Window* pWindow;
        if ( mpWindow )
            pWindow = mpWindow;
        else
        {
            // Gibt es ein aktives Fenster und ist der Cursor in dieses Fenster
            // selektiert, dann zeige den Cursor an
            pWindow = Application::GetFocusWindow();
            if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint
                || !pWindow->mpWindowImpl->mpFrameData->mbHasFocus )
                pWindow = NULL;
        }

        if ( pWindow )
        {
            if ( !mpData )
            {
                mpData = new ImplCursorData;
                mpData->mbCurVisible = FALSE;
                mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
            }

            mpData->mpWindow    = pWindow;
            mpData->mnStyle     = mnStyle;
            if ( bDrawDirect )
                ImplDraw();

            if ( !mpWindow )
            {
                mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
                if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                    mpData->maTimer.Start();
                else if ( !mpData->mbCurVisible )
                    ImplDraw();
            }
        }
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplHide()
{
    if ( mpData && mpData->mpWindow )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        mpData->maTimer.Stop();
        mpData->mpWindow = NULL;
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplNew()
{
    if ( mbVisible && mpData && mpData->mpWindow )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        ImplDraw();
        if ( !mpWindow )
        {
            if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                mpData->maTimer.Start();
        }
    }
}

// -----------------------------------------------------------------------

IMPL_LINK( Cursor, ImplTimerHdl, AutoTimer*, EMPTYARG )
{
    if ( mpData->mbCurVisible )
        ImplRestore();
    else
        ImplDraw();
    return 0;
}

// =======================================================================

Cursor::Cursor()
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = 0;
    mnOffsetY       = 0;
    mnOrientation   = 0;
    mnDirection     = 0;
    mnStyle         = 0;
    mbVisible       = FALSE;
}

// -----------------------------------------------------------------------

Cursor::Cursor( const Cursor& rCursor ) :
    maSize( rCursor.maSize ),
    maPos( rCursor.maPos )
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mnStyle         = 0;
    mbVisible       = rCursor.mbVisible;
}

// -----------------------------------------------------------------------

Cursor::~Cursor()
{
    if ( mpData )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        delete mpData;
    }
}

// -----------------------------------------------------------------------

void Cursor::SetStyle( USHORT nStyle )
{
    if ( mnStyle != nStyle )
    {
        mnStyle = nStyle;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::Show()
{
    if ( !mbVisible )
    {
        mbVisible = TRUE;
        ImplShow();
    }
}

// -----------------------------------------------------------------------

void Cursor::Hide()
{
    if ( mbVisible )
    {
        mbVisible = FALSE;
        ImplHide();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetWindow( Window* pWindow )
{
    if ( mpWindow != pWindow )
    {
        mpWindow = pWindow;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetPos( const Point& rPoint )
{
    if ( maPos != rPoint )
    {
        maPos = rPoint;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetOffsetY( long nNewOffsetY )
{
    if ( mnOffsetY != nNewOffsetY )
    {
        mnOffsetY = nNewOffsetY;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetSize( const Size& rSize )
{
    if ( maSize != rSize )
    {
        maSize = rSize;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetWidth( long nNewWidth )
{
    if ( maSize.Width() != nNewWidth )
    {
        maSize.Width() = nNewWidth;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetHeight( long nNewHeight )
{
    if ( maSize.Height() != nNewHeight )
    {
        maSize.Height() = nNewHeight;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetSlant( long nNewSlant )
{
    if ( mnSlant != nNewSlant )
    {
        mnSlant = nNewSlant;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetOrientation( short nNewOrientation )
{
    if ( mnOrientation != nNewOrientation )
    {
        mnOrientation = nNewOrientation;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetDirection( unsigned char nNewDirection )
{
    if ( mnDirection != nNewDirection )
    {
        mnDirection = nNewDirection;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

Cursor& Cursor::operator=( const Cursor& rCursor )
{
    maPos           = rCursor.maPos;
    maSize          = rCursor.maSize;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mbVisible       = rCursor.mbVisible;
    ImplNew();

    return *this;
}

// -----------------------------------------------------------------------

BOOL Cursor::operator==( const Cursor& rCursor ) const
{
    if ( (maPos         == rCursor.maPos)           &&
         (maSize        == rCursor.maSize)          &&
         (mnSlant       == rCursor.mnSlant)         &&
         (mnOrientation == rCursor.mnOrientation)   &&
         (mnDirection   == rCursor.mnDirection)     &&
         (mbVisible     == rCursor.mbVisible) )
        return TRUE;
    else
        return FALSE;
}
<commit_msg>INTEGRATION: CWS vgbugs07 (1.10.240); FILE MERGED 2007/06/04 13:29:46 vg 1.10.240.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cursor.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 20:28:56 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _SV_TIMER_HXX
#include <vcl/timer.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <vcl/settings.hxx>
#endif
#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif
#ifndef _SV_WINDOW_H
#include <window.h>
#endif
#ifndef _TL_POLY_HXX
#include <tools/poly.hxx>
#endif
#ifndef _SV_CURSOR_HXX
#include <vcl/cursor.hxx>
#endif

// =======================================================================

struct ImplCursorData
{
    AutoTimer       maTimer;            // Timer
    Point           maPixPos;           // Pixel-Position
    Point           maPixRotOff;        // Pixel-Offset-Position
    Size            maPixSize;          // Pixel-Size
    long            mnPixSlant;         // Pixel-Slant
    short           mnOrientation;      // Pixel-Orientation
    unsigned char   mnDirection;        // indicates writing direction
    USHORT          mnStyle;            // Cursor-Style
    BOOL            mbCurVisible;       // Ist Cursor aktuell sichtbar
    Window*         mpWindow;           // Zugeordnetes Windows
};

// =======================================================================

static void ImplCursorInvert( ImplCursorData* pData )
{
    Window* pWindow  = pData->mpWindow;
    BOOL    bMapMode = pWindow->IsMapModeEnabled();
    pWindow->EnableMapMode( FALSE );
    USHORT nInvertStyle;
    if ( pData->mnStyle & CURSOR_SHADOW )
        nInvertStyle = INVERT_50;
    else
        nInvertStyle = 0;

    Rectangle aRect( pData->maPixPos, pData->maPixSize );
    if ( pData->mnDirection || pData->mnOrientation || pData->mnPixSlant )
    {
        Polygon aPoly( aRect );
        if( aPoly.GetSize() == 5 )
        {
            aPoly[1].X() += 1;  // include the right border
            aPoly[2].X() += 1;
            if ( pData->mnPixSlant )
            {
                Point aPoint = aPoly.GetPoint( 0 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 0 );
                aPoly.SetPoint( aPoint, 4 );
                aPoint = aPoly.GetPoint( 1 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 1 );
            }

            // apply direction flag after slant to use the correct shape
            if ( pData->mnDirection )
            {
                Point pAry[7];
                int delta = 3*aRect.getWidth()+1;
                if( pData->mnDirection == CURSOR_DIRECTION_LTR )
                {
                    // left-to-right
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = pAry[1];
                    pAry[2].X() += delta;
                    pAry[3] =  pAry[1];
                    pAry[3].Y() += delta;
                    pAry[4] = aPoly.GetPoint( 2 );
                    pAry[5] = aPoly.GetPoint( 3 );
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                else if( pData->mnDirection == CURSOR_DIRECTION_RTL )
                {
                    // right-to-left
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = aPoly.GetPoint( 2 );
                    pAry[3] = aPoly.GetPoint( 3 );
                    pAry[4] = pAry[0];
                    pAry[4].Y() += delta;
                    pAry[5] =  pAry[0];
                    pAry[5].X() -= delta;
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                aPoly = Polygon( 7, pAry);
            }

            if ( pData->mnOrientation )
                aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
            pWindow->Invert( aPoly, nInvertStyle );
        }
    }
    else
        pWindow->Invert( aRect, nInvertStyle );
    pWindow->EnableMapMode( bMapMode );
}

// -----------------------------------------------------------------------

void Cursor::ImplDraw()
{
    if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
    {
        Window* pWindow         = mpData->mpWindow;
        mpData->maPixPos        = pWindow->LogicToPixel( maPos );
        mpData->maPixSize       = pWindow->LogicToPixel( maSize );
        mpData->mnPixSlant      = pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
        mpData->mnOrientation   = mnOrientation;
        mpData->mnDirection     = mnDirection;
        long nOffsetY           = pWindow->LogicToPixel( Size( 0, mnOffsetY ) ).Height();

        // Position um den Offset korrigieren
        mpData->maPixPos.Y() -= nOffsetY;
        mpData->maPixRotOff = mpData->maPixPos;
        mpData->maPixRotOff.Y() += nOffsetY;

        // Wenn groesse 0 ist, nehmen wir die breite, die in den
        // Settings eingestellt ist
        if ( !mpData->maPixSize.Width() )
            mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();

        // Ausgabeflaeche berechnen und ausgeben
        ImplCursorInvert( mpData );
        mpData->mbCurVisible = TRUE;
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplRestore()
{
    if ( mpData && mpData->mbCurVisible )
    {
        ImplCursorInvert( mpData );
        mpData->mbCurVisible = FALSE;
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplShow( BOOL bDrawDirect )
{
    if ( mbVisible )
    {
        Window* pWindow;
        if ( mpWindow )
            pWindow = mpWindow;
        else
        {
            // Gibt es ein aktives Fenster und ist der Cursor in dieses Fenster
            // selektiert, dann zeige den Cursor an
            pWindow = Application::GetFocusWindow();
            if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint
                || !pWindow->mpWindowImpl->mpFrameData->mbHasFocus )
                pWindow = NULL;
        }

        if ( pWindow )
        {
            if ( !mpData )
            {
                mpData = new ImplCursorData;
                mpData->mbCurVisible = FALSE;
                mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
            }

            mpData->mpWindow    = pWindow;
            mpData->mnStyle     = mnStyle;
            if ( bDrawDirect )
                ImplDraw();

            if ( !mpWindow )
            {
                mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
                if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                    mpData->maTimer.Start();
                else if ( !mpData->mbCurVisible )
                    ImplDraw();
            }
        }
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplHide()
{
    if ( mpData && mpData->mpWindow )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        mpData->maTimer.Stop();
        mpData->mpWindow = NULL;
    }
}

// -----------------------------------------------------------------------

void Cursor::ImplNew()
{
    if ( mbVisible && mpData && mpData->mpWindow )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        ImplDraw();
        if ( !mpWindow )
        {
            if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                mpData->maTimer.Start();
        }
    }
}

// -----------------------------------------------------------------------

IMPL_LINK( Cursor, ImplTimerHdl, AutoTimer*, EMPTYARG )
{
    if ( mpData->mbCurVisible )
        ImplRestore();
    else
        ImplDraw();
    return 0;
}

// =======================================================================

Cursor::Cursor()
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = 0;
    mnOffsetY       = 0;
    mnOrientation   = 0;
    mnDirection     = 0;
    mnStyle         = 0;
    mbVisible       = FALSE;
}

// -----------------------------------------------------------------------

Cursor::Cursor( const Cursor& rCursor ) :
    maSize( rCursor.maSize ),
    maPos( rCursor.maPos )
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mnStyle         = 0;
    mbVisible       = rCursor.mbVisible;
}

// -----------------------------------------------------------------------

Cursor::~Cursor()
{
    if ( mpData )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        delete mpData;
    }
}

// -----------------------------------------------------------------------

void Cursor::SetStyle( USHORT nStyle )
{
    if ( mnStyle != nStyle )
    {
        mnStyle = nStyle;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::Show()
{
    if ( !mbVisible )
    {
        mbVisible = TRUE;
        ImplShow();
    }
}

// -----------------------------------------------------------------------

void Cursor::Hide()
{
    if ( mbVisible )
    {
        mbVisible = FALSE;
        ImplHide();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetWindow( Window* pWindow )
{
    if ( mpWindow != pWindow )
    {
        mpWindow = pWindow;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetPos( const Point& rPoint )
{
    if ( maPos != rPoint )
    {
        maPos = rPoint;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetOffsetY( long nNewOffsetY )
{
    if ( mnOffsetY != nNewOffsetY )
    {
        mnOffsetY = nNewOffsetY;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetSize( const Size& rSize )
{
    if ( maSize != rSize )
    {
        maSize = rSize;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetWidth( long nNewWidth )
{
    if ( maSize.Width() != nNewWidth )
    {
        maSize.Width() = nNewWidth;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetHeight( long nNewHeight )
{
    if ( maSize.Height() != nNewHeight )
    {
        maSize.Height() = nNewHeight;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetSlant( long nNewSlant )
{
    if ( mnSlant != nNewSlant )
    {
        mnSlant = nNewSlant;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetOrientation( short nNewOrientation )
{
    if ( mnOrientation != nNewOrientation )
    {
        mnOrientation = nNewOrientation;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

void Cursor::SetDirection( unsigned char nNewDirection )
{
    if ( mnDirection != nNewDirection )
    {
        mnDirection = nNewDirection;
        ImplNew();
    }
}

// -----------------------------------------------------------------------

Cursor& Cursor::operator=( const Cursor& rCursor )
{
    maPos           = rCursor.maPos;
    maSize          = rCursor.maSize;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mbVisible       = rCursor.mbVisible;
    ImplNew();

    return *this;
}

// -----------------------------------------------------------------------

BOOL Cursor::operator==( const Cursor& rCursor ) const
{
    if ( (maPos         == rCursor.maPos)           &&
         (maSize        == rCursor.maSize)          &&
         (mnSlant       == rCursor.mnSlant)         &&
         (mnOrientation == rCursor.mnOrientation)   &&
         (mnDirection   == rCursor.mnDirection)     &&
         (mbVisible     == rCursor.mbVisible) )
        return TRUE;
    else
        return FALSE;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: salvd.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-27 17:58:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#define _SV_SALVD_CXX

// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <salunx.h>

#ifndef _SV_SALDATA_HXX
#include <saldata.hxx>
#endif
#ifndef _SV_SALDISP_HXX
#include <saldisp.hxx>
#endif
#ifndef _SV_SALINST_HXX
#include <salinst.hxx>
#endif
#ifndef _SV_SALGDI_HXX
#include <salgdi.hxx>
#endif
#ifndef _SV_SALVD_HXX
#include <salvd.hxx>
#endif

// -=-= SalInstance =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalVirtualDevice* SalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
                                                    long nDX, long nDY,
                                                    USHORT nBitCount )
{
    SalVirtualDevice *pVDev = new SalVirtualDevice();
    if( !nBitCount && pGraphics )
        nBitCount = pGraphics->GetBitCount();
    if( !pVDev->maVirDevData.Init( pGraphics->maGraphicsData.GetDisplay(),
                                   nDX, nDY, nBitCount ) )
    {
        delete pVDev;
        return NULL;
    }

    pVDev->maVirDevData.InitGraphics( pVDev, pGraphics );
    return pVDev;
}

void SalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
{ delete pDevice; }

// -=-= SalGraphicsData =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalGraphicsData::Init( SalVirtualDevice *pDevice,
                                  SalGraphics      *pGraphics )
{
    SalDisplay *pDisplay  = pDevice->maVirDevData.GetDisplay();

    int nVisualDepth = pDisplay->GetColormap().GetVisual()->GetDepth();
    int nDeviceDepth = pDevice->maVirDevData.GetDepth();

    if( nDeviceDepth == nVisualDepth )
        xColormap_ = &pDisplay->GetColormap();
    else
    if( nDeviceDepth == 1 )
        xColormap_ = new SalColormap();

    hDrawable_   = pDevice->maVirDevData.GetDrawable();
    m_pVDev      = pDevice;
    m_pFrame     = NULL;

    bWindow_     = pDisplay->IsDisplay();
    bVirDev_     = TRUE;

    nPenPixel_   = GetPixel( nPenColor_ );
    nTextPixel_  = GetPixel( nTextColor_ );
    nBrushPixel_ = GetPixel( nBrushColor_ );
}

// -=-= SalVirDevData / SalVirtualDevice -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
BOOL SalVirDevData::Init( SalDisplay *pDisplay,
                                long nDX, long nDY,
                                USHORT nBitCount )
{
    pDisplay_               = pDisplay;
    pGraphics_              = new SalGraphicsLayout();
    pGraphics_->SetLayout( 0 ); // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
    nDX_                    = nDX;
    nDY_                    = nDY;
    nDepth_                 = nBitCount;

    hDrawable_              = XCreatePixmap( GetXDisplay(),
                                     pDisplay_->GetDrawable(),
                                     nDX_, nDY_,
                                     GetDepth() );

    return hDrawable_ != None ? TRUE : FALSE;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
inline SalVirDevData::SalVirDevData()
{
    pDisplay_               = (SalDisplay*)ILLEGAL_POINTER;
    pGraphics_              = NULL;
    hDrawable_              = None;
    nDX_                    = 0;
    nDY_                    = 0;
    nDepth_                 = 0;
    bGraphics_              = FALSE;
}

SalVirtualDevice::SalVirtualDevice() {}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
inline SalVirDevData::~SalVirDevData()
{
    if( pGraphics_ )
    {
        pGraphics_->maGraphicsData.DeInit();
        delete pGraphics_;
    }

    if( GetDrawable() )
        XFreePixmap( GetXDisplay(), GetDrawable() );
}

SalVirtualDevice::~SalVirtualDevice()
{}

// -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#define _GetDrawable()   maVirDevData.GetDrawable()
#define _GetDisplay()    maVirDevData.GetDisplay()
#define _GetXDisplay()   maVirDevData.GetXDisplay()
#define _GetDepth()      maVirDevData.nDepth_

// -=-= SalVirtualDevice -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalGraphics* SalVirtualDevice::GetGraphics()
{
    if( maVirDevData.bGraphics_ )
        return NULL;

    if( maVirDevData.pGraphics_ )
        maVirDevData.bGraphics_ = TRUE;

    return maVirDevData.pGraphics_;
}

void SalVirtualDevice::ReleaseGraphics( SalGraphics* )
{ maVirDevData.bGraphics_ = FALSE; }

BOOL SalVirtualDevice::SetSize( long nDX, long nDY )
{
    if( !nDX ) nDX = 1;
    if( !nDY ) nDY = 1;

    Pixmap h = XCreatePixmap( _GetXDisplay(),
                              maVirDevData.pDisplay_->GetDrawable(),
                              nDX, nDY, _GetDepth() );

    if( !h )
    {
        if( !_GetDrawable() )
        {
            maVirDevData.hDrawable_ = XCreatePixmap( _GetXDisplay(),
                                         maVirDevData.pDisplay_->GetDrawable(),
                                         1, 1, _GetDepth() );
            maVirDevData.nDX_ = 1;
            maVirDevData.nDY_ = 1;
        }
        return FALSE;
    }

    if( _GetDrawable() )
        XFreePixmap( _GetXDisplay(), _GetDrawable() );
    maVirDevData.hDrawable_ = h;

    maVirDevData.nDX_ = nDX;
    maVirDevData.nDY_ = nDY;

    if( maVirDevData.pGraphics_ )
        maVirDevData.InitGraphics( this, maVirDevData.pGraphics_ );

    return TRUE;
}

<commit_msg>INTEGRATION: CWS vclplug (1.4.188); FILE MERGED 2003/10/22 13:50:09 pl 1.4.188.2: #21232# removed SalGraphicsLayout, functionality now in SalGraphics itself 2003/10/21 15:54:07 pl 1.4.188.1: #i21232# first round of virtualizing the Sal classes, Unix works, Windows to come<commit_after>/*************************************************************************
 *
 *  $RCSfile: salvd.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2003-11-18 14:46:37 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#define _SV_SALVD_CXX

// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <salunx.h>

#ifndef _SV_SALDATA_HXX
#include <saldata.hxx>
#endif
#ifndef _SV_SALDISP_HXX
#include <saldisp.hxx>
#endif
#ifndef _SV_SALINST_HXX
#include <salinst.hxx>
#endif
#ifndef _SV_SALGDI_H
#include <salgdi.h>
#endif
#ifndef _SV_SALVD_H
#include <salvd.h>
#endif

// -=-= SalInstance =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalVirtualDevice* X11SalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
                                                       long nDX, long nDY,
                                                       USHORT nBitCount )
{
    X11SalVirtualDevice *pVDev = new X11SalVirtualDevice();
    if( !nBitCount && pGraphics )
        nBitCount = pGraphics->GetBitCount();
    if( !pVDev->Init( GetSalData()->GetDefDisp(), nDX, nDY, nBitCount ) )
    {
        delete pVDev;
        return NULL;
    }

    pVDev->InitGraphics( pVDev );
    return pVDev;
}

void X11SalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
{
    delete pDevice;
}

// -=-= SalGraphicsData =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalGraphics::Init( X11SalVirtualDevice *pDevice )
{
    SalDisplay *pDisplay  = pDevice->GetDisplay();

    int nVisualDepth = pDisplay->GetColormap().GetVisual()->GetDepth();
    int nDeviceDepth = pDevice->GetDepth();

    if( nDeviceDepth == nVisualDepth )
        xColormap_ = &pDisplay->GetColormap();
    else
    if( nDeviceDepth == 1 )
        xColormap_ = new SalColormap();

    hDrawable_   = pDevice->GetDrawable();
    m_pVDev      = pDevice;
    m_pFrame     = NULL;

    bWindow_     = pDisplay->IsDisplay();
    bVirDev_     = TRUE;

    nPenPixel_   = GetPixel( nPenColor_ );
    nTextPixel_  = GetPixel( nTextColor_ );
    nBrushPixel_ = GetPixel( nBrushColor_ );
}

// -=-= SalVirDevData / SalVirtualDevice -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
BOOL X11SalVirtualDevice::Init( SalDisplay *pDisplay,
                                long nDX, long nDY,
                                USHORT nBitCount )
{
    pDisplay_               = pDisplay;
    pGraphics_              = new X11SalGraphics();
    pGraphics_->SetLayout( 0 ); // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
    nDX_                    = nDX;
    nDY_                    = nDY;
    nDepth_                 = nBitCount;

    hDrawable_              = XCreatePixmap( GetXDisplay(),
                                     pDisplay_->GetDrawable(),
                                     nDX_, nDY_,
                                     GetDepth() );

    pGraphics_->Init( this );

    return hDrawable_ != None ? TRUE : FALSE;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
X11SalVirtualDevice::X11SalVirtualDevice()
{
    pDisplay_               = (SalDisplay*)ILLEGAL_POINTER;
    pGraphics_              = NULL;
    hDrawable_              = None;
    nDX_                    = 0;
    nDY_                    = 0;
    nDepth_                 = 0;
    bGraphics_              = FALSE;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
X11SalVirtualDevice::~X11SalVirtualDevice()
{
    if( pGraphics_ )
        delete pGraphics_;

    if( GetDrawable() )
        XFreePixmap( GetXDisplay(), GetDrawable() );
}

SalGraphics* X11SalVirtualDevice::GetGraphics()
{
    if( bGraphics_ )
        return NULL;

    if( pGraphics_ )
        bGraphics_ = TRUE;

    return pGraphics_;
}

void X11SalVirtualDevice::ReleaseGraphics( SalGraphics* )
{ bGraphics_ = FALSE; }

BOOL X11SalVirtualDevice::SetSize( long nDX, long nDY )
{
    if( !nDX ) nDX = 1;
    if( !nDY ) nDY = 1;

    Pixmap h = XCreatePixmap( GetXDisplay(),
                              pDisplay_->GetDrawable(),
                              nDX, nDY, nDepth_ );

    if( !h )
    {
        if( !GetDrawable() )
        {
            hDrawable_ = XCreatePixmap( GetXDisplay(),
                                        pDisplay_->GetDrawable(),
                                        1, 1, nDepth_ );
            nDX_ = 1;
            nDY_ = 1;
        }
        return FALSE;
    }

    if( GetDrawable() )
        XFreePixmap( GetXDisplay(), GetDrawable() );
    hDrawable_ = h;

    nDX_ = nDX;
    nDY_ = nDY;

    if( pGraphics_ )
        InitGraphics( this );

    return TRUE;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include <fstream>

//Image
#include "otbListSampleGenerator.h"

// ListSample
#include "itkListSample.h"
#include "itkVariableLengthVector.h"
#include "itkFixedArray.h"

// SVM estimator
#include "otbSVMSampleListModelEstimator.h"

// Statistic XML Reader
#include "otbStatisticsXMLFileReader.h"

// Validation
#include "otbSVMClassifier.h"
#include "otbConfusionMatrixCalculator.h"

// Normalize the samples
#include "otbShiftScaleSampleListFilter.h"

// List sample concatenation
#include "otbConcatenateSampleListFilter.h"

// Classification filter
#include "otbSVMImageClassificationFilter.h"

// Extract a ROI of the vectordata
#include "otbVectorDataIntoImageProjectionFilter.h"

namespace otb
{
namespace Wrapper
{

class ValidateSVMImagesClassifier: public Application
{

public:
  /** Standard class typedefs. */
  typedef ValidateSVMImagesClassifier Self;
  typedef Application Superclass;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self)
;

  itkTypeMacro(ValidateSVMImagesClassifier, otb::Application)
;

  typedef otb::Image<FloatVectorImageType::InternalPixelType, 2> ImageReaderType;

  typedef FloatVectorImageType::PixelType PixelType;
  typedef FloatVectorImageType VectorImageType;
  typedef FloatImageType ImageType;
  typedef Int32ImageType LabeledImageType;

  // Training vectordata
  typedef itk::VariableLengthVector<ImageType::PixelType> MeasurementType;

  // SampleList manipulation
  typedef otb::ListSampleGenerator<VectorImageType, VectorDataType> ListSampleGeneratorType;

  typedef ListSampleGeneratorType::ListSampleType ListSampleType;
  typedef ListSampleGeneratorType::LabelType LabelType;
  typedef ListSampleGeneratorType::ListLabelType LabelListSampleType;
  typedef otb::Statistics::ConcatenateSampleListFilter<ListSampleType> ConcatenateListSampleFilterType;
  typedef otb::Statistics::ConcatenateSampleListFilter<LabelListSampleType> ConcatenateLabelListSampleFilterType;

  // Statistic XML file Reader
  typedef otb::StatisticsXMLFileReader<MeasurementType> StatisticsReader;
  // Enhance List Sample
  typedef otb::Statistics::ShiftScaleSampleListFilter<ListSampleType, ListSampleType> ShiftScaleFilterType;

  /// Classification typedefs
  typedef otb::SVMImageClassificationFilter<VectorImageType, LabeledImageType> ClassificationFilterType;
  typedef ClassificationFilterType::Pointer ClassificationFilterPointerType;
  typedef ClassificationFilterType::ModelType ModelType;
  typedef ModelType::Pointer ModelPointerType;

  typedef otb::Functor::VariableLengthVectorToMeasurementVectorFunctor<MeasurementType> MeasurementVectorFunctorType;
  typedef otb::SVMSampleListModelEstimator<ListSampleType, LabelListSampleType, MeasurementVectorFunctorType>
      SVMEstimatorType;
  // Estimate performance on validation sample
  typedef otb::SVMClassifier<ListSampleType, LabelType::ValueType> ClassifierType;
  typedef otb::ConfusionMatrixCalculator<LabelListSampleType, LabelListSampleType> ConfusionMatrixCalculatorType;
  typedef ClassifierType::OutputType ClassifierOutputType;

 // Extract ROI and Project vectorData
 typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType, VectorImageType> VectorDataReprojectionType;

private:
  ValidateSVMImagesClassifier()
  {
    SetName("ValidateSVMImagesClassifier");
    SetDescription("Perform SVM validation from multiple input images and multiple vector data.");

    SetDocName("Validate SVM Images Classifier Application");
    SetDocLongDescription(
                          "This application performs SVM validation from multiple input images and multiple vector data.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");
    SetDocCLExample("otbApplicationLauncherCommandLine ValidateSVMImagesClassifier ${OTB-BIN}/bin"
      "--il ${OTB-Data}/Classification/QB_1_ortho.tif --vd  ${OTB-Data}/Classification/VectorData_QB1_bis.shp"
      " --imstat ${OTB-Data}/Baseline/OTB-Applications/Files/clImageStatisticsQB123.xml "
      " --svm  ${OTB-Data}/Baseline/OTB-Applications/Files/clsvmModelQB123.svm"
      " --out PerformanceEstimationQB123.txt ");
    AddDocTag(Tags::Learning);

  }

  virtual ~ValidateSVMImagesClassifier()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImageList, "il", "Input Image List");
    SetParameterDescription("il", "Input image list filename.");
    AddParameter(ParameterType_InputVectorDataList, "vd", "Vector Data List");
    SetParameterDescription("vd", "Vector Data of sample used to validate the estimator.");
    AddParameter(ParameterType_Filename, "dem", "DEM repository");
    SetParameterDescription("dem", "Path to DEM repository.");
    MandatoryOff("dem");
    AddParameter(ParameterType_Filename, "imstat", "XML image statistics file");
    MandatoryOff("imstat");
    SetParameterDescription("imstat", "filename of an XML file containing mean and standard deviation of input images.");
    AddParameter(ParameterType_Filename, "svm", "SVM validation filename");
    SetParameterDescription("svm",
                            "SVM model to validate its performances (given by TrainSVMImagesClassification output for instance).");
    AddParameter(ParameterType_Filename, "out", "Output filename");
    SetParameterDescription("out", "Filename, which will contain the performance of the SVM model.");
    MandatoryOff("out");
    SetParameterRole("out", Role_Output);
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    GetLogger()->Debug("Entering DoExecute\n");
    //Create training and validation for list samples and label list samples
    ConcatenateLabelListSampleFilterType::Pointer
        concatenateTrainingLabels = ConcatenateLabelListSampleFilterType::New();
    ConcatenateListSampleFilterType::Pointer concatenateTrainingSamples = ConcatenateListSampleFilterType::New();
    ConcatenateLabelListSampleFilterType::Pointer
        concatenateValidationLabels = ConcatenateLabelListSampleFilterType::New();
    ConcatenateListSampleFilterType::Pointer concatenateValidationSamples = ConcatenateListSampleFilterType::New();

    MeasurementType meanMeasurementVector;
    MeasurementType stddevMeasurementVector;

    //--------------------------
    // Load measurements from images
    unsigned int nbBands = 0;
    //Iterate over all input images

    FloatVectorImageListType* imageList = GetParameterImageList("il");
    VectorDataListType* vectorDataList = GetParameterVectorDataList("vd");

    //Iterate over all input images
    for (unsigned int imgIndex = 0; imgIndex < imageList->Size(); ++imgIndex)
      {
      FloatVectorImageType::Pointer image = imageList->GetNthElement(imgIndex);
      image->UpdateOutputInformation();

      if (imgIndex == 0)
        {
        nbBands = image->GetNumberOfComponentsPerPixel();
        }

      // read the Vectordata
      VectorDataType::Pointer vectorData = vectorDataList->GetNthElement(imgIndex);
      vectorData->Update();

      VectorDataReprojectionType::Pointer vdreproj = VectorDataReprojectionType::New();
      vdreproj->SetInputImage(image);
      vdreproj->SetInput(vectorData);
      vdreproj->SetUseOutputSpacingAndOriginFromImage(false);

      // Configure DEM directory
      if (IsParameterEnabled("dem"))
        {
        vdreproj->SetDEMDirectory(GetParameterString("dem"));
        }
      else
        {
        if (otb::ConfigurationFile::GetInstance()->IsValid())
          {
          vdreproj->SetDEMDirectory(otb::ConfigurationFile::GetInstance()->GetDEMDirectory());
          }
        }

      vdreproj->Update();

      //Sample list generator
      ListSampleGeneratorType::Pointer sampleGenerator = ListSampleGeneratorType::New();

      //Set inputs of the sample generator
      //TODO the ListSampleGenerator perform UpdateOutputData over the input image (need a persistent implementation)
      sampleGenerator->SetInput(image);
      sampleGenerator->SetInputVectorData(vdreproj->GetOutput());
      sampleGenerator->SetValidationTrainingProportion(1.0); // All in validation

      sampleGenerator->SetClassKey("Class");

      sampleGenerator->Update();

      //Concatenate training and validation samples from the image
      concatenateValidationLabels->AddInput(sampleGenerator->GetValidationListLabel());
      concatenateValidationSamples->AddInput(sampleGenerator->GetValidationListSample());
      }

    // Update
    concatenateValidationSamples->Update();
    concatenateValidationLabels->Update();

    if (IsParameterEnabled("imstat"))
      {
      StatisticsReader::Pointer statisticsReader = StatisticsReader::New();
      statisticsReader->SetFileName(GetParameterString("imstat"));
      meanMeasurementVector = statisticsReader->GetStatisticVectorByName("mean");
      stddevMeasurementVector = statisticsReader->GetStatisticVectorByName("stddev");
      }
    else
      {
      meanMeasurementVector.SetSize(nbBands);
      meanMeasurementVector.Fill(0.);
      stddevMeasurementVector.SetSize(nbBands);
      stddevMeasurementVector.Fill(1.);
      }

    ShiftScaleFilterType::Pointer validationShiftScaleFilter = ShiftScaleFilterType::New();
    validationShiftScaleFilter->SetInput(concatenateValidationSamples->GetOutput());
    validationShiftScaleFilter->SetShifts(meanMeasurementVector);
    validationShiftScaleFilter->SetScales(stddevMeasurementVector);
    validationShiftScaleFilter->Update();
    //--------------------------
    // split the data set into training/validation set
    ListSampleType::Pointer validationListSample = validationShiftScaleFilter->GetOutputSampleList();
    LabelListSampleType::Pointer validationLabeledListSample = concatenateValidationLabels->GetOutputSampleList();

    otbAppLogINFO("Size of validation set: " << validationListSample->Size());
    otbAppLogINFO("Size of labeled validation set: " << validationLabeledListSample->Size());

    //--------------------------
    // Load svm model
    ModelPointerType modelSVM = ModelType::New();
    modelSVM->LoadModel(GetParameterString("svm").c_str());

    //--------------------------
    // Performances estimation
    ClassifierType::Pointer validationClassifier = ClassifierType::New();
    validationClassifier->SetSample(validationListSample);
    validationClassifier->SetNumberOfClasses(modelSVM->GetNumberOfClasses());
    validationClassifier->SetModel(modelSVM);
    validationClassifier->Update();

    // Estimate performances
    ClassifierOutputType::ConstIterator it = validationClassifier->GetOutput()->Begin();
    ClassifierOutputType::ConstIterator itEnd = validationClassifier->GetOutput()->End();

    LabelListSampleType::Pointer classifierListLabel = LabelListSampleType::New();

    while (it != itEnd)
      {
      // Due to a bug in SVMClassifier, outlier in one-class SVM are labeled with unsigned int max
      classifierListLabel->PushBack(
                                    it.GetClassLabel() == itk::NumericTraits<unsigned int>::max() ? 2
                                                                                : it.GetClassLabel());
      ++it;
      }

    ConfusionMatrixCalculatorType::Pointer confMatCalc = ConfusionMatrixCalculatorType::New();

    confMatCalc->SetReferenceLabels(validationLabeledListSample);
    confMatCalc->SetProducedLabels(classifierListLabel);

    confMatCalc->Update();

    otbAppLogINFO("*** SVM training performances ***\n" <<"Confusion matrix:\n" << confMatCalc->GetConfusionMatrix() << std::endl);

    for (unsigned int itClasses = 0; itClasses < modelSVM->GetNumberOfClasses(); itClasses++)
      {
      otbAppLogINFO("Precision of class [" << itClasses << "] vs all: " << confMatCalc->GetPrecisions()[itClasses] << std::endl);
      otbAppLogINFO("Recall of class [" << itClasses << "] vs all: " << confMatCalc->GetRecalls()[itClasses] << std::endl);
      otbAppLogINFO("F-score of class [" << itClasses << "] vs all: " << confMatCalc->GetFScores()[itClasses] << "\n" << std::endl);
      }
    otbAppLogINFO("Global performance, Kappa index: " << confMatCalc->GetKappaIndex() << std::endl);

    //--------------------------
    // Save output in a ascii file (if needed)
    if (IsParameterEnabled("out"))
      {
      std::ofstream file;
      file.open(GetParameterString("out").c_str());
      file << "Precision of the different class: " << confMatCalc->GetPrecisions() << std::endl;
      file << "Recall of the different class: " << confMatCalc->GetRecalls() << std::endl;
      file << "F-score of the different class: " << confMatCalc->GetFScores() << std::endl;
      file << "Kappa index: " << confMatCalc->GetKappaIndex() << std::endl;
      file.close();
      }
  }
};

} // end of namespace Wrapper
} // end of namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::ValidateSVMImagesClassifier)
<commit_msg>DOC:enrich ValidateSVMImagesClassifier documentation<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include <fstream>

//Image
#include "otbListSampleGenerator.h"

// ListSample
#include "itkListSample.h"
#include "itkVariableLengthVector.h"
#include "itkFixedArray.h"

// SVM estimator
#include "otbSVMSampleListModelEstimator.h"

// Statistic XML Reader
#include "otbStatisticsXMLFileReader.h"

// Validation
#include "otbSVMClassifier.h"
#include "otbConfusionMatrixCalculator.h"

// Normalize the samples
#include "otbShiftScaleSampleListFilter.h"

// List sample concatenation
#include "otbConcatenateSampleListFilter.h"

// Classification filter
#include "otbSVMImageClassificationFilter.h"

// Extract a ROI of the vectordata
#include "otbVectorDataIntoImageProjectionFilter.h"

namespace otb
{
namespace Wrapper
{

class ValidateSVMImagesClassifier: public Application
{

public:
  /** Standard class typedefs. */
  typedef ValidateSVMImagesClassifier Self;
  typedef Application Superclass;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self)
;

  itkTypeMacro(ValidateSVMImagesClassifier, otb::Application)
;

  typedef otb::Image<FloatVectorImageType::InternalPixelType, 2> ImageReaderType;

  typedef FloatVectorImageType::PixelType PixelType;
  typedef FloatVectorImageType VectorImageType;
  typedef FloatImageType ImageType;
  typedef Int32ImageType LabeledImageType;

  // Training vectordata
  typedef itk::VariableLengthVector<ImageType::PixelType> MeasurementType;

  // SampleList manipulation
  typedef otb::ListSampleGenerator<VectorImageType, VectorDataType> ListSampleGeneratorType;

  typedef ListSampleGeneratorType::ListSampleType ListSampleType;
  typedef ListSampleGeneratorType::LabelType LabelType;
  typedef ListSampleGeneratorType::ListLabelType LabelListSampleType;
  typedef otb::Statistics::ConcatenateSampleListFilter<ListSampleType> ConcatenateListSampleFilterType;
  typedef otb::Statistics::ConcatenateSampleListFilter<LabelListSampleType> ConcatenateLabelListSampleFilterType;

  // Statistic XML file Reader
  typedef otb::StatisticsXMLFileReader<MeasurementType> StatisticsReader;
  // Enhance List Sample
  typedef otb::Statistics::ShiftScaleSampleListFilter<ListSampleType, ListSampleType> ShiftScaleFilterType;

  /// Classification typedefs
  typedef otb::SVMImageClassificationFilter<VectorImageType, LabeledImageType> ClassificationFilterType;
  typedef ClassificationFilterType::Pointer ClassificationFilterPointerType;
  typedef ClassificationFilterType::ModelType ModelType;
  typedef ModelType::Pointer ModelPointerType;

  typedef otb::Functor::VariableLengthVectorToMeasurementVectorFunctor<MeasurementType> MeasurementVectorFunctorType;
  typedef otb::SVMSampleListModelEstimator<ListSampleType, LabelListSampleType, MeasurementVectorFunctorType>
      SVMEstimatorType;
  // Estimate performance on validation sample
  typedef otb::SVMClassifier<ListSampleType, LabelType::ValueType> ClassifierType;
  typedef otb::ConfusionMatrixCalculator<LabelListSampleType, LabelListSampleType> ConfusionMatrixCalculatorType;
  typedef ClassifierType::OutputType ClassifierOutputType;

 // Extract ROI and Project vectorData
 typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType, VectorImageType> VectorDataReprojectionType;

private:
  ValidateSVMImagesClassifier()
  {
    SetName("ValidateSVMImagesClassifier");
    SetDescription("Estimate the performance of the SVM model with a new set of validation samples and another image.");

    SetDocName("Validate SVM Images Classifier Application");
    SetDocLongDescription("Estimate the performance of the SVM model obtained by the ImagesSVMClassifier with a new set of validation samples and another image.\n The application asks for images statisctics as input (XML file generated with the ComputeImagesStatistics application) and a SVM model (text file) generated with the ImagesSVMClassifier application.\n It will compute the global confusion matrix and kappa index and also the precision, recall and F-score of each class.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");
    SetDocCLExample("otbApplicationLauncherCommandLine ValidateSVMImagesClassifier ${OTB-BIN}/bin"
      "--il ${OTB-Data}/Classification/QB_1_ortho.tif --vd  ${OTB-Data}/Classification/VectorData_QB1_bis.shp"
      " --imstat ${OTB-Data}/Baseline/OTB-Applications/Files/clImageStatisticsQB123.xml "
      " --svm  ${OTB-Data}/Baseline/OTB-Applications/Files/clsvmModelQB123.svm"
      " --out PerformanceEstimationQB123.txt ");
    AddDocTag(Tags::Learning);

  }

  virtual ~ValidateSVMImagesClassifier()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImageList, "il", "Input Image List");
    SetParameterDescription("il", "Input image list filename.");
    AddParameter(ParameterType_InputVectorDataList, "vd", "Vector Data List");
    SetParameterDescription("vd", "Vector Data of samples used to validate the estimator.");
    AddParameter(ParameterType_Filename, "dem", "DEM repository");
    SetParameterDescription("dem", "Path to DEM repository.");
    MandatoryOff("dem");
    AddParameter(ParameterType_Filename, "imstat", "XML image statistics file");
    MandatoryOff("imstat");
    SetParameterDescription("imstat", "filename of an XML file containing mean and standard deviation of input images.");
    AddParameter(ParameterType_Filename, "out", "Output filename");
    SetParameterDescription("out", "Filename, which will contain the performance of the SVM model.");
    MandatoryOff("out");
    SetParameterRole("out", Role_Output);
    AddParameter(ParameterType_Filename, "svm", "SVM validation filename");
    SetParameterDescription("svm",
                            "SVM model to validate its performances (given by TrainSVMImagesClassification output for instance).");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    GetLogger()->Debug("Entering DoExecute\n");
    //Create training and validation for list samples and label list samples
    ConcatenateLabelListSampleFilterType::Pointer
        concatenateTrainingLabels = ConcatenateLabelListSampleFilterType::New();
    ConcatenateListSampleFilterType::Pointer concatenateTrainingSamples = ConcatenateListSampleFilterType::New();
    ConcatenateLabelListSampleFilterType::Pointer
        concatenateValidationLabels = ConcatenateLabelListSampleFilterType::New();
    ConcatenateListSampleFilterType::Pointer concatenateValidationSamples = ConcatenateListSampleFilterType::New();

    MeasurementType meanMeasurementVector;
    MeasurementType stddevMeasurementVector;

    //--------------------------
    // Load measurements from images
    unsigned int nbBands = 0;
    //Iterate over all input images

    FloatVectorImageListType* imageList = GetParameterImageList("il");
    VectorDataListType* vectorDataList = GetParameterVectorDataList("vd");

    //Iterate over all input images
    for (unsigned int imgIndex = 0; imgIndex < imageList->Size(); ++imgIndex)
      {
      FloatVectorImageType::Pointer image = imageList->GetNthElement(imgIndex);
      image->UpdateOutputInformation();

      if (imgIndex == 0)
        {
        nbBands = image->GetNumberOfComponentsPerPixel();
        }

      // read the Vectordata
      VectorDataType::Pointer vectorData = vectorDataList->GetNthElement(imgIndex);
      vectorData->Update();

      VectorDataReprojectionType::Pointer vdreproj = VectorDataReprojectionType::New();
      vdreproj->SetInputImage(image);
      vdreproj->SetInput(vectorData);
      vdreproj->SetUseOutputSpacingAndOriginFromImage(false);

      // Configure DEM directory
      if (IsParameterEnabled("dem"))
        {
        vdreproj->SetDEMDirectory(GetParameterString("dem"));
        }
      else
        {
        if (otb::ConfigurationFile::GetInstance()->IsValid())
          {
          vdreproj->SetDEMDirectory(otb::ConfigurationFile::GetInstance()->GetDEMDirectory());
          }
        }

      vdreproj->Update();

      //Sample list generator
      ListSampleGeneratorType::Pointer sampleGenerator = ListSampleGeneratorType::New();

      //Set inputs of the sample generator
      //TODO the ListSampleGenerator perform UpdateOutputData over the input image (need a persistent implementation)
      sampleGenerator->SetInput(image);
      sampleGenerator->SetInputVectorData(vdreproj->GetOutput());
      sampleGenerator->SetValidationTrainingProportion(1.0); // All in validation

      sampleGenerator->SetClassKey("Class");

      sampleGenerator->Update();

      //Concatenate training and validation samples from the image
      concatenateValidationLabels->AddInput(sampleGenerator->GetValidationListLabel());
      concatenateValidationSamples->AddInput(sampleGenerator->GetValidationListSample());
      }

    // Update
    concatenateValidationSamples->Update();
    concatenateValidationLabels->Update();

    if (IsParameterEnabled("imstat"))
      {
      StatisticsReader::Pointer statisticsReader = StatisticsReader::New();
      statisticsReader->SetFileName(GetParameterString("imstat"));
      meanMeasurementVector = statisticsReader->GetStatisticVectorByName("mean");
      stddevMeasurementVector = statisticsReader->GetStatisticVectorByName("stddev");
      }
    else
      {
      meanMeasurementVector.SetSize(nbBands);
      meanMeasurementVector.Fill(0.);
      stddevMeasurementVector.SetSize(nbBands);
      stddevMeasurementVector.Fill(1.);
      }

    ShiftScaleFilterType::Pointer validationShiftScaleFilter = ShiftScaleFilterType::New();
    validationShiftScaleFilter->SetInput(concatenateValidationSamples->GetOutput());
    validationShiftScaleFilter->SetShifts(meanMeasurementVector);
    validationShiftScaleFilter->SetScales(stddevMeasurementVector);
    validationShiftScaleFilter->Update();
    //--------------------------
    // split the data set into training/validation set
    ListSampleType::Pointer validationListSample = validationShiftScaleFilter->GetOutputSampleList();
    LabelListSampleType::Pointer validationLabeledListSample = concatenateValidationLabels->GetOutputSampleList();

    otbAppLogINFO("Size of validation set: " << validationListSample->Size());
    otbAppLogINFO("Size of labeled validation set: " << validationLabeledListSample->Size());

    //--------------------------
    // Load svm model
    ModelPointerType modelSVM = ModelType::New();
    modelSVM->LoadModel(GetParameterString("svm").c_str());

    //--------------------------
    // Performances estimation
    ClassifierType::Pointer validationClassifier = ClassifierType::New();
    validationClassifier->SetSample(validationListSample);
    validationClassifier->SetNumberOfClasses(modelSVM->GetNumberOfClasses());
    validationClassifier->SetModel(modelSVM);
    validationClassifier->Update();

    // Estimate performances
    ClassifierOutputType::ConstIterator it = validationClassifier->GetOutput()->Begin();
    ClassifierOutputType::ConstIterator itEnd = validationClassifier->GetOutput()->End();

    LabelListSampleType::Pointer classifierListLabel = LabelListSampleType::New();

    while (it != itEnd)
      {
      // Due to a bug in SVMClassifier, outlier in one-class SVM are labeled with unsigned int max
      classifierListLabel->PushBack(
                                    it.GetClassLabel() == itk::NumericTraits<unsigned int>::max() ? 2
                                                                                : it.GetClassLabel());
      ++it;
      }

    ConfusionMatrixCalculatorType::Pointer confMatCalc = ConfusionMatrixCalculatorType::New();

    confMatCalc->SetReferenceLabels(validationLabeledListSample);
    confMatCalc->SetProducedLabels(classifierListLabel);

    confMatCalc->Update();

    otbAppLogINFO("*** SVM training performances ***\n" <<"Confusion matrix:\n" << confMatCalc->GetConfusionMatrix() << std::endl);

    for (unsigned int itClasses = 0; itClasses < modelSVM->GetNumberOfClasses(); itClasses++)
      {
      otbAppLogINFO("Precision of class [" << itClasses << "] vs all: " << confMatCalc->GetPrecisions()[itClasses] << std::endl);
      otbAppLogINFO("Recall of class [" << itClasses << "] vs all: " << confMatCalc->GetRecalls()[itClasses] << std::endl);
      otbAppLogINFO("F-score of class [" << itClasses << "] vs all: " << confMatCalc->GetFScores()[itClasses] << "\n" << std::endl);
      }
    otbAppLogINFO("Global performance, Kappa index: " << confMatCalc->GetKappaIndex() << std::endl);

    //--------------------------
    // Save output in a ascii file (if needed)
    if (IsParameterEnabled("out"))
      {
      std::ofstream file;
      file.open(GetParameterString("out").c_str());
      file << "Precision of the different class: " << confMatCalc->GetPrecisions() << std::endl;
      file << "Recall of the different class: " << confMatCalc->GetRecalls() << std::endl;
      file << "F-score of the different class: " << confMatCalc->GetFScores() << std::endl;
      file << "Kappa index: " << confMatCalc->GetKappaIndex() << std::endl;
      file.close();
      }
  }
};

} // end of namespace Wrapper
} // end of namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::ValidateSVMImagesClassifier)
<|endoftext|>


<commit_before>// ImageProcessor
// Class to handle the processing of the image sequence

#include "imageProcessor.h"

ImageProcessor::ImageProcessor()
{
	width = 480;
	height = 480;

	minVal = 0;
	maxVal = 255;
	bucketSize = 8;
	buckets = (maxVal + 1) / bucketSize;
}

ImageProcessor::~ImageProcessor()
{
}

void ImageProcessor::setFiles(vector<string> fn)
{
	fileNames = fn;

	inferParameters();
	initializeData();
}

void ImageProcessor::inferParameters()
{
	if (fileNames.size() <= 0)
	{
		cerr << "Image list empty. Exiting." << endl;
		exit(EXIT_FAILURE);
	}

	frames = fileNames.size();

	CImg<unsigned char> inspectImage(fileNames[0].c_str());
	width = inspectImage.width();
	height = inspectImage.height();
	channels = inspectImage.depth();
}

void ImageProcessor::initializeData()
{
	bucketData = new BucketData(width, height, buckets);
}

void ImageProcessor::setBucketSize(int newSize)
{
	bucketSize = newSize;
	buckets = (maxVal + 1) / bucketSize;
}

int ImageProcessor::getABucket(int value)
{
	if (value < minVal)
		return 0;

	if (value > maxVal)
		return buckets - 1;

	return value / bucketSize;
}

int ImageProcessor::getBBucket(int value)
{
	return getABucket(value + (bucketSize / 2));
}

void ImageProcessor::processSequence()
{
	countBuckets();
	findBiggestBucket();
	createOutput();
}

void ImageProcessor::countBuckets()
{
	cout << endl << "Reading:\t";

	// Read image frames and count the buckets
	for (auto &file : fileNames)
	{
		CImg<unsigned char> newImage(file.c_str());

		std::cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixel = newImage(i, j, 0, 0);

				int a_bucket = getABucket(pixel);
				bucketData->valueBucketA[i + j * width + a_bucket * (width * height)]++;

				int b_bucket = getBBucket(pixel);
				bucketData->valueBucketB[i + j * width + b_bucket * (width * height)]++;
			}
		}
	}
}

void ImageProcessor::findBiggestBucket()
{
	// Find the biggest bucket
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			int maxCount = 0;
			int nearMaxCount = 0;
			int maxBucket = -1;
			bool maxTypeA = true;

			for (int bucket = 0; bucket < buckets; bucket++)
			{
				if (bucketData->valueBucketA[i + j * width + bucket * (width * height)] > maxCount)
				{
					nearMaxCount = maxCount;
					maxCount = bucketData->valueBucketA[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = true;
				}
				if (bucketData->valueBucketB[i + j * width + bucket * (width * height)] > maxCount)
				{
					nearMaxCount = maxCount;
					maxCount = bucketData->valueBucketB[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = false;
				}
			}

			bucketData->finalBucket[i + j * width].id = maxBucket;
			bucketData->finalBucket[i + j * width].isABucket = maxTypeA;
			bucketData->finalBucket[i + j * width].diff = maxCount;
		}
	}
}

void ImageProcessor::createOutput()
{
	vector<float> accRed(width * height);
	vector<float> accGreen(width * height);
	vector<float> accBlue(width * height);
	vector<int> count(width * height);

	cout << endl << "Averaging:\t";

	// Average out all the pixel values from the biggest bucket
	for (auto &file : fileNames)
	{
		CImg<unsigned char> newImage(file.c_str());

		cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixelRed = newImage(i, j, 0, 0);

				if (bucketData->finalBucket[i + j * width].isABucket)
				{
					int pixABucket = getABucket(pixelRed);

					if (pixABucket == bucketData->finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
				else
				{
					int pixBBucket = getBBucket(pixelRed);

					if (pixBBucket == bucketData->finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
			}
		}
	}

	// Paint the final result in a window
	CImg<unsigned char> reconstructionImage(width, height, 1, 3, 0);
	CImgDisplay main_disp(width, height, "Reconstructed background");

	CImg<unsigned char> confidenceImage(width, height, 1, 1, 0);
	CImgDisplay aux_disp(width, height, "Confidence mask");

	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			reconstructionImage(i, j, 0, 0) = (unsigned char) (accRed[i + j * width] / count[i + j * width]);
			reconstructionImage(i, j, 0, 1) = (unsigned char) (accGreen[i + j * width] / count[i + j * width]);
			reconstructionImage(i, j, 0, 2) = (unsigned char) (accBlue[i + j * width] / count[i + j * width]);

			confidenceImage(i, j, 0, 0) = (unsigned char)bucketData->finalBucket[i + j * width].diff * 4;
		}
		main_disp.render(reconstructionImage);
		main_disp.paint();

		aux_disp.render(confidenceImage);
		aux_disp.paint();
	}

	cout << endl;

	while (!main_disp.is_closed())
	{
		main_disp.wait();
	}
}
<commit_msg>Simplified and improved the confidence map<commit_after>// ImageProcessor
// Class to handle the processing of the image sequence

#include "imageProcessor.h"

ImageProcessor::ImageProcessor()
{
	width = 480;
	height = 480;

	minVal = 0;
	maxVal = 255;
	bucketSize = 8;
	buckets = (maxVal + 1) / bucketSize;
}

ImageProcessor::~ImageProcessor()
{
}

void ImageProcessor::setFiles(vector<string> fn)
{
	fileNames = fn;

	inferParameters();
	initializeData();
}

void ImageProcessor::inferParameters()
{
	if (fileNames.size() <= 0)
	{
		cerr << "Image list empty. Exiting." << endl;
		exit(EXIT_FAILURE);
	}

	frames = fileNames.size();

	CImg<unsigned char> inspectImage(fileNames[0].c_str());
	width = inspectImage.width();
	height = inspectImage.height();
	channels = inspectImage.depth();
}

void ImageProcessor::initializeData()
{
	bucketData = new BucketData(width, height, buckets);
}

void ImageProcessor::setBucketSize(int newSize)
{
	bucketSize = newSize;
	buckets = (maxVal + 1) / bucketSize;
}

int ImageProcessor::getABucket(int value)
{
	if (value < minVal)
		return 0;

	if (value > maxVal)
		return buckets - 1;

	return value / bucketSize;
}

int ImageProcessor::getBBucket(int value)
{
	return getABucket(value + (bucketSize / 2));
}

void ImageProcessor::processSequence()
{
	countBuckets();
	findBiggestBucket();
	createOutput();
}

void ImageProcessor::countBuckets()
{
	cout << endl << "Reading:\t";

	// Read image frames and count the buckets
	for (auto &file : fileNames)
	{
		CImg<unsigned char> newImage(file.c_str());

		std::cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixel = newImage(i, j, 0, 0);

				int a_bucket = getABucket(pixel);
				bucketData->valueBucketA[i + j * width + a_bucket * (width * height)]++;

				int b_bucket = getBBucket(pixel);
				bucketData->valueBucketB[i + j * width + b_bucket * (width * height)]++;
			}
		}
	}
}

void ImageProcessor::findBiggestBucket()
{
	// Find the biggest bucket
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			int maxCount = 0;
			int maxBucket = -1;
			bool maxTypeA = true;

			for (int bucket = 0; bucket < buckets; bucket++)
			{
				if (bucketData->valueBucketA[i + j * width + bucket * (width * height)] > maxCount)
				{
					maxCount = bucketData->valueBucketA[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = true;
				}
				if (bucketData->valueBucketB[i + j * width + bucket * (width * height)] > maxCount)
				{
					maxCount = bucketData->valueBucketB[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = false;
				}
			}

			bucketData->finalBucket[i + j * width].id = maxBucket;
			bucketData->finalBucket[i + j * width].isABucket = maxTypeA;
			bucketData->finalBucket[i + j * width].diff = maxCount;
		}
	}
}

void ImageProcessor::createOutput()
{
	vector<float> accRed(width * height);
	vector<float> accGreen(width * height);
	vector<float> accBlue(width * height);
	vector<int> count(width * height);

	cout << endl << "Averaging:\t";

	// Average out all the pixel values from the biggest bucket
	for (auto &file : fileNames)
	{
		CImg<unsigned char> newImage(file.c_str());

		cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixelRed = newImage(i, j, 0, 0);

				if (bucketData->finalBucket[i + j * width].isABucket)
				{
					int pixABucket = getABucket(pixelRed);

					if (pixABucket == bucketData->finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
				else
				{
					int pixBBucket = getBBucket(pixelRed);

					if (pixBBucket == bucketData->finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
			}
		}
	}

	// Paint the final result in a window
	CImg<unsigned char> reconstructionImage(width, height, 1, 3, 0);
	CImgDisplay main_disp(width, height, "Reconstructed background");

	CImg<unsigned char> confidenceImage(width, height, 1, 1, 0);
	CImgDisplay aux_disp(width, height, "Confidence mask");

	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			reconstructionImage(i, j, 0, 0) = (unsigned char) (accRed[i + j * width] / count[i + j * width]);
			reconstructionImage(i, j, 0, 1) = (unsigned char) (accGreen[i + j * width] / count[i + j * width]);
			reconstructionImage(i, j, 0, 2) = (unsigned char) (accBlue[i + j * width] / count[i + j * width]);

			confidenceImage(i, j, 0, 0) = (unsigned char) (bucketData->finalBucket[i + j * width].diff * maxVal / frames);
		}
		main_disp.render(reconstructionImage);
		main_disp.paint();

		aux_disp.render(confidenceImage);
		aux_disp.paint();
	}

	cout << endl;

	while (!main_disp.is_closed())
	{
		main_disp.wait();
	}
}
<|endoftext|>