Files
ThirdParty-6/ParaView-5.0.1/ParaViewCore/ServerManager/Rendering/vtkSMUtilities.cxx

345 lines
10 KiB
C++

/*=========================================================================
Program: ParaView
Module: vtkSMUtilities.cxx
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 notice for more information.
=========================================================================*/
#include "vtkSMUtilities.h"
#include "vtkBMPWriter.h"
#include "vtkErrorCode.h"
#include "vtkImageData.h"
#include "vtkImageIterator.h"
#include "vtkJPEGWriter.h"
#include "vtkMath.h"
#include "vtkMultiProcessController.h"
#include "vtkObjectFactory.h"
#include "vtkPNGWriter.h"
#include "vtkPNMWriter.h"
#include "vtkPoints.h"
#include "vtkPVInstantiator.h"
#include "vtkTIFFWriter.h"
#include "vtkTimerLog.h"
#include "vtkTransform.h"
#include <vtksys/SystemTools.hxx>
#include <sstream>
#include <string>
#include <algorithm>
vtkStandardNewMacro(vtkSMUtilities);
//----------------------------------------------------------------------------
int vtkSMUtilities::SaveImage(vtkImageData* image, const char* filename,
int quality /*=-1*/)
{
vtkTimerLog::MarkStartEvent("vtkSMUtilities::SaveImage");
if (!filename || !filename[0])
{
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImage");
return vtkErrorCode::NoFileNameError;
}
std::string ext = vtksys::SystemTools::GetFilenameLastExtension(filename);
ext = vtksys::SystemTools::LowerCase(ext);
vtkImageWriter* writer = 0;
if (ext == ".bmp")
{
writer= vtkBMPWriter::New();
}
else if (ext == ".tif" || ext == ".tiff")
{
writer = vtkTIFFWriter::New();
}
else if (ext == ".ppm")
{
writer = vtkPNMWriter::New();
}
else if (ext == ".png")
{
writer = vtkPNGWriter::New();
}
else if (ext == ".jpg" || ext == ".jpeg")
{
vtkJPEGWriter* jpegWriter = vtkJPEGWriter::New();
if (quality >=0 && quality <= 100)
{
jpegWriter->SetQuality(quality);
}
writer = jpegWriter;
}
else
{
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImage");
return vtkErrorCode::UnrecognizedFileTypeError;
}
writer->SetInputData(image);
writer->SetFileName(filename);
writer->Write();
int error_code = writer->GetErrorCode();
writer->Delete();
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImage");
return error_code;
}
//----------------------------------------------------------------------------
int vtkSMUtilities::
SaveImage(vtkImageData* image, const char* filename, const char* writerName)
{
vtkTimerLog::MarkStartEvent("vtkSMUtilities::SaveImage");
if (!filename || !writerName)
{
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImage");
return vtkErrorCode::UnknownError;
}
vtkObject* object = vtkPVInstantiator::CreateInstance(writerName);
if (!object)
{
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImage");
vtkGenericWarningMacro("Failed to create Writer " << writerName);
return vtkErrorCode::UnknownError;
}
vtkImageWriter* writer = vtkImageWriter::SafeDownCast(object);
if (!writer)
{
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImage");
vtkGenericWarningMacro("Object is not a vtkImageWriter: "
<< object->GetClassName());
object->Delete();
return vtkErrorCode::UnknownError;
}
writer->SetInputData(image);
writer->SetFileName(filename);
writer->Write();
int error_code = writer->GetErrorCode();
writer->Delete();
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImage");
return error_code;
}
//----------------------------------------------------------------------------
// This is usually called on a serial client, but if it is called in
// a parallel job (for example, while coprocessing for a solver), then
// we really only want to write out an image on process 0.
int vtkSMUtilities::SaveImageOnProcessZero(vtkImageData* image,
const char* filename, const char* writerName)
{
vtkTimerLog::MarkStartEvent("vtkSMUtilities::SaveImageOnProcessZero");
int error_code;
vtkMultiProcessController *controller =
vtkMultiProcessController::GetGlobalController();
if (controller)
{
if (controller->GetLocalProcessId() == 0)
{
error_code = SaveImage(image, filename, writerName);
}
controller->Broadcast(&error_code, 1, 0);
}
else
{
error_code = SaveImage(image, filename, writerName);
}
vtkTimerLog::MarkEndEvent("vtkSMUtilities::SaveImageOnProcessZero");
return error_code;
}
//----------------------------------------------------------------------------
vtkPoints* vtkSMUtilities::CreateOrbit(const double center[3],
const double in_normal[3], double radius, int resolution)
{
double normal[3] = {in_normal[0], in_normal[1], in_normal[2]};
vtkMath::Normalize(normal);
double x_axis[3] = {1,0,0};
double y_axis[3] = {1,0,0};
double startPoint[3];
// Is X not colinear to the normal ?
if(vtkMath::Dot(x_axis, normal) < 0.999)
{
// Do with X axis
vtkMath::Cross(x_axis, normal, startPoint);
vtkMath::Normalize(startPoint);
}
else
{
// Do with Y axis
vtkMath::Cross(y_axis, normal, startPoint);
vtkMath::Normalize(startPoint);
}
// Fix start point
for(int i=0;i<3;i++)
{
// Scale start point to have a given radius
startPoint[i] *= radius;
// Translate regarding the center
startPoint[i] += center[i];
}
return CreateOrbit(center, normal, resolution, startPoint);
}
//----------------------------------------------------------------------------
vtkPoints* vtkSMUtilities::CreateOrbit(const double center[3],
const double in_normal[3], int resolution, const double startPoint[3])
{
// Create the step rotation
double normal[3] = {in_normal[0], in_normal[1], in_normal[2]};
vtkMath::Normalize(normal);
vtkTransform * transform = vtkTransform::New();
transform->Identity();
transform->RotateWXYZ(360/resolution, normal);
// Setup initial point location
double point[3];
point[0] = startPoint[0] - center[0];
point[1] = startPoint[1] - center[1];
point[2] = startPoint[2] - center[2];
// Fill the result
vtkPoints* pts = vtkPoints::New(VTK_DOUBLE);
pts->SetNumberOfPoints(resolution);
for (int i=0; i < resolution; i++)
{
pts->SetPoint( i,
point[0] + center[0],
point[1] + center[1],
point[2] + center[2]);
transform->TransformPoint(point, point);
}
transform->Delete();
return pts;
}
//-----------------------------------------------------------------------------
void vtkSMUtilities::Merge(vtkImageData* dest, vtkImageData* src,
int borderWidth, const unsigned char* borderColorRGB)
{
if (!src || !dest)
{
return;
}
assert(dest->GetScalarType() == VTK_UNSIGNED_CHAR);
assert(src->GetScalarType() == VTK_UNSIGNED_CHAR);
vtkImageIterator<unsigned char> inIt(src, src->GetExtent());
int outextent[6];
src->GetExtent(outextent);
// we need to flip Y.
outextent[2] = dest->GetExtent()[3] - outextent[2];
outextent[3] = dest->GetExtent()[3] - outextent[3];
int temp = outextent[2];
outextent[2] = outextent[3];
outextent[3] = temp;
// snap extents to what is available.
outextent[0] = std::max(outextent[0], dest->GetExtent()[0]);
outextent[1] = std::min(outextent[1], dest->GetExtent()[1]);
outextent[2] = std::max(outextent[2], dest->GetExtent()[2]);
outextent[3] = std::min(outextent[3], dest->GetExtent()[3]);
vtkImageIterator<unsigned char> outIt(dest, outextent);
while (!outIt.IsAtEnd() && !inIt.IsAtEnd())
{
unsigned char* spanOut = outIt.BeginSpan();
unsigned char* spanIn = inIt.BeginSpan();
unsigned char* outSpanEnd = outIt.EndSpan();
unsigned char* inSpanEnd = inIt.EndSpan();
if (outSpanEnd != spanOut && inSpanEnd != spanIn)
{
size_t minO = outSpanEnd - spanOut;
size_t minI = inSpanEnd - spanIn;
memcpy(spanOut, spanIn, (minO < minI)? minO : minI);
}
inIt.NextSpan();
outIt.NextSpan();
}
if (borderWidth < 1 || borderColorRGB == NULL)
{
return;
}
// overlay the border.
int oddBorderWidth = static_cast<int>(std::floor(borderWidth/2.0));
int evenBorderWidth = static_cast<int>(std::ceil(borderWidth/2.0));
bool draw_border[4] = {
(outextent[0] != dest->GetExtent()[0]) && (evenBorderWidth > 0) ,
(outextent[1] != dest->GetExtent()[1]) && (oddBorderWidth > 0) ,
(outextent[2] != dest->GetExtent()[2]) && (evenBorderWidth > 0) ,
(outextent[3] != dest->GetExtent()[3]) && (oddBorderWidth > 0)
};
for (int cc=0; cc < 4; cc++)
{
if (draw_border[cc] == false)
{
// this is an outer edge. No need to put a border.
continue;
}
int border_extent[6];
memcpy(border_extent, outextent, 4*sizeof(int));
border_extent[4] = border_extent[5] = 0;
if ((cc % 2) == 0)
{
// even == start
border_extent[cc+1] = border_extent[cc] + evenBorderWidth;
}
else
{
// odd == end
border_extent[cc-1] = border_extent[cc] - oddBorderWidth;
}
vtkSMUtilities::FillImage(dest, border_extent, borderColorRGB);
}
}
//----------------------------------------------------------------------------
void vtkSMUtilities::FillImage(vtkImageData* image, const int extent[6],
const unsigned char rgb[3])
{
assert(image->GetScalarType() == VTK_UNSIGNED_CHAR);
unsigned char rgba[4] = {rgb[0], rgb[1], rgb[2], 0xFF};
vtkImageIterator<unsigned char> iter(image, const_cast<int*>(extent));
int num_comps = image->GetNumberOfScalarComponents();
int comps_to_fill = std::min(4, num_comps);
while (!iter.IsAtEnd())
{
unsigned char* start = iter.BeginSpan();
unsigned char* end = iter.EndSpan();
for (; start < end; start += num_comps)
{
memcpy(start, rgba, sizeof(unsigned char) * comps_to_fill);
}
iter.NextSpan();
}
}
//----------------------------------------------------------------------------
void vtkSMUtilities::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}