Skip to content

Instantly share code, notes, and snippets.

@Ignotus-mago
Last active September 10, 2022 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ignotus-mago/ac3a50dfc0e1b60fc082a66e611790c0 to your computer and use it in GitHub Desktop.
Save Ignotus-mago/ac3a50dfc0e1b60fc082a66e611790c0 to your computer and use it in GitHub Desktop.
Processing tool for basic image transforms using a PGraphics.
// Processing tool for basic image transforms using a PGraphics.
// ImageTransform.pde implements the PGraphics and the transforms in a separate class.
// The drawAndSave method creates an image to use for the transforms.
// The ImageTransform class does the work.
/*
Note the different behaviors for uppercase and lowercase keys,
which have an effect when the image includes an alpha channel.
=====================------------->>>>> Key Command Help <<<<<-------------=====================
press 't' or 'T' to show animation.
press 'f' to rotate image 90 degrees CW, 'F' to fill background and rotate.
press 'b' to rotate image 90 degrees CCW, 'B' to fill background and rotate.
press 'r' to rotate image 180 degrees, 'R' to fill background and rotate.
press 'x' to flip x-coordinates, 'X' to fill background and flip.
press 'z' to flip x-coordinates and rotate 90 degrees CW, 'Z' to fill background, flip and rotate.
press 'c' to flip x-coordinates and rotate 90 degrees CCW, 'C' to fill background, flip and rotate.
press 'y' to flip y-coordinates, 'Y' to fill background and flip.
press 'w' to resize PGraphics and rotate image 45 degrees, 'W' to fill background, resize and flip.
press 'k' or 'K' to reset image size (use after 'w').
press 'o' or 'O' to reload the image from disk.
press 's' or 'S' to save the display to a PNG file.
press 'h' to show help.
=====================------------->>>>><<<<<-------------=====================
*/
/**
* @author Paul Hertz
* https://github.com/Ignotus-mago
*
*/
PGraphics graf;
PImage img;
// a 768 x 768 pixel image with alpha (transparent color) background.
String imgFilename = "fShape.png";
int step = 0;
int gw;
int gh;
float ang = 360.0/89 * DEG_TO_RAD;
int totalSteps = 23;
ImageTransform iTrans;
boolean isTwirl = false;
int startWidth;
int startHeight;
public void setup() {
size(1024, 1024);
graf = createGraphics(1024, 1024);
drawAndSave(imgFilename);
// you can load a different image here
img = loadImage(imgFilename);
startWidth = img.width;
startHeight = img.height;
graf.setSize(img.width, img.height);
gw = graf.width;
gh = graf.width;
iTrans = new ImageTransform();
showHelp();
}
public void draw() {
background(255);
if (isTwirl) {
rotateGraf();
image(graf.get(), (width - gw)/2, (height - gh)/2);
}
else {
image(img, (width - img.width)/2, (height - img.height)/2);
}
}
public void drawAndSave(String filename) {
// use a local PGraphics to create and save an image
PGraphics eff = createGraphics(768, 768);
eff.beginDraw();
eff.background(76, 123, 220, 64);
eff.noStroke();
eff.fill(220, 47, 34, 224);
eff.rect(192, 576, 576, 192);
eff.fill(246, 233, 47, 224);
eff.rect(192, 192, 576, 192);
eff.endDraw();
eff.save(filename);
}
public void rotateGraf() {
graf.beginDraw();
graf.push();
graf.translate(gw/2, gh/2);
graf.scale(0.6, 0.6);
graf.rotate((TWO_PI * step++)/totalSteps + ang);
if (step % totalSteps == 0) {
step = 0;
ang += PI/89;
if (ang > TWO_PI) ang = ang - TWO_PI;
}
graf.translate(-gw/2, -gh/2);
graf.image(img, 0, 0);
graf.pop();
graf.endDraw();
}
public void keyPressed() {
// vary the color and the alpha value for different effects
int c = color(255, 0);
float maxRotAdjust = sqrt(2);
switch (key) {
case 't': case 'T':
isTwirl = !isTwirl;
break;
case 'f':
img = iTrans.rotate90(img);
break;
case 'F':
img = iTrans.rotate90(img, c);
break;
case 'b':
img = iTrans.rotate90CCW(img);
break;
case 'B':
img = iTrans.rotate90CCW(img, c);
break;
case 'r':
img = iTrans.rotate180(img);
break;
case 'R':
img = iTrans.rotate180(img, c);
break;
case 'x':
img = iTrans.flipX(img);
break;
case 'X':
img = iTrans.flipX(img, c);
break;
case 'z':
img = iTrans.flipX90(img);
break;
case 'Z':
img = iTrans.flipX90(img, c);
break;
case 'c':
img = iTrans.flipX90CCW(img);
break;
case 'C':
img = iTrans.flipX90CCW(img, c);
break;
case 'y':
img = iTrans.flipY(img);
break;
case 'Y':
img = iTrans.flipY(img, c);
break;
case 'w':
// shows the sort of image size adjustments you may need when rotation is not a multiple of 90 degrees
iTrans.resizeGraphics(int(maxRotAdjust * startWidth + 1), int(maxRotAdjust * startHeight + 1));
img = iTrans.rotAndScale(img, 45 * DEG_TO_RAD, 1, 1);
img.save("temp.png");
break;
case 'W':
// shows the sort of image size adjustments you may need when rotation is not a multiple of 90 degrees
iTrans.resizeGraphics(int(maxRotAdjust * startWidth + 1), int(maxRotAdjust * startHeight + 1));
img = iTrans.rotAndScale(img, 45 * DEG_TO_RAD, 1, 1, c);
img.save("temp.png");
break;
case 'k': case 'K':
// reset the image size
PImage temp = createImage(startWidth, startHeight, ARGB);
temp.copy(img, (img.width - startWidth)/2, (img.height - startHeight)/2, startWidth, startHeight, 0, 0, startWidth, startHeight);
img = temp;
break;
case 'o': case 'O':
// reload the image
img = loadImage(imgFilename);
break;
case 's': case 'S':
save("display.png");
break;
case 'h': case 'H':
showHelp();
break;
default:
break;
}
}
public void showHelp() {
println("\n=====================------------->>>>> Key Command Help <<<<<-------------=====================");
println(" press 't' or 'T' to show animation.");
println(" press 'f' to rotate image 90 degrees CW, 'F' to fill background and rotate.");
println(" press 'b' to rotate image 90 degrees CCW, 'B' to fill background and rotate.");
println(" press 'r' to rotate image 180 degrees, 'R' to fill background and rotate.");
println(" press 'x' to flip x-coordinates, 'X' to fill background and flip.");
println(" press 'z' to flip x-coordinates and rotate 90 degrees CW, 'Z' to fill background, flip and rotate.");
println(" press 'c' to flip x-coordinates and rotate 90 degrees CCW, 'C' to fill background, flip and rotate.");
println(" press 'y' to flip y-coordinates, 'Y' to fill background and flip.");
println(" press 'w' to resize PGraphics and rotate image 45 degrees, 'W' to fill background, resize and flip.");
println(" press 'k' or 'K' to reset image size (use after 'w').");
println(" press 'o' or 'O' to reload the image from disk.");
println(" press 's' or 'S' to save the display to a PNG file.");
println(" press 'h' to show help.\n");
println("=====================------------->>>>><<<<<-------------=====================\n");
}
/* =====================------------->>>>><<<<<-------------===================== */
/* I recommend you put the ImageTransformType enum and the ImageTransform class */
/* in a separate tab in the Processing IDE. */
/* =====================------------->>>>><<<<<-------------===================== */
/**
* Enum with a list of the transforms that the ImageTransform class makes available: 90 rotations clockwise,
* 90 degree rotation counter-clockwise, 180 degree rotation, flipping x-coordinates (reflecting over the y-axis),
* flipping x-coordinates followed by 90 degree clockwise rotation, flipping x-coordinates followed by 90 degree
* counter-clockwise rotation, flipping y-coordinates (reflecting over the x-axis).
*/
public enum ImageTransformType {ROT90CW, ROT90CCW, ROT180, FLIPX, FLIPX90, FLIPX90CCW, FLIPY, NADA};
/**
* ImageTransform uses a PGraphics to do basic transforms on a PImage.
* Called by TransformTool.pde
*/
class ImageTransform {
PGraphics itGraf;
int itw = 1024;
int ith = 1024;
/**
* initializes a PGraphics with width = w and height = h.
*/
public ImageTransform(int w, int h) {
this.itw = w;
this.ith = h;
this.itGraf = createGraphics(itw, ith);
}
/**
* initializes a PGraphics with width = height = 1024.
*/
public ImageTransform() {
this(1024, 1024);
}
/**
* @return itGraf, the PGraphics instance used for transforms
*/
public PGraphics getGraphics() {
return this.itGraf;
}
/**
* @return the width of the PGraphics instance used for transforms
*/
public int getWidth() {
return this.itw;
}
/**
* @return the height of the PGraphics instance used for transforms
*/
public int getHeight() {
return this.ith;
}
/**
* @param img a PImage whose width and height will be used to set the width and height
* of the PGraphics instance used for transforms
*/
public void adjustToImage(PImage img) {
if (img.width != itw || img.height != ith) {
itw = img.width;
ith = img.height;
itGraf.setSize(itw, ith);
}
}
/**
* @param w the new width of the PGraphics instance used for transforms
* @param h the new height of the PGraphics instance used for transforms
*/
public void resizeGraphics(int w, int h) {
itw = w;
ith = h;
itGraf.setSize(itw, ith);
}
/**
* @param img a PImage to transform
* @param type the ImageTransformType (ROT90CW, ROT90CCW, ROT180, FLIPX, FLIPY)
* @return a transformed PImage from the PGraphics instance used for transforms
*/
public PImage transform(PImage img, ImageTransformType type) {
// the methods called will set itGraf width and height to image width and height
switch (type) {
case ROT90CW: {
img = rotate90(img);
break;
}
case ROT90CCW: {
img = rotate90CCW(img);
break;
}
case ROT180: {
img = rotate180(img);
break;
}
case FLIPX: {
img = flipX(img);
break;
}
case FLIPX90: {
img = flipX90(img);
break;
}
case FLIPX90CCW: {
img = flipX90CCW(img);
break;
}
case FLIPY: {
img = flipY(img);
break;
}
case NADA: {
break;
}
}
return img;
}
/**
* Rotates or reflects a PImage, as specified by the type argument.
*
* @param img a PImage to transform
* @param type the ImageTransformType (ROT90CW, ROT90CCW, ROT180, FLIPX, FLIPY)
* @param c the background color for the image (affects the alpha channel of the output)
* @return a transformed PImage from the PGraphics instance used for transforms
*/
public PImage transform(PImage img, ImageTransformType type, int c) {
// the methods called will set itGraf width and height to image width and height
switch (type) {
case ROT90CW: {
img = rotate90(img, c);
break;
}
case ROT90CCW: {
img = rotate90CCW(img, c);
break;
}
case ROT180: {
img = rotate180(img, c);
break;
}
case FLIPX: {
img = flipX(img, c);
break;
}
case FLIPX90: {
img = flipX90(img, c);
break;
}
case FLIPX90CCW: {
img = flipX90CCW(img, c);
break;
}
case FLIPY: {
img = flipY(img, c);
break;
}
case NADA: {
img = nada(img, c);
break;
}
}
return img;
}
/**
* Rotates and scales a PImage around its center.
* You may need to set width and height with resizeGraphics before calling this method,
* e.g., when rotating by and angle other than a multiple of pi/2 radians.
*
* @param img PImage to rotate and scale
* @param rads angle of rotation in radians
* @param sx x-axis scaling
* @param sy y-axis scaling
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotAndScale(PImage img, float rads, float sx, float sy) {
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.translate(itw / 2, ith / 2);
itGraf.scale(sx, sy);
itGraf.rotate(rads);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, (itw - img.width) / 2, (ith - img.height) / 2);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Rotates and scales a PImage around its center.
* You may need to set width and height with resizeGraphics before calling this method,
* e.g., when rotating by and angle other than a multiple of pi/2 radians.
*
* @param img PImage to rotate and scale
* @param rads angle of rotation in radians
* @param sx x-axis scaling
* @param sy y-axis scaling
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotAndScale(PImage img, float rads, float sx, float sy, int c) {
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.translate(itw / 2, ith / 2);
itGraf.scale(sx, sy);
itGraf.rotate(rads);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, (itw - img.width) / 2, (ith - img.height) / 2);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Rotates an image 90 degrees clockwise, returns a transformed copy
* @param img PImage to transform
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotate90(PImage img) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, 0, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Rotates an image 90 degrees clockwise, returns a transformed copy
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotate90(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, 0, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Rotates an image 90 degrees counter-clockwise, returns a transformed copy
* @param img PImage to transform
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotate90CCW(PImage img) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(-PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, 0, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Rotates an image 90 degrees counter-clockwise, returns a transformed copy
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotate90CCW(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(-PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, 0, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Rotates an image 180 degrees, returns a transformed copy
* @param img PImage to transform
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotate180(PImage img) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(PApplet.PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, 0, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Rotates an image 180 degrees, returns a transformed copy
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage rotate180(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(PApplet.PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.image(img, 0, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the y-axis, flipping the x-coordinates, returns a transformed copy
* @param img PImage to transform
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipX(PImage img) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.scale(-1, 1);
itGraf.image(img, -img.width, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the y-axis, flipping the x-coordinates, returns a transformed copy
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipX(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.scale(-1, 1);
itGraf.image(img, -img.width, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the y-axis, flipping the x-coordinates, rotates it 90 degrees CW and returns a transformed copy
* @param img PImage to transform
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipX90(PImage img) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.scale(-1, 1);
itGraf.image(img, -img.width, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the y-axis, flipping the x-coordinates, rotates it 90 degrees CW and returns a transformed copy
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipX90(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.scale(-1, 1);
itGraf.image(img, -img.width, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the y-axis, flipping the x-coordinates, rotates it 90 degrees CCW and returns a transformed copy
* @param img PImage to transform
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipX90CCW(PImage img) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(-PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.scale(-1, 1);
itGraf.image(img, -img.width, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the y-axis, flipping the x-coordinates, rotates it 90 degrees CCW and returns a transformed copy
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipX90CCW(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.translate(itw / 2, ith / 2);
itGraf.rotate(-PApplet.HALF_PI);
itGraf.translate(-itw / 2, -ith / 2);
itGraf.scale(-1, 1);
itGraf.image(img, -img.width, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the x-axis, flipping the y-coordinates, returns a transformed copy.
* Same as a flipX() followed by rotate180().
* @param img PImage to transform
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipY(PImage img) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
// itGraf.background(255);
itGraf.scale(1, -1);
itGraf.image(img, 0, -img.height);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Reflects an image on the x-axis, flipping the y-coordinates, returns a transformed copy
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage flipY(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.scale(1, -1);
itGraf.image(img, 0, -img.height);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
/**
* Leaves image geometry untransformed but possibly with a different background color (for images with an alpha channel)
* @param img PImage to transform
* @param c background color (may affect alpha channel of output)
* @return a PImage obtained from the PGraphics instance used for transforms
*/
public PImage nada(PImage img, int c) {
adjustToImage(img);
itGraf.beginDraw();
itGraf.pushMatrix();
itGraf.background(c);
itGraf.image(img, 0, 0);
itGraf.popMatrix();
itGraf.endDraw();
return itGraf.get();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment