void Application::onKey(int key, int scancode, int action, int mods) {
    InputEvent& e = inputEvent;
    e.type = InputType::Key;
    e.action = action;
    e.key = key;
    e.scancode = scancode;
    e.mods = mods;
    e.cursor = context->cursorPosition;
    if (key == GLFW_KEY_F11 && e.action == GLFW_PRESS) {
        for (int i = 0; i < 1000; i++) {
            std::string screenShot = MakeString() << GetDesktopDirectory()
                                     << ALY_PATH_SEPARATOR<<"screenshot"<<std::setw(4)<<std::setfill('0')<<i<<".png";
            if(!FileExists(screenShot)) {
                std::cout<<"Saving "<<screenShot<<std::endl;
                ImageRGBA img;
                getScreenShot(img);
                FlipVertical(img);
                WriteImageToFile(screenShot,img);
                break;
            }
        }
    }

    fireEvent(e);
}
void Application::runOnce(const std::string& fileName) {
    close();
    run(0);
    glfwSwapBuffers(context->window);
    ImageRGBA img;
    getScreenShot(img);
    FlipVertical(img);
    WriteImageToFile(fileName, img);
}
void MedianFilter(char FilterShape, int FilterSize, const unsigned char* ImageData, unsigned char* ImageDataOut, int SizeI, int SizeJ, int BytesPerPixel)
{

    int Margin = FilterSize/2;
    int ExpandedI = SizeI + 2*Margin;
    int ExpandedJ = SizeJ + 2*Margin;
    unsigned char ExpandedImage[ExpandedI][ExpandedJ][BytesPerPixel];
    // Construct Expanded Image
    ImageExpandRepeat(Margin, ImageData, &ExpandedImage[0][0][0], SizeI, SizeJ, BytesPerPixel);

    WriteImageToFile("ExpandedImage.raw",&ExpandedImage[0][0][0],ExpandedI,ExpandedJ,BytesPerPixel);

    int SortedArray[FilterSize*FilterSize];

    for(int color=0; color<BytesPerPixel; color++)
    {
        switch(FilterShape)
        {
        case 'S':
            for(int i=0; i<SizeI; i++)
            {
                for(int j=0; j<SizeJ; j++)
                {
                    for(int m=-Margin; m<=Margin; m++)
                    {
                        for(int n=-Margin; n<=Margin; n++)
                        {
                            SortedArray[(m+Margin)*FilterSize+n+Margin]= ExpandedImage[i+Margin+m][j+Margin+n][color];
                        }
                    }
                    qsort(SortedArray,FilterSize*FilterSize,sizeof(int),compare);
                    ImageDataOut[BytesPerPixel*(i*SizeJ+j)+color] = SortedArray[FilterSize*FilterSize/2];
                }
            }
            break;
        case 'C':
            for(int i=0; i<SizeI; i++)
            {
                for(int j=0; j<SizeJ; j++)
                {
                    int n = 0;
                    for(int m=-Margin; m<=Margin; m++)
                    {
                        SortedArray[n]= ExpandedImage[i+Margin+m][j+Margin][color];
                        n ++;
                    }
                    for(int m=-Margin; m<=Margin; m++)
                    {
                        if(m!=0)
                        {
                            SortedArray[Margin+m+Margin]= ExpandedImage[i+Margin][j+Margin+m][color];
                            n ++;
                        }
                    }
                    qsort(SortedArray,FilterSize+FilterSize-1,sizeof(int),compare);
                    ImageDataOut[BytesPerPixel*(i*SizeJ+j)+color] = SortedArray[(FilterSize+FilterSize-1)/2];
                }
            }
            break;
        }
    }
}