1 /*-----------------------------------------------------------------------------
2 Code written by Francois Fleuret, using GCC & Emacs
4 Contact <francois.fleuret@inria.fr>
5 -----------------------------------------------------------------------------*/
9 /*---------------------------------------------------------------------------*/
14 Picture::Picture(int SX, int SY)
18 Body.resize(SizeX*SizeY*PIC_DEPTH);
22 Picture::Picture(Picture &v)
27 Body.resize(SizeX*SizeY*PIC_DEPTH);
28 for(i=0; i<SizeX*SizeY*PIC_DEPTH; i++) Body.set(i, v.Body.get(i));
31 Picture::~Picture() {}
33 void Picture::Blur(int s)
35 int nSizeX, nSizeY, x, y, xx, yy, c;
41 newBody.resize(nSizeX*nSizeY*PIC_DEPTH);
43 for(x=0; x<nSizeX; x++)
44 for(y=0; y<nSizeY; y++)
45 for(c=0; c<PIC_DEPTH; c++)
48 for(xx=x; (xx<x+2*s+1) || (xx<SizeX); xx++)
49 for(yy=y; (yy<y+2*s+1) || (yy<SizeY); yy++)
50 sum += Body.get(PIC_DEPTH*(xx+yy*SizeX)+c);
51 newBody.set(PIC_DEPTH*(x+y*nSizeX)+c, sum/((2*s+1)*(2*s+1)));
59 // renvoie la n-ieme composante du pixel (x, y)
60 float Picture::GetComponent(int x, int y, int n)
62 return Body.get(PIC_DEPTH*(x+y*SizeX)+n);
65 // Modifie la n-ieme composante du pixel (x, y)
66 void Picture::SetComponent(int x, int y, int n, float v)
68 Body.set(PIC_DEPTH*(x+y*SizeX)+n, v);
71 // Efface "graphiquement" l'image (i.e. met du noir partout)
77 void Picture::Fill(float v)
80 for(k=0; k<SizeX*SizeY*PIC_DEPTH; k++) Body.set(k, v);
83 void Picture::Reformat(int x, int y)
86 Body.resize(SizeX*SizeY*PIC_DEPTH);
89 // Detruit l'image (i.e. libere la memoire et met la size a 0)
96 void Picture::Reverse()
99 for(k=0; k<SizeX*SizeY*PIC_DEPTH; k++) Body.set(k, 1 - Body.get(k));
106 for(x = 0; x<SizeX; x++)
107 for(y = 0; y<SizeY; y++)
108 if(GetComponent(x, y, PIC_BLUE) < 0.999)
111 for(c=0; c<PIC_DEPTH; c++) v += GetComponent(x, y, c);
113 for(c=0; c<PIC_DEPTH; c++) SetComponent(x, y, c, v);
117 void Picture::AddBorders(int w, float r, float g, float b)
119 int nSizeX, nSizeY, x, y, d;
122 nSizeX = SizeX + 2*w;
123 nSizeY = SizeY + 2*w;
125 nBody.resize(nSizeX*nSizeY*PIC_DEPTH);
127 for(d = 0; d<nSizeX*nSizeY; d++)
129 nBody.set(d*PIC_DEPTH + PIC_RED, r);
130 nBody.set(d*PIC_DEPTH + PIC_GREEN, g);
131 nBody.set(d*PIC_DEPTH + PIC_BLUE, b);
134 for(x = 0; x<SizeX; x++)
135 for(y = 0; y<SizeY; y++)
136 for(d = 0; d<PIC_DEPTH; d++)
137 nBody.set(PIC_DEPTH*((x+w)+(y+w)*nSizeX)+d,
138 Body.get(PIC_DEPTH*(x+y*SizeX)+d));
145 #define ATTEND_MODEP 0
147 #define ATTEND_SCALE 2
148 #define LOAD_PIXELS 3
150 #define MODE_UNKNOWN -1
154 void Picture::LoadPpm(char *file_name)
156 char buffer[BUFFER_SIZE];
160 unsigned char ch, *cht;
164 from = fopen(file_name, "r");
166 modeP = MODE_UNKNOWN;
176 fscanf(from, "%c", &ch);
177 if(ch != '\n') buffer[k++] = ch;
178 else buffer[k++] = '\0';
181 if(strlen(buffer)>0) if(buffer[0] != '#')
186 if(strcmp("P5", buffer) == 0)
191 else if(strcmp("P6", buffer) == 0)
196 else cerr<<"Picture::LoadPpm ERROR, not P5 or P6 format\n";
200 sscanf(buffer, "%d %d", &x, &y);
205 Body.resize(SizeX*SizeY*PIC_DEPTH);
207 else cerr<<"Picture::LoadPpm ERROR, incoherent size\n";
212 sscanf(buffer, "%d", &s);
218 while(mode != LOAD_PIXELS);
220 if((Body.size != 0) && (s>0))
222 cht = new unsigned char[SizeX*PIC_DEPTH];
228 for(y=0; y<SizeY; y++)
230 fread(cht, sizeof(unsigned char), SizeX, from);
231 for(x=0; x<SizeX; x++)
232 for(c=0; c<PIC_DEPTH; c++)
233 SetComponent(x, y, c, float(cht[x])/s);
237 for(y=0; y<SizeY; y++)
239 fread(cht, sizeof(unsigned char), SizeX*PIC_DEPTH, from);
240 for(x=0; x<SizeX; x++)
241 for(c=0; c<PIC_DEPTH; c++)
242 SetComponent(x, y, c,
243 float(cht[x*PIC_DEPTH+c])/s);
247 cerr<<"Unknown format in LoadPpm\n";
253 else cerr<<"Creation error : memory allocation failed\n";
257 else cerr<<"Picture::LoadPpm fopen ERROR\n";
260 void Picture::SavePpm(char *file_name)
266 to = fopen(file_name, "w");
270 fprintf(to, "# Created with Pictures::SavePpm, Contact <francois.fleuret@inria.fr> for infos.\n");
271 fprintf(to, "%d %d\n", SizeX, SizeY);
272 fprintf(to, "255\n");
275 for(y=0; y<SizeY; y++)
276 for(x=0; x<SizeX; x++)
277 for(c=0; c<PIC_DEPTH; c++)
279 ch = (unsigned char) (255*GetComponent(x, y, c));
280 fwrite(&ch, sizeof(ch), 1, to);
283 else cerr<<"Picture::SavePpm fopen ERROR\n";
286 void Picture::ReSize(int nx, int ny)
288 Array<float> newBody;
289 int x, y, c, dx, dy, tt1, ss1, tt2, ss2;
290 float s1, s2, t1, t2, sx, sy;
294 newBody.resize(nx*ny*PIC_DEPTH);
296 for(x=0; x<nx; x++) for(y=0; y<ny; y++)
297 for(c=0; c<PIC_DEPTH; c++)
298 newBody.set((y*nx+x)*PIC_DEPTH+c, 0);
300 for(x=0; x<SizeX; x++) for(y=0; y<SizeY; y++)
302 t1 = float(x)*nx/SizeX;
303 t2 = float(x+0.9999)*nx/SizeX;
304 s1 = float(y)*ny/SizeY;
305 s2 = float(y+0.9999)*ny/SizeY;
307 tt1 = int(t1); tt2 = int(t2); ss1 = int(s1); ss2 = int(s2);
310 if((ss1 < 0) || (ss1 >= ny) || (ss2 < 0) || (ss2 >= ny) ||
311 (tt1 < 0) || (tt1 >= nx) || (tt2 < 0) || (tt2 >= nx))
313 cerr<<"ss1 out of boudaries in Picture::ReSize()\n";
318 sx = (tt2 - t1)*SizeX/nx;
319 sy = (ss2 - s1)*SizeY/nx;
324 for(c=0; c<PIC_DEPTH; c++)
325 newBody.set((ss1*nx+tt1)*PIC_DEPTH+c,
326 newBody.get((ss1*nx+tt1)*PIC_DEPTH+c) + GetComponent(x, y, c));
329 for(c=0; c<PIC_DEPTH; c++)
331 newBody.set((ss1*nx+tt1)*PIC_DEPTH+c,
332 newBody.get((ss1*nx+tt1)*PIC_DEPTH+c) + sy*GetComponent(x, y, c));
333 newBody.set((ss2*nx+tt1)*PIC_DEPTH+c,
334 newBody.get((ss2*nx+tt1)*PIC_DEPTH+c) + (1-sy)*GetComponent(x, y, c));
342 for(c=0; c<PIC_DEPTH; c++)
344 newBody.set((ss1*nx+tt1)*PIC_DEPTH+c,
345 newBody.get((ss1*nx+tt1)*PIC_DEPTH+c) + sx*GetComponent(x, y, c));
346 newBody.set((ss1*nx+tt2)*PIC_DEPTH+c,
347 newBody.get((ss1*nx+tt2)*PIC_DEPTH+c) + (1-sx)*GetComponent(x, y, c));
352 for(c=0; c<PIC_DEPTH; c++)
354 newBody.set((ss1*nx+tt1)*PIC_DEPTH+c,
355 newBody.get((ss1*nx+tt1)*PIC_DEPTH+c) + sx*sy*GetComponent(x, y, c));
357 newBody.set((ss2*nx+tt1)*PIC_DEPTH+c,
358 newBody.get((ss2*nx+tt1)*PIC_DEPTH+c) + sx*(1-sy)*GetComponent(x, y, c));
360 newBody.set((ss1*nx+tt2)*PIC_DEPTH+c,
361 newBody.get((ss1*nx+tt2)*PIC_DEPTH+c) + (1-sx)*sy*GetComponent(x, y, c));
363 newBody.set((ss2*nx+tt2)*PIC_DEPTH+c,
364 newBody.get((ss2*nx+tt2)*PIC_DEPTH+c) + (1-sx)*(1-sy)*GetComponent(x, y, c));
370 for(x=0; x<nx; x++) for(y=0; y<ny; y++)
371 for(c=0; c<PIC_DEPTH; c++)
372 newBody.set((y*nx+x)*PIC_DEPTH+c, newBody.get((y*nx+x)*PIC_DEPTH+c) / (float(SizeX)/nx * float(SizeY)/ny));
379 void Picture::Cut(int x, int y, int w, int h, Picture &src)
383 Body.resize(SizeX*SizeY*PIC_DEPTH);
384 Copy(0, 0, x, y, w, h, src);
387 void Picture::Copy(int xd, int yd, int xs, int ys, int w, int h, Picture &src)
392 if((xd<0) || (xd+w>SizeX) || (yd<0) || (yd+h > SizeY))
394 cerr<<"Parameters error in Picture::Copy()\n";
398 if((xs<0) || (xs+w>src.SizeX) || (ys<0) || (ys+h > src.SizeY))
400 cerr<<"Parameters error in Picture::Copy()\n";
405 for(i=0; i<w; i++) for(j=0; j<h; j++)
406 for(c=0; c<PIC_DEPTH; c++)
407 Body.set(((yd+j)*SizeX+(xd+i))*PIC_DEPTH+c, src.Body.get(((ys+j)*src.SizeX+(xs+i))*PIC_DEPTH+c));
410 int Picture::operator == (Picture &src)
413 if((SizeX == src.SizeX) && (SizeY == src.SizeY))
416 for(i=0; (i<SizeX) && r; i++) for(j=0; (j<SizeY) && r; j++)
417 for(c=0; (c<PIC_DEPTH) && r; c++)
418 r = Body.get((j*SizeX+i)*PIC_DEPTH+c) ==
419 src.Body.get((j*SizeX+i)*PIC_DEPTH+c);
426 void Picture::operator = (Picture &src)
432 Body.resize(SizeX*SizeY*PIC_DEPTH);
433 for(i=0; i<SizeX*SizeY*PIC_DEPTH; i++) Body.set(i, src.Body.get(i));
436 float Picture::DistanceL2(Picture *p)
440 if((SizeX == p->SizeX) && (SizeY == p->SizeY))
443 for(x=0; x<SizeX; x++)
444 for(y=0; y<SizeY; y++)
445 for(c=0; c<PIC_DEPTH; c++)
447 d = Body.get(PIC_DEPTH*(x+y*SizeX)+c) - p->Body.get(PIC_DEPTH*(x+y*SizeX)+c);
454 cerr<<"Norme L2 entre des images de tailles differentes\n";
459 /*---------------------------------------------------------------------------*/