Menu
bath2019
  • Verge 3D Work
  • Work In Progress
bath2019

Mollweide-projection into wrapable rectangle

Posted on June 19, 2019June 19, 2019
//***************************************************************************
// Mollweide-projection into wrapable rectangle 
// Petri Ihalainen
// 22-Nov-2013
// Version 1.0
//***************************************************************************

import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;

//======================
// YOUR SETTINGS BELOW
//======================

String  WorkDir = "C:\\Documents and Settings\\Ihalainen\\Työpöytä\\"; // NOTE THE DOUBLE BACK-SLASHES!!
String  MollweideName  = "Mollweide-projection.jpg";
String  RectangleName  = "Rectangle-projection";	   // No file-extension here! The script will add it.
String  SavingFormat   = "png";                      // png, jpg, gif or bmp should work

Boolean InterpolatePixels = true; // true for quality, false for speed

//Use these if the original image e.g. has a frame area
int ExcludePixelsTop    = 0; 
int ExcludePixelsBottom = 0;
int ExcludePixelsLeft   = 0;
int ExcludePixelsRight  = 0;

//=======================================================================================================
// End of settings
//=======================================================================================================

//=========================
// Methods
//=========================

//---------------------
// Iterate Theta
//---------------------
float IterateTheta(float phi)
{
	// The iteration was said to be slow by poles but I have not noticed.
	t = phi;
	float t1 = 0.0f;
	while (Math.abs(t1-t) > 0.00001)
	{	
		t = t1;
		t1 = t - (float)((2.0f*t + Math.sin(2.0f*t)-Math.PI*Math.sin(phi))/(2.0f+2.0f*Math.cos(2.0f*t)));
	}
	return t;
}

//---------------------------------
// Interpolate between four pixels
//---------------------------------
Color getBlendedColor(BufferedImage img, int w, int h, int exL, int exT, float x, int r0, int r1, float wr0, float wr1)
{	
	int c00,c01,c10,c11;
	int red,green,blue;
	float c,wc00=0.5f,wc01=0.5f,wc10=0.5f,wc11=0.5f;//,wc;
	Color p00,p10,p01,p11;

// weights on upper row
	ym0 = ((r0 + 0.5f) - h*0.5f)/h*2.0f;	
	xm0 = (float)(Math.sqrt(1.0 - ym0*ym0)*x);
	cm0 = (w/2.0f + xm0*w/2.0f);
	c00 = (int)cm0;
	c10 = c00;
	cRes0 = cm0 - c00;
	
	if (cRes0 < 0.5)
	{
		c00--;
		wc00 = 0.5f - cRes0;
		wc10 = 0.5f + cRes0;
	}
	if (cRes0 > 0.5)
	{
		c10++;
		wc00 = 1.5f - cRes0;
		wc10 = cRes0-0.5f;
	}
	
// weights on lower row
	ym1 = ((r1 + 0.5f) - h*0.5f)/h*2.0f;	
	xm1 = (float)(Math.sqrt(1.0 - ym1*ym1)*x);
	cm1 = (w/2.0f + xm1*w/2.0f);
	c01 = (int)cm1;
	c11 = c01;
	cRes1 = cm1 - c01;
	
	if (cRes1 < 0.5)
	{
		c01--;
		wc01 = 0.5f - cRes1;
		wc11 = 0.5f + cRes1;
	}
	if (cRes1 > 0.5)
	{
		c11++;
		wc01 = 1.5f - cRes1;
		wc11 = cRes1-0.5f;
	}


	if (c00<0) c00=0;
	if (c01>w-1) c01=w-1;
	if (c10<0) c10=0;
	if (c11>w-1) c11=w-1;

	p00 = new Color(img.getRGB(c00+exL,r0+exT),false);
	p10 = new Color(img.getRGB(c10+exL,r0+exT),false);
	p01 = new Color(img.getRGB(c01+exL,r1+exT),false);
	p11 = new Color(img.getRGB(c11+exL,r1+exT),false);


	red =   (int)(p00.getRed()*wc00*wr0   + p10.getRed()*wc10*wr0   + p01.getRed()*wc01*wr1   + p11.getRed()*wc11*wr1  +0.5f);
	green = (int)(p00.getGreen()*wc00*wr0 + p10.getGreen()*wc10*wr0 + p01.getGreen()*wc01*wr1 + p11.getGreen()*wc11*wr1+0.5f);
	blue =  (int)(p00.getBlue()*wc00*wr0  + p10.getBlue()*wc10*wr0  + p01.getBlue()*wc01*wr1  + p11.getBlue()*wc11*wr1 +0.5f);

  // print (red + " " + green +" "+ blue);

	if (red > 255) red=255; if (red < 0) red=0; 
	if (green > 255) green=255; if (green < 0) green=0; 
	if (blue > 255) blue=255; if (blue < 0) blue=0; 

	return (new Color(red,green,blue));
}

//--------------------------------------------------------------------
// Create rectangle image by interpolating the over the closest pixels
//--------------------------------------------------------------------

