Skip to content

Commit

Permalink
Work in progress Deep pixel inspector
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldresser-ie committed Feb 3, 2024
1 parent a4661d7 commit 8c9c08f
Show file tree
Hide file tree
Showing 10 changed files with 1,283 additions and 6 deletions.
166 changes: 166 additions & 0 deletions include/GafferImageUI/DeepSampleGadget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2023, Image Engine Design Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above
// copyright notice, this list of conditions and the following
// disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided with
// the distribution.
//
// * Neither the name of John Haddon nor the names of
// any other contributors to this software may be used to endorse or
// promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#ifndef GAFFERIMAGEUI_DEEPSAMPLEGADGET_H
#define GAFFERIMAGEUI_DEEPSAMPLEGADGET_H

#include "GafferUI/Gadget.h"
#include "GafferUI/Style.h"
#include "GafferUI/GraphGadget.h"
#include "GafferUI/ViewportGadget.h"

#include "GafferImageUI/TypeIds.h"

#include "GafferImage/ImagePlug.h"

#include "Gaffer/StandardSet.h"

#include "boost/optional.hpp"

namespace Gaffer
{

IE_CORE_FORWARDDECLARE( Context );

}

namespace GafferImageUI
{

class GAFFERUI_API DeepSampleGadget : public GafferUI::Gadget
{

public :

DeepSampleGadget();

~DeepSampleGadget() override;

GAFFER_GRAPHCOMPONENT_DECLARE_TYPE( GafferImageUI::DeepSampleGadget, GafferImageUI::DeepSampleGadgetTypeId, GafferUI::Gadget );

//void setImagePlug( GafferImage::ImagePlug *imagePlug);
//GafferImage::ImagePlug *getImagePlug();

void setDeepSamples( IECore::ConstCompoundDataPtr deepSamples );
void setAutoFrame( bool autoFrame );
void setLogarithmic( bool log );

std::string getToolTip( const IECore::LineSegment3f &line ) const override;

protected :

unsigned layerMask() const override;
Imath::Box3f renderBound() const override;
void renderLayer( GafferUI::Gadget::Layer layer, const GafferUI::Style *style, RenderReason reason ) const override;

private :

void frame();

void plugDirtied( Gaffer::Plug *plug );

bool keyPress( GafferUI::GadgetPtr gadget, const GafferUI::KeyEvent &event );

// Find elements at certain positions
int keyAt( const IECore::LineSegment3f &position ) const;
IECore::InternedString curveAt( const IECore::LineSegment3f &position ) const;

void renderCurve( IECore::ConstFloatVectorDataPtr z, IECore::ConstFloatVectorDataPtr zBack, IECore::ConstFloatVectorDataPtr a, IECore::ConstFloatVectorDataPtr v );

bool onTimeAxis( int y ) const;
bool onValueAxis( int x ) const;

inline float axisMapping( float y ) const
{
return m_logarithmic ?
( y >= 1 ? 1.0f : 1 - log10( 1 - y ) ) :
y;
}

inline float reverseAxisMapping( float y ) const
{
return m_logarithmic ?
( 1 - exp10( 1 - y ) ) :
y;
}

// Compute grid line locations. Note that positions are given in raster space so
// that lines can get drawn directly.
// For the time-dimension we limit the computed locations to multiples of one
// frame plus one level of unlabeled dividing lines. Resulting at a minimum
// distance between lines of a fifth of a frame when zoomed in all the way.
// For the value dimension we allow sub-steps as small as 0.001.
struct AxisDefinition
{
std::vector<std::pair<float, float> > main;
std::vector<float> secondary;
};

void computeGrid( const GafferUI::ViewportGadget *viewportGadget, AxisDefinition &x, AxisDefinition &y ) const;

Gaffer::Context *m_context;

Gaffer::StandardSetPtr m_visiblePlugs;
Gaffer::StandardSetPtr m_editablePlugs;



IECore::ConstCompoundDataPtr m_deepSampleDicts;
IECore::ConstCompoundDataPtr m_deepSampleDictsAccumulated;

int m_highlightedKey;
int m_highlightedCurve;

bool m_keyPreview;
Imath::V3f m_keyPreviewLocation;

// details regarding spacing and layouting
int m_xMargin;
int m_yMargin;
int m_textScale;
int m_labelPadding;

boost::optional<int> m_frameIndicatorPreviewFrame;

bool m_autoFrame;
bool m_logarithmic;
};

IE_CORE_DECLAREPTR( DeepSampleGadget );

} // namespace GafferImageUI

