#include "visualiser.h" /* write a png file */ int Visualiser::write_png(char *file_name,SDL_Surface *image) { FILE *fp; png_structp png_ptr; png_infop info_ptr; png_color_8 sig_bit; // png_colorp palette; int width = 755; unsigned int height =512; //341 /* open the file */ fp = fopen(file_name, "wb"); if (fp == NULL) return (-1); /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if (png_ptr == NULL) { fclose(fp); return (-1); } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, png_infopp_NULL); return (-1); } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { /* If we get here, we had a problem reading the file */ fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); return (-1); } /* set up the output control if you are using standard C streams */ png_init_io(png_ptr, fp); /* This is the hard way */ /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED */ png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* optional significant bit chunk */ /* if we are dealing with a grayscale image then */ //sig_bit.gray = true_bit_depth; /* otherwise, if we are dealing with a color image then */ sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; /* if the image has an alpha channel then */ //sig_bit.alpha = true_alpha_bit_depth; png_set_sBIT(png_ptr, info_ptr, &sig_bit); /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */ /* note that if sRGB is present the gAMA and cHRM chunks must be ignored * on read and must be written in accordance with the sRGB profile */ /* Write the file header information. REQUIRED */ png_write_info(png_ptr, info_ptr); /* If you want, you can write the info in two steps, in case you need to * write your private chunk ahead of PLTE: * * png_write_info_before_PLTE(write_ptr, write_info_ptr); * write_my_chunk(); * png_write_info(png_ptr, info_ptr); * * However, given the level of known- and unknown-chunk support in 1.1.0 * and up, this should no longer be necessary. */ png_set_packing(png_ptr); /* The easiest way to write the image (you may have a different memory * layout, however, so choose what fits your needs best). You need to * use the first method if you aren't handling interlacing yourself. */ png_uint_32 k;//, height, width; //wxLogMessage(_T("Surface data : bbp:%d"),image->format->BitsPerPixel); png_bytep row_pointers[512];//341 png_bytep imagep = ((Uint8 *)image->pixels); for (k = 0; k < height; k++) row_pointers[k] = imagep + k*((width+1)*3); png_write_image(png_ptr, row_pointers); /* You can write optional chunks like tEXt, zTXt, and tIME at the end * as well. Shouldn't be necessary in 1.1.0 and up as all the public * chunks are supported and you can use png_set_unknown_chunks() to * register unknown chunks into the info structure to be written out. */ /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end(png_ptr, info_ptr); /* clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, &info_ptr); /* close the file */ fclose(fp); /* that's it */ return (0); } Visualiser::Visualiser(int delay) : wxThread(wxTHREAD_DETACHED) { m_delay = delay; Create(); } void Visualiser::OnExit() { } void Visualiser::GetColour(int connectionSpeed, int &r, int &g, int &b) { switch(connectionSpeed) { case 10: r = 255; g = 0; b = 0; break; case 9: r = 0; g = 0; b = 255; break; case 8: r = 255; g = 0; b = 255; break; case 7: case 6: r = 255; g = 255; b = 0; break; case 5: r = 0; g = 255; b = 255; break; default: r = 0; g = 255; b = 0; break; } } wxThread::ExitCode Visualiser::Entry() { // do stuff in loop...draw to image file.... // load sample.png into image SDL_Surface *image; SDL_Surface *original; SDL_RWops *rwop; rwop=SDL_RWFromFile("map.png", "rb"); original=IMG_LoadPNG_RW(rwop); if(!original) { wxLogError("Visualiser: IMG_LoadPNG_RW: %s\n", IMG_GetError()); // handle error SDL_FreeRW(rwop); return (wxThread::ExitCode)-1; } SDL_FreeRW(rwop); int x = 0; int y = 0; int x2 = 0; int y2 = 0; int r,g,b,r2,g2,b2; r=g=b=0; r2=g2=b2=0; while(!TestDestroy()) { // copy original to new surface each time image = sge_copy_surface(original); users_mutex.Lock(); if (users->GetCount() < 1) wxLogMessage(_T("Visualiser: nothing to render")); for (unsigned int i=0; i < users->GetCount(); i++) { UserData *tempUser = &users->Item(i); // draw rect on this point GetCoordsAt(tempUser->longitude-180,tempUser->latitude-90,x,y); // GetColour(tempUser->connectionSpeed,r,g,b); r = g = b = 155; r2 = g2 = b2 = 155; sge_FilledRect(image,x-2,y-2,x+2,y+2, r,g,b); // draw line from here to next user.... if (tempUser->next!=NULL && tempUser->next!=tempUser) { //GetColour(tempUser->next->connectionSpeed,r2,g2,b2); GetCoordsAt(tempUser->next->longitude-180,tempUser->next->latitude-90,x2,y2); sge_AAmcLine(image,x,y,x2,y2, r,g,b, r2,g2,b2); } } users_mutex.Unlock(); wxLogMessage(_T("Visualiser: Writing map.")); //write_png("/home/www/html/nest/map.png",image); write_png("map2.png",image); //wxCopyFile("map2.png","/map.png",TRUE); // wxRemoveFile("map2.png"); SDL_FreeSurface(image); image = NULL; Sleep(m_delay); } return 0; } void Visualiser::GetCoordsAt(float longitude, float latitude, int &x, int &y) { latitude = ((latitude) * PI)/180.0f; float width = 755; float height = 512; float tempy = 0.5f * log((1+sin(latitude))/(1-sin(latitude))); tempy *= -120.73278908253292f; tempy += 350; y = (int)tempy; x = (int)((width/360.0f)*(longitude+180)); } void Visualiser::DrawPointAt(SDL_Surface *image, float longitude, float latitude, int i) { //float latitude = -90; //float longitude = 354-180; // offset y by -1.441487 so max becomes 0 then abs then scale y by 118.28063659262969 latitude = ((latitude) * PI)/180.0f; float width = 755; float height = 512; float y = 0.5f * log((1+sin(latitude))/(1-sin(latitude))); y *= -120.73278908253292f; y += 350; float x = (width/360.0f)*(longitude+180); //float yoffset = (height-341)/2.0f; //float yoffset = -143; sge_FilledRect(image, (int)x-2,(int)(y)-2, (int)x+2,(int)(y)+2, 255,(int)(i*2.8333333333333335),0); //wxLogMessage(_T("longitude %f latitude %f gives x,y = %f,%f"),longitude,latitude,x,y); }