BufferedImage InterpolatedImage(BufferedImage imgMoll, int ExT, int ExB, int ExL, int ExR)
{ 
	int w = imgMoll.getWidth()-ExL-ExR;
	int h = imgMoll.getHeight()-ExT-ExB;

	BufferedImage imgRect = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
	g2rect = imgRect.createGraphics();
	
	int row, col;
	int r0,r1;
	float r,wr0=0.5f,wr1=0.5f,wr;
	float xRect, yRect, yMoll, yMPI2, xMoll, theta, phiRect, pi = (float)Math.PI; 	
	
	yMPI2 = (float)(Math.PI / Math.sqrt(2.0) * Math.sin(Math.PI /2.0)); // This is neede scale y to [-1.0 ... 1.0]

	for (row=0; row<h; row++)
	{ 
		print ("row " + (row + 1) + " of " + h);
		
		yRect = (-h/2.0f + row+0.5f)/(h/2.0f); // The rectangle y
		phiRect = yRect*pi/2.0f; // Convert y to vertical angle
		theta = IterateTheta((float)phiRect);  // a Mollweide variable iterated
		yMoll = (float)(Math.PI  / Math.sqrt(2.0) * Math.sin(theta))/yMPI2; // the Mollwide y
		
		r = h/2.0f + yMoll*h/2.0f; 

		r0 = (int)r;
		r1 = r0;
		wr = r-(int)r;
		wr0 = 1.0f-wr1;
		
		if (wr<0.5f) {
			r0--; 
			wr0 = 0.5f - wr;
			wr1 = 0.5f + wr;}
		if (wr>0.5f){
			r1++;
			wr0 = 1.5f - wr;
			wr1 = wr-0.5f;}

		if (r0<0) r0=0;
		if (r1>h-1) r1=h-1;

		for (col=0; col<w; col++)
		{
			xRect = (-w/2.0f + col + 0.5f)/(w/2.0f); // The rectangle
			g2rect.setColor(getBlendedColor(imgMoll, w, h, ExL, ExT, xRect, r0, r1, wr0, wr1));
			g2rect.drawLine(col,row,col,row);
		}
	}
	return imgRect; // INTERPOLATED 
}

//-------------------------------------------------------------------
// Create a rectangular image by picking the closest pixel
//-------------------------------------------------------------------

BufferedImage PickedImage(BufferedImage imgMoll, int ExT, int ExB, int ExL, int ExR)
{	
	int w = imgMoll.getWidth()-ExL-ExR;
	int h = imgMoll.getHeight()-ExT-ExB;

	BufferedImage imgRect = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
	g2rect = imgRect.createGraphics();
	
	int row, col;
	float r,wr0=0.5f,wr1=0.5f,wr;
	float xRect, yRect, yMoll, yMPI2, xMoll, theta, phiRect, pi = (float)Math.PI; 	

	yMPI2 = (float)(Math.PI / Math.sqrt(2.0) * Math.sin(Math.PI /2.0)); // This is needed to scale y to [-1.0 ... 1.0]

	for (row=0; row<h; row++)
	{
		print ("row " + (row + 1) + " of " + h);

		yRect = (-h/2.0f + row+0.5f)/(h/2.0f); // The rectangle y
		phiRect = yRect*pi/2.0f; // Convert y to vertical angle
		theta = IterateTheta((float)phiRect);  // a Mollweide variable iterated
		yMoll = (float)(Math.PI  / Math.sqrt(2.0) * Math.sin(theta))/yMPI2; // the Mollwide y

		for (col=0; col<w; col++)
		{
			xRect = (-w/2.0f + col + 0.5f)/(w/2.0f); // The rectangle x
			xMoll = (float)Math.sqrt(1.0 - yMoll*yMoll) * xRect; // The Mollweide-x provided by Pythagoras

			rMoll = (int)(h/2.0f + yMoll*h/2.0f)+ExT; // y to a pixel row
			cMoll = (int)(w/2.0f + xMoll*w/2.0f)+ExL; // x to a pixel column

			g2rect.setColor(new Color(imgMoll.getRGB(cMoll,rMoll),false));

			g2rect.drawLine(col,row,col,row);
		}
	}
	return imgRect; // PICKED
}

//=========================================================
// Doing the job in a thread so you can follow the progress
//=========================================================
new Thread() 
	{public void run() {

//--------------------
// Some prework
//--------------------
String ReadPath = WorkDir + MollweideName;
String WritePath = WorkDir + RectangleName + "." + SavingFormat;
BufferedImage imgMoll = null;

//------------------------
// Reading the input image
//------------------------
print ("Loading " + ReadPath);
try 
	{imgMoll = ImageIO.read(new File(ReadPath));} 
catch (IOException e) 
	{print ("Not found");
	return;}

print ("Input image height "+imgMoll.getHeight()+" pixels");
print ("Input image width "+imgMoll.getWidth()+" pixels");

//-----------------------
// Get the new image
//-----------------------
t0 = System.currentTimeMillis();
BufferedImage imgRect;

if (InterpolatePixels)
	imgRect = InterpolatedImage(imgMoll, ExcludePixelsTop, ExcludePixelsBottom, ExcludePixelsLeft, ExcludePixelsRight);
else
	imgRect = PickedImage(imgMoll, ExcludePixelsTop, ExcludePixelsBottom, ExcludePixelsLeft, ExcludePixelsRight);


//----------------------
// Saving the new image
//----------------------

try 
	{
		print ("Saving " + WritePath);
		ImageIO.write(imgRect, SavingFormat, new File(WritePath));
	} 
catch (IOException e) 
	{
		print ("Error in saving " + WritePath);
	}

//--------------------
// End :)
//--------------------

t1 = System.currentTimeMillis();
print ("Processing competed in " + (t1-t0)/1000.0 + " seconds");
	} 
}.start();

Recent Posts

  • Mollweide-projection into wrapable rectangle
  • Python EB
  • Bath
©2022 bath2019 | WordPress Theme by Superbthemes.com