#endif // GAFFERIMAGEUI_DEEPSAMPLEGADGET_H
1 change: 1 addition & 0 deletions include/GafferImageUI/TypeIds.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ enum TypeId
ColorInspectorPlugTypeId = 110854,
Box2iGadgetTypeId = 110855,
V2iGadgetTypeId = 110856,
DeepSampleGadgetTypeId = 110857,

LastTypeId = 110899
};
Expand Down
111 changes: 111 additions & 0 deletions python/GafferImageUI/DeepPixelInfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
##########################################################################
#
# Copyright (c) 2020, Image Engine Design Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided with
# the distribution.
#
# * Neither the name of John Haddon nor the names of
# any other contributors to this software may be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import sys
import imath

import IECore

import Gaffer
import GafferImage
import GafferUI
import GafferImageUI

class DeepPixelInfo( GafferUI.Widget ) :

def __init__( self, **kw ) :

self.__column = GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Vertical, spacing = 4 )

GafferUI.Widget.__init__( self, self.__column, **kw )

self.__pixel = Gaffer.V2iPlug( "pixelCoordinates" )
Gaffer.Metadata.registerValue( self.__pixel, "readOnly", True )
self.__channels = Gaffer.StringVectorDataPlug( "channels", Gaffer.Plug.Direction.In, IECore.StringVectorData() )
Gaffer.Metadata.registerValue( self.__channels, "readOnly", True )
self.__autoFrame = Gaffer.BoolPlug( "autoFrame", defaultValue = True )
self.__logarithmic = Gaffer.BoolPlug( "logarithmic" )

# HACK for ChannelMaskPlug
self.__inputPlugs = Gaffer.ArrayPlug( "in", element = GafferImage.ImagePlug() )

self.__dummyNode = Gaffer.Node()
self.__dummyNode.addChild( self.__pixel )
self.__dummyNode.addChild( self.__channels )
self.__dummyNode.addChild( self.__autoFrame )
self.__dummyNode.addChild( self.__logarithmic )
self.__dummyNode.addChild( self.__inputPlugs )

self.__uiPlugDirtiedConnection = self.__dummyNode.plugDirtiedSignal().connect( Gaffer.WeakMethod( self.__uiPlugDirtied ), scoped = True )

with self.__column :
with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing = 4 ) :
self.__busyWidget = GafferUI.BusyWidget( size = 20 )
self.__p1 = GafferUI.PlugWidget( self.__pixel )
self.__p2 = GafferUI.PlugWidget( GafferImageUI.RGBAChannelsPlugValueWidget( self.__channels ) )
self.__p3 = GafferUI.PlugWidget( self.__autoFrame )
self.__p4 = GafferUI.PlugWidget( self.__logarithmic )

self.__gadgetWidget = GafferUI.GadgetWidget(
bufferOptions = set( [ GafferUI.GLWidget.BufferOptions.Depth ] )
)

self.__deepSamplesGadget = GafferImageUI.DeepSampleGadget()
self.__gadgetWidget.getViewportGadget().setPrimaryChild( self.__deepSamplesGadget )
self.__gadgetWidget.getViewportGadget().setVariableAspectZoom( True )

self.__pixelValues = [{}, {}]

def __uiPlugDirtied( self, plug ):
if plug == self.__logarithmic:
self.__deepSamplesGadget.setLogarithmic( plug.getValue() )
elif plug == self.__autoFrame:
self.__deepSamplesGadget.setAutoFrame( plug.getValue() )

def setSource( self, pixel, channels ):
self.__pixel.setValue( pixel )
self.__channels.setValue( channels )

def updatePixelData( self, pixels ):
self.__deepSamplesGadget.setDeepSamples( IECore.CompoundData(
{
"A" : pixels[0],
"B" : pixels[1]
}
) )

def setBusy( self, busy ):
self.__busyWidget.setBusy( busy )
Loading

0 comments on commit 8c9c08f

Please sign in to comment.