Programació d'efectes en imatges en Processing

Índex
- Introducció
- Objectius
- 1.Imatges en Processing
- 2.Transformacions puntuals
- 3.Transformacions espacials lineals
- 3.1.Identitat
- 3.2.Negatiu
- 3.3.Suavització
- 3.4.Contorns
- 4.Transformacions espacials no lineals
- 4.1.Erosió
- 4.2.Dilatació
- 4.3.Obertura i tancament
- 5.Transformacions geomètriques
- 5.1.Zoom i delmació
- 5.2.Translació
- 5.3.Rotació
- 5.4.Composició de transformacions
- Activitats
- Bibliografia
Introducció
Objectius
-
Introduir la programació de les transformacions puntuals, espacials lineals, espacials no lineals i geomètriques.
-
Explorar les possibilitats del llenguatge Processing pel que fa a aquestes programacions.
-
Relacionar, mitjançant experiments dirigits, els conceptes introduïts amb la transformació d'imatges.
1.Imatges en Processing
1.1.Càrrega i visualització d'imatges en Processing
/** * Exemple 1: Càrrega i visualització d'una imatge * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 */ // Declarem un objecte de tipus PImage PImage img; void setup() { // Assignem a la finestra de treball les mateixes mides que la imatge size(696,696); // Carreguem la imatge img = loadImage("geranidolor.jpg"); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { //La funció image() permet visualitzar la imatge a la finestra de l'aplicació image(img,0,0); }
PImage img;
img = loadImage("geranidolor.jpg");
image(img,0,0);

