{"id":15009207,"url":"https://github.com/hageldave/ezfftw","last_synced_at":"2025-04-09T17:22:46.098Z","repository":{"id":144520167,"uuid":"118948375","full_name":"hageldave/ezFFTW","owner":"hageldave","description":"A wrapper built on top of bytedeco's JavaCPP preset for the FFTW library, that hides the cumbersome native pointering for ez (easy) use.","archived":false,"fork":false,"pushed_at":"2021-05-28T13:47:17.000Z","size":148,"stargazers_count":15,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-23T19:22:41.884Z","etag":null,"topics":["fft","fftw","fourier-transform","java-library","maven","multidimensional","native-bindings"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hageldave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-25T18:00:38.000Z","updated_at":"2024-11-12T04:24:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"11216a09-f435-4c4f-aa17-704f666b00bb","html_url":"https://github.com/hageldave/ezFFTW","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FezFFTW","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FezFFTW/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FezFFTW/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hageldave%2FezFFTW/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hageldave","download_url":"https://codeload.github.com/hageldave/ezFFTW/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248075283,"owners_count":21043557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fft","fftw","fourier-transform","java-library","maven","multidimensional","native-bindings"],"created_at":"2024-09-24T19:23:38.008Z","updated_at":"2025-04-09T17:22:46.092Z","avatar_url":"https://github.com/hageldave.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ezFFTW\n\nA wrapper for the FFTW library built on top of bytedeco's JavaCPP preset that hides the cumbersome native pointering for ez (easy) use. [See bytedeco's code here](https://github.com/bytedeco/javacpp-presets/tree/master/fftw). [See FFTW code here](https://github.com/FFTW/fftw3).\n\n[![Build Status](https://travis-ci.com/hageldave/ezFFTW.svg?branch=master)](https://travis-ci.com/hageldave/ezFFTW)\n[![Coverage Status](https://coveralls.io/repos/github/hageldave/ezFFTW/badge.svg?branch=master)](https://coveralls.io/github/hageldave/ezFFTW?branch=master)\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.hageldave.ezfftw/ezfftw.svg)](https://search.maven.org/search?q=g:com.github.hageldave.ezfftw)\n\nMaven Dependency (Central Repository):\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.github.hageldave.ezfftw\u003c/groupId\u003e\n\t\u003cartifactId\u003eezfftw\u003c/artifactId\u003e\n\t\u003cversion\u003e0.1.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Examples\n\n### Sine + Cosine\n(from [examples/Simple.java](../master/src/test/java/hageldave/ezfftw/dp/example/Simple.java))\n```java\nstatic void sinePlusCosine(){\n  int numSamples = 16;\n  double second = 2*Math.PI; // interval of one second\n  // create samples\n  double[] samples = new double[numSamples];\n  for(int i = 0; i \u003c numSamples; i++){\n    samples[i] = Math.sin(i*second/numSamples);\n    samples[i]+= Math.cos(i*second/numSamples);\n  }\n  // execute fft\n  double[] realPart = new double[numSamples];\n  double[] imagPart = new double[numSamples];\n  FFT.fft(samples, realPart,imagPart, numSamples);\n  // print result (omit conjugated complex results)\n  for(int i = 0; i \u003c 1+numSamples/2; i++) {\n    System.out.format(\"%dHz | % .2f%+.2fi%n\",i, realPart[i], imagPart[i]);\n  }\n}\n```\n\n### Image Band Pass\n(from [examples/Filtering.java](../master/src/test/java/hageldave/ezfftw/dp/example/Filtering.java))\n```java\nstatic void bandPassImageFilter(InputStream input, OutputStream output, String outFormat){\n  try {\n    // load image\n    BufferedImage loadedImg = ImageIO.read(input);\n    final int width = loadedImg.getWidth();\n    final int height = loadedImg.getHeight();\n    // make sampler for image\n    RealValuedSampler sampler = new RealValuedSampler() {\n      @Override\n      public double getValueAt(long... coordinates) {\n        // we know coordinates will be 2D and in range of image dimensions\n        int rgb = loadedImg.getRGB((int)coordinates[0], (int)coordinates[1]);\n        // return average grey in range [0,1]\n        return ((rgb\u003e\u003e16\u00260xff)+(rgb\u003e\u003e8\u00260xff)+(rgb\u00260xff))/(3*255.0); \n      }\n    };\n    // make fft storage (RowMajorArrayAccessor implements sampler and writer)\n    RowMajorArrayAccessor realPart = new RowMajorArrayAccessor(new double[width*height], width,height);\n    RowMajorArrayAccessor imagPart = new RowMajorArrayAccessor(new double[width*height], width,height);\n    // execute fft\n    FFT.fft(sampler, realPart.combineToComplexWriter(imagPart), width, height);\n    // make sampler that will filter out frequencies\n    ComplexValuedSampler filterSampler = new ComplexValuedSampler() {\n      @Override\n      public double getValueAt(boolean imaginary, long... coordinates) {\n        // get coordinates with centered DC\n        double x = ( ((coordinates[0]+ width/2)% width)- width/2 );\n        double y = ( ((coordinates[1]+height/2)%height)-height/2 );\n        // get length (corresponds to frequency)\n        double l = Math.sqrt(x*x+y*y);\n        // define band pass frequencies to be in ]50, 100[\n        if(l \u003e 50 \u0026\u0026 l \u003c 100){\n          return imaginary ? imagPart.getValueAt(coordinates[0],coordinates[1]) \n                  : realPart.getValueAt(coordinates[0],coordinates[1]);\n        } else return 0;\n      }\n    };\n    // make target image for writing result\n    BufferedImage filteredImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\n    RealValuedWriter imgWriter = new RealValuedWriter() {\n      @Override\n      public void setValueAt(double value, long... coordinates) {\n        value /= width*height; // remove scaling (FFTW does it like this)\n        value = Math.max(0, Math.min(value, 1)); // clamp value between [0,1]\n        int byteval = (int)(value*255);\n        int argb = 0xff000000|(byteval\u003c\u003c16)|(byteval\u003c\u003c8)|byteval; // make greyscale argb\n        filteredImg.setRGB((int)coordinates[0], (int)coordinates[1], argb);\n            \n      }\n    };\n    // execute inverse fft\n    FFT.ifft(filterSampler, imgWriter, width, height);\n    ImageIO.write(filteredImg, outFormat, output);\n  } catch (IOException e){\n    e.printStackTrace();\n  }\n}\n```\n\n### Filtered Back Projection\n(from [examples/FilteredBackProjection.java](../master/src/test/java/hageldave/ezfftw/dp/example/FilteredBackProjection.java))\n```java\nstatic double[][] filteredBackProjection(double[][] radon, int outputResolution) {\n  /* apply ramp filter to radon transform - 1st step fourier transform\n   * (every line is one projection and has to be filtered separately)\n   */\n  try(//with resources\n      NativeRealArray projection = new NativeRealArray(radon[0].length);\n      NativeRealArray fft_r = new NativeRealArray(projection.length);\n      NativeRealArray fft_i = new NativeRealArray(projection.length);\n  ){\n    for(int i = 0; i \u003c radon.length; i++){\n      projection.set(radon[i]);\n      FFTW_Guru.execute_split_r2c(projection, fft_r, fft_i, projection.length);\n      projection.get(0, radon[i]);\n      // 2nd step apply ramp filter ( multiply by abs(freq) with normalized freq )\n      long spectrumWidth = projection.length;\n      long highestFreq = spectrumWidth/2;\n      for(long k = 0; k \u003c spectrumWidth; k++){\n        long freq = ((k+highestFreq)%spectrumWidth)-highestFreq;\n        double scaling = Math.abs(freq*1.0/highestFreq);\n        fft_r.set(k, fft_r.get(k)*scaling);\n        fft_i.set(k, fft_i.get(k)*scaling);\n      }\n      // 3rd step, inverse fft\n      FFTW_Guru.execute_split_c2r(fft_r, fft_i, projection, projection.length);\n      projection.get(0, radon[i]);\n    }\n  }\n  // now do back projection\n  double[][] output = new double[outputResolution][outputResolution];\n  double toRadians = Math.PI/radon.length;\n  int projectionWidth = radon[0].length;\n  for(int i = 0; i \u003c outputResolution; i++){\n    double y = ((i*1.0/outputResolution)-0.5)*2;\n    for(int j = 0; j \u003c outputResolution; j++){\n      double x = ((j*1.0/outputResolution)-0.5)*2;\n      double sum = 0;\n      int numSummands = 0;\n      // for each projection find radius where [x,y] was projected to\n      for(int p = 0; p \u003c radon.length; p++){\n        double angle = p*toRadians;\n        double radius = x*Math.cos(angle)+y*Math.sin(angle);\n        int r = (int)((radius+1)/2*(projectionWidth-1));\n        if(r \u003e=0 \u0026\u0026 r \u003c projectionWidth){\n          sum += radon[p][r];\n          numSummands++;\n        }\n      }\n      if(numSummands \u003e 0)\n        sum /= numSummands;\n      output[i][j] = sum;\n    }\n  }\n  return output;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhageldave%2Fezfftw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhageldave%2Fezfftw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhageldave%2Fezfftw/lists"}