1.2.Imatges i píxels
![Figura 2. Relació entre la quadrícula de píxels i l'array pixels[].](http://materials.cv.uoc.edu/daisy/Materials/PID_00235961/html5/img/17066_m5_002.gif)
/** * Exemple 2: Imatges i Píxels (I) * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; void setup() { // Assignem a la finestra de treball les mateixes mides que la imatge size(696, 696); // Carreguem la imatge img = loadImage("geranidolor.jpg"); // Sempre hem de cridar aquesta funció abans d'accedir a l'array de píxels img.loadPixels(); } void draw() { //La funció image() permet visualitzar la imatge image(img, 0, 0); } void mousePressed() { // La variable loc serveix per "localitzar" el píxel seleccionat dins // l'array de pixels int loc = mouseX + mouseY * img.width; // Extraiem el color del píxel color c = img.pixels[loc]; // Aquestes funcions permeten consultar les components R, G i B d'un color float r = red(c); float g = green(c); float b = blue(c); // Finalment, imprimim el resultat a la finestra de la Console println("El valor RGB del píxel (" + mouseX + ", " + mouseY + ") és (" + r + ", " + g + ", " + b + ")"); }
img.loadPixels();
int loc = mouseX + mouseY * img.width;
// Extraiem el color del píxel color c = img.pixels[loc]; // Aquestes funcions permeten consultar les components R, G i B d'un color float r = red(c); float g = green(c); float b = blue(c);
// Aquestes funcions permeten consultar les components R, G i B d'un color float r = img.pixels[loc] >> 16 & 0xFF; float g = img.pixels[loc] >> 8 & 0xFF; float b = img.pixels[loc] & 0xFF;
/** * Exemple 3: Imatges i Píxels (II) * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem dos objectes de tipus PImage, un per la imatge original // i un altre per la imatge filtrada PImage imgOriginal; PImage imgFilter; void setup() { // Carreguem la imatge imgOriginal = loadImage("geranidolor.jpg"); // Creem una nova imatge amb les mateixes dimensions que la imatge original imgFilter = createImage(imgOriginal.width, imgOriginal.height, RGB); // Assignem a la finestra de treball les mateixes mides que la imatge surface.setSize(imgOriginal.width, imgOriginal.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Com sempre, hem de cridar aquestes funcions abans d'accedir a l'array // de píxels de les imatges imgOriginal.loadPixels(); imgFilter.loadPixels(); int loc= 0; // Recorrem tots els píxels de la imatge while (loc < imgOriginal.pixels.length) { // Aquestes funcions permeten consultar les components R, G i B d'un color float r = imgOriginal.pixels[loc] >> 16 & 0xFF; float g = imgOriginal.pixels[loc] >> 8 & 0xFF; float b = imgOriginal.pixels[loc] & 0xFF; // A la imatge filtrada només importem el valor del nivell R (vermell) // i els altres dos els deixem amb nivell 0 imgFilter.pixels[loc] = color(r, 0, 0); loc++; } // Si fem modificacions sobre els píxels, sempre hem d'actualitzar l'array // de píxels amb la funció updatePixels() imgFilter.updatePixels(); // La funció image() permet visualitzar la imatge filtrada image(imgFilter, 0, 0); // Guardem el resultat a la carpeta "data" del projecte imgFilter.save(dataPath("geranidolor2.jpg")); }
PImage imgOriginal; PImage imgFilter;
imgFilter = createImage(imgOriginal.width, imgOriginal.height, RGB);
imgFilter.pixels[loc] = color(r, 0, 0);
imgFilter.updatePixels();
imgFilter.save(dataPath("geranidolor2.jpg"));
imgFilter.save(dataPath("geranidolor2"));
surface.setSize(imgOriginal.width, imgOriginal.height);
size(imgOriginal.width, imgOriginal.height);

1.3.El mètode filter() de PImage
img.filter(filterName, parametre);
img.filter(GRAY);
img.filter(THRESHOLD, 0.3);
-
THRESHOLD: és la transformació de binarització, on el valor del llindar va de 0.0 (0) a 1.0 (255). Aquest mètode necessita paràmetre.
-
GRAY: converteix una imatge en color a escala de grisos. No necessita paràmetre.
-
OPAQUE: fa completament opaca una imatge. No necessita paràmetre.
-
INVERT: és la transformació en negatiu. No necessita paràmetre.
-
POSTERIZE: limita el nombre de colors de cada canal. El valor del paràmetre estableix aquest límit, i pot variar entre 2 i 255.
-
BLUR: aplica un filtre de tipus Guassian blur, amb el radi especificat en el segon paràmetre. Si no s'inclou el segon paràmetre, el valor del radi del filtre és 1. Com més gran sigui el radi, més acusat serà el filtrat.
-
ERODE: aplica la transformació espacial no lineal erosió. No necessita paràmetre.
-
DILATE: aplica la transformació espacial no lineal dilatació. No necessita paràmetre.
/** * Exemple 4: Filtre GRAY * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; void setup() { // Carreguem la imatge img = loadImage("geranidolor.jpg"); // Assignem a la finestra de treball les mateixes mides que la imatge surface.setSize(img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Apliquem el filtre GRAY a la imatge img.filter(GRAY); //La funció image() permet visualitzar la imatge filtrada image(img, 0, 0); // Guardem el resultat a la carpeta "data" del projecte img.save(dataPath("geranidolor2.jpg")); }

/** * Exemple 5: Filtre POSTERIZE * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; void setup() { // Carreguem la imatge img = loadImage("geranidolor.jpg"); // Assignem a la finestra de treball les mateixes mides que la imatge surface.setSize(img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Apliquem el filtre POSTERIZE a la imatge img.filter(POSTERIZE, 6); //La funció image() permet visualitzar la imatge filtrada image(img, 0, 0); // Guardem el resultat a la carpeta "data" del projecte img.save(dataPath("geranidolor2.jpg")); }

2.Transformacions puntuals
2.1.Identitat
/** * Exemple 6: Transformació Puntual Identitat, * per imatges en escala de grisos * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem dos objectes de tipus PImage, un per la imatge original // i un altre per la imatge filtrada PImage imgOriginal; PImage imgFilter; void setup() { // Carreguem la imatge imgOriginal = loadImage("4.1.02.png"); // Creem una nova imatge amb les mateixes dimensions que // la imatge original imgFilter = createImage(imgOriginal.width, imgOriginal.height, RGB); // Les mides de la finestra de treball permetran visualitzar // les dues imatges alhora surface.setSize(2*imgOriginal.width, imgOriginal.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Com sempre, hem de cridar aquestes funcions abans d'accedir a // l'array de píxels de les imatges imgOriginal.loadPixels(); imgFilter.loadPixels(); int loc= 0; // Recorrem tots els píxels de la imatge while (loc < imgOriginal.pixels.length) { // En ser una imatge en escala de grisos, R = G = B // Així que tenim suficient consultant un dels canals RGB float b = imgOriginal.pixels[loc] & 0xFF; // Algoritme - Transformació Puntual (Identitat) imgFilter.pixels[loc] = color(b); loc++; } // Si fem modificacions sobre els píxels, sempre hem d'actualitzar // l'array amb la funció updatePixels() imgFilter.updatePixels(); // La funció image() permet visualitzar les dues imatges image(imgOriginal, 0, 0); image(imgFilter, imgOriginal.width, 0); // Guardem la imatge transformada a la carpeta "data" del projecte imgFilter.save(dataPath("imgFilter.png")); }
surface.setSize(2*imgOriginal.width, imgOriginal.height);
float b = imgOriginal.pixels[loc] & 0xFF;
imgFilter.pixels[loc] = color(b);

2.2.Negatiu
// Algoritme - Transformació Puntual (Negatiu) imgFilter.pixels[loc] = color(255-b);

2.3.Binarització
// Declarem dos objectes de tipus PImage, un per la imatge original // i un altre per la imatge filtrada PImage imgOriginal; PImage imgFilter; // Llindar int llindarValue = 20;
// Algoritme - Transformació Puntual (Binarització) if (b < llindarValue) { imgFilter.pixels[loc] = color(0); } else { imgFilter.pixels[loc] = color(255); }

2.4.Transformacions d'aclariment i enfosquiment de la imatge

// Amb aquests valors, definim la forma de la corba d'aclariment i enfosquiment intx0 = 23; intx1 = 250; inty0 = 65; inty1 = 240;
// Algoritme - Transformació Puntual (Aclariment i Enfosquiment) if (b < x0 ) { imgFilter.pixels[loc] = color(int(map(b, 0, x0, 0, y0))); } else if ( b < x1 ) { imgFilter.pixels[loc] = color(int(map(b, x0, x1, y0, y1))); } else { imgFilter.pixels[loc] = color(int(map(b, x1, 255, y1, 255))); }
/** * Exemple 9: Transformació Puntual Aclariment i Enfosquiment per parts, * per imatges en escala de grisos * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem dos objectes de tipus PImage, un per la imatge original // i un altre per la imatge filtrada PImage imgOriginal; PImage imgFilter; // Amb aquests valors, definim la forma de la corba d'aclariment i enfosquiment intx0 = 23; intx1 = 250; inty0 = 65; inty1 = 240; void setup() { // Carreguem la imatge imgOriginal = loadImage("4.1.02.png"); // Creem una nova imatge amb les mateixes dimensions que la imatge original imgFilter = createImage(imgOriginal.width, imgOriginal.height, RGB); // Les mides de la finestra de treball permetran visualitzar // les dues imatges alhora surface.setSize(2*imgOriginal.width, imgOriginal.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Com sempre, hem de cridar aquestes funcions abans d'accedir a // l'array de píxels de les imatges imgOriginal.loadPixels(); imgFilter.loadPixels(); int loc= 0; // Recorrem tots els píxels de la imatge while (loc < imgOriginal.pixels.length) { // En ser una imatge en escala de grisos, R = G = B // Així que tenim suficient consultant un dels canals RGB float b = imgOriginal.pixels[loc] & 0xFF; // Algoritme - Transformació Puntual (Aclariment i Enfosquiment) if ( b < x0 ) { imgFilter.pixels[loc] = color(int(map(b, 0, x0, 0, y0))); } else if ( b < x1 ) { imgFilter.pixels[loc] = color(int(map(b, x0, x1, y0, y1))); } else { imgFilter.pixels[loc] = color(int(map(b, x1, 255, y1, 255))); } loc++; } // Si fem modificacions sobre els píxels, sempre hem d'actualitzar // l'array amb la funció updatePixels() imgFilter.updatePixels(); // La funció image() permet visualitzar les dues imatges image(imgOriginal, 0, 0); image(imgFilter, imgOriginal.width, 0); // Guardem el resultat a la carpeta "data" del projecte imgFilter.save(dataPath("imgFilter.png")); }

3.Transformacions espacials lineals
// Recorrem tots els píxels de la imatge while (loc < imgOriginal.pixels.length) {
// Recorrem tots els píxels de la imatge for (int x = 0; x < imgOriginal.width; x++) { for (int y = 0; y < imgOriginal.height; y++) {
int loc = x + y * imgOriginal.width;
3.1.Identitat
/** * Exemple 10: Transformació espacial lineal Identitat, *per imatges en escala de grisos * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem dos objectes de tipus PImage, un per la imatge original // i un altre per la imatge filtrada PImage imgOriginal; PImage imgFilter; // Màscara de convolució (Identitat) expressada com a matriu float[][] matrix = { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }; // Dimensió de la màscara de convolució int matrixsize = 3; // Correcció desplaçament int offset = 0; void setup() { // Carreguem la imatge imgOriginal = loadImage("4.2.06.png"); // Creem una nova imatge amb les mateixes dimensions que la imatge original imgFilter = createImage(imgOriginal.width, imgOriginal.height, RGB); // Les mides de la finestra de treball permetran visualitzar // les dues alhora surface.setSize(2*imgOriginal.width, imgOriginal.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Com sempre, hem de cridar aquestes funcions abans d'accedir a // l'array de píxels de les imatges imgOriginal.loadPixels(); imgFilter.loadPixels(); // Recorrem tots els píxels de la imatge for (int x = 0; x < imgOriginal.width; x++) { for (int y = 0; y < imgOriginal.height; y++) { // Càlcul de la convolució espacial int c = convolution(x, y, matrix, matrixsize, offset, imgOriginal); // Generem un nou píxel a la imatge filtrada int loc = x + y * imgOriginal.width; imgFilter.pixels[loc] = color(c); } } // Si fem modificacions sobre els píxels, sempre hem d'actualitzar // l'array amb la funció updatePixels() imgFilter.updatePixels(); // La funció image() permet visualitzar les dues imatges image(imgOriginal, 0, 0); image(imgFilter, imgOriginal.width, 0); // Guardem el resultat a la carpeta "data" del projecte imgFilter.save(dataPath("imgFilter.png")); } // Funció que calcula la convolució espacial int convolution(int x, int y, float[][] matrix, int matrixsize, int offset, PImage img) { float result = 0.0; int half = matrixsize / 2; // Recorrem la matriu de convolució for (int i = 0; i < matrixsize; i++) { for (int j = 0; j < matrixsize; j++) { // Càlcul del píxel sobre el que estem treballant int xloc = x + i - half; int yloc = y + j - half; int loc = xloc + img.width * yloc; // Ens assegurem que agafem un píxel dintre del rang vàlid. En aquest cas estem aplicant la // replicació de valors de píxels propers per localitzacions de píxels que surten de la imatge loc = constrain(loc, 0, img.pixels.length-1); // Càlcul de l'operació convolució // Consultem el valor del canal blue (B) result += ((imgOriginal.pixels[loc] & 0xFF) * matrix[i][j]); } } // Apliquem el desplaçament result += offset; // Ens assegurem que el nivell de gris està en el rang (0, 255) result = constrain(result, 0, 255); // Retornem el nivell de gris return (int)result; }
// Màscara de convolució (Identitat) expressada com a matriu float[][] matrix = { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }; // Dimensió de la màscara de convolució int matrixsize = 3; // Correcció desplaçament int offset = 0;
for (int x = 0; x < imgOriginal.width; x++) { for (int y = 0; y < imgOriginal.height; y++) {
int c = convolution(x, y, matrix, matrixsize, offset, imgOriginal);
int loc = x + y * imgOriginal.width; imgFilter.pixels[loc] = color(c);
int convolution(int x, int y, float[][] matrix, int matrixsize, int offset, PImage img)

3.2.Negatiu
// Màscara de convolució Negatiu expressada com a matriu float[][] matrix = { { 0, 0, 0 }, { 0, -1, 0 }, { 0, 0, 0 } }; // Dimensió de la màscara de convolució int matrixsize = 3; // Correcció desplaçament int offset = 255;

3.3.Suavització
// Màscara de convolució Suavització, expressada com a matriu float[][] matrix = { { 1/9f, 1/9f, 1/9f }, { 1/9f, 1/9f, 1/9f }, { 1/9f, 1/9f, 1/9f } }; // Dimensió de la màscara de convolució int matrixsize = 3; // Correcció desplaçament int offset = 0;

3.4.Contorns
// Màscara de convolució Contorns (detecció) expressada com a matriu float[][] matrix = { { -1, -1, -1 }, { -1, 8, -1 }, { -1, -1, -1 } }; // Dimensió de la màscara de convolució int matrixsize = 3; // Correcció desplaçament int offset = 128;

// Màscara de convolució Contorns (realçament) expressada com a matriu float[][] matrix = { { -1, -1, -1 }, { -1, 9, -1 }, { -1, -1, -1 } }; // Dimensió de la màscara de convolució int matrixsize = 3; // Correcció desplaçament int offset = 0;

4.Transformacions espacials no lineals
4.1.Erosió
/** * Exemple 15: Transformació espacial no lineal Erosió * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; void setup() { // Carreguem la imatge img = loadImage("faces.png"); // Les mides de la finestra de treball permetran visualitzar // la imatge original i la imatge filtrada surface.setSize(2*img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Visualitzem la imatge abans de filtrar image(img, 0, 0); // Apliquem el filtre, amb el mètode Erosió img.filter(ERODE); // Visualitzem la imatge després de filtrar image(img, img.width, 0); // Guardem el resultat de la transformació a la carpeta "data" del projecte img.save(dataPath("imgFilter2.png")); }

4.2.Dilatació
// Apliquem el filtre, amb el mètode Dilatació img.filter(DILATE);

4.3.Obertura i tancament
/** * Exemple 17: Transformació espacial no lineal Obertura * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; void setup() { // Carreguem la imatge img = loadImage("faces.png"); // Les mides de la finestra de treball permetran visualitzar // la imatge original i la imatge filtrada surface.setSize(2*img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Visualitzem la imatge abans de filtrar image(img, 0, 0); // Apliquem el filtre, amb el mètode Erosió img.filter(ERODE); // Apliquem el filtre, amb el mètode Dilatació img.filter(DILATE); // Visualitzem la imatge després de filtrar image(img, img.width, 0); // Guardem el resultat de la transformació a la carpeta "data" del projecte img.save(dataPath("imgFilter2.png")); }

// Apliquem el filtre, amb el mètode Dilatació img.filter(DILATE); // Apliquem el filtre, amb el mètode Erosió img.filter(ERODE);

5.Transformacions geomètriques
5.1.Zoom i delmació
/** * Exemple 19: Transformació geomètrica Zoom i Delmació * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; // Per valors > 1 apliquem un zoom, valors < 1 una delmació float resizeValue = 1.5; void setup() { // Carreguem la imatge img = loadImage("4.1.04.png"); // Les mides de la finestra de treball han de permetre visualitzar // la imatge original i la imatge transformada surface.setSize(int((resizeValue+1)*img.width), int(max(resizeValue,1)*img.height)); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Visualitzem la imatge abans d'ampliar image(img, 0, 0); // Apliquem la transformació geomètrica "resize" img.resize(int(resizeValue*img.width), int(resizeValue*img.height)); // Visualitzem la imatge després d'aplicar-li la transformació image(img, img.width/resizeValue, 0); // Guardem el resultat de la transformació a la carpeta "data" del projecte img.save(dataPath("imgFilter2.png")); }

float resizeValue = 0.5;

/** * Exemple 20: Transformació Scale * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; // Valor de l'escala float scaleValue = 0.5; void setup() { // Carreguem la imatge img = loadImage("4.1.04.png"); // Mides de la finestra de treball surface.setSize(int(scaleValue*img.width), int(scaleValue*img.height)); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Modifica les dimensions del sistema de coordenades, però no modifica // les dimensions de la imatge scale(scaleValue); // Visualitzem la imatge image(img, 0, 0); // Guardem la imatge a la carpeta "data" del projecte img.save(dataPath("img2.png")); }
5.2.Translació
/** * Exemple 21: Transformació Translació * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; // Coordenades del nou origen int coorX = 40; int coorY = 40; void setup() { // Carreguem la imatge img = loadImage("4.1.04.png"); // Mides de la finestra de treball surface.setSize(img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Movem el sistema de coordenades translate(coorX, coorY); // Visualitzem la imatge image(img, 0, 0); // Guardem el contingut de la finestra de l'aplicació com imatge // a la carpeta "data" del projecte save(dataPath("img2.png")); }

// Mides de la finestra de treball surface.setSize(img.width+ coorX, img.height+ coorY);
img.save(dataPath("img2.png"));
save(dataPath("img2.png"));
img.save(dataPath("img2.png"));
filter(GRAY);
img.save(dataPath("img2.png"));
5.3.Rotació
/** * Exemple 22: Transformació Rotació * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; // Valor de la rotació float rotateValue = PI/10; void setup() { // Carreguem la imatge img = loadImage("4.1.04.png"); // Mides de la finestra de treball surface.setSize(img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Rotem el sistema de coordenades rotate(rotateValue); // Visualitzem la imatge image(img, 0, 0); // Guardem el contingut de la finestra de l'aplicació com imatge // a la carpeta "data" del projecte save(dataPath("img2.png")); }

5.4.Composició de transformacions
/** * Exemple 23: Composició de Transformacions (I) * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; // Valor de l'escala float scaleValue = 0.5; // Coordenades del nou origen int coorX = 200; int coorY = 100; // Valor de la rotació float rotateValue = PI/10; void setup() { // Carreguem la imatge img = loadImage("4.1.04.png"); // Mides de la finestra de treball surface.setSize(img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Modifica les dimensions del sistema de coordenades, però no modifica // les dimensions de la imatge scale(scaleValue); // Movem el sistema de coordenades translate(coorX, coorY); // Rotem el sistema de coordenades rotate(rotateValue); // Visualitzem la imatge image(img, 0, 0); // Guardem el contingut de la finestra de l'aplicació com imatge // a la carpeta "data" del projecte save(dataPath("img2.png")); }

/** * Exemple 24: Composició de Transformacions (II) * Francesc Martí, martifrancesc@uoc.edu, 15-04-2016 * */ // Declarem un objecte de tipus PImage PImage img; // Valor de l'escala float scaleValue = 0.5; // Coordenades del nou origen int coorX = 200; int coorY = 100; // Valor de la rotació float rotateValue = PI/10; void setup() { // Carreguem la imatge img = loadImage("4.1.04.png"); // Mides de la finestra de treball surface.setSize(img.width, img.height); // La funció draw() s'executarà només una vegada noLoop(); } void draw() { // Aquesta transformació afecta a les dues imatges que visualitzarem scale(scaleValue); pushMatrix(); // Movem el sistema de coordenades translate(coorX, coorY); // Rotem el sistema de coordenades rotate(rotateValue); // Visualitzem la imatge image(img, 0, 0); popMatrix(); // Visualitzem un altre cop la imatge image(img, 0, 0); // Guardem el contingut de la finestra de l'aplicació com imatge // a la carpeta "data" del projecte save(dataPath("img2.png")); }
Activitats

