NAudio 2-channels waves to graphics - graphics

Good day, colleagues!
Help, the head has already broken ...
the following code I get a wave from the WAV file and output it in Graphics ... I'm betting on how to split the output of the graph on the left and right channel ... please ...! Tried to taste the manual on NAudio but so did not understand anything about what I need ...
#region draw container
SolidBrush whiteBrush = new SolidBrush(Color.White);
SolidBrush blackBrush = new SolidBrush(Color.Black);
Pen blackPen = new Pen(Color.Black, 1);
e.Graphics.FillRectangle(whiteBrush, 0, 0, this.Width-2, this.Height-2);
e.Graphics.DrawLine(blackPen, 0, 0, this.Width-2, 0);
e.Graphics.DrawLine(blackPen, 0, this.Height / 2, this.Width-2, this.Height / 2);
e.Graphics.DrawLine(blackPen, 0, this.Height - 2, this.Width-2, this.Height-2);
e.Graphics.DrawLine(blackPen, 0, 0, 0, this.Height-2);
e.Graphics.DrawLine(blackPen, this.Width-2, 0, this.Width-2, this.Height-2);
e.Graphics.DrawString("L:", new Font("Arial", 6, FontStyle.Bold), blackBrush, 2, 2);
e.Graphics.DrawString("R:", new Font("Arial", 6, FontStyle.Bold), blackBrush, 2, (this.Height /2) + 2);
#endregion
if (waveStream != null)
{
waveStream.Position = 0;
int bytesRead;
byte[] waveData = new byte[samplesPerPixel * bytesPerSample];
waveStream.Position = startPosition + (e.ClipRectangle.Left * bytesPerSample * samplesPerPixel);
Pen linePen_L = new Pen(PenColor_L, PenWidth);
Pen linePen_R = new Pen(PenColor_R, PenWidth);
//bool _left = true; bool _right = false;
for (float x = e.ClipRectangle.X; x < e.ClipRectangle.Right; x += 1)
{
//_left = !_left;
//_right = !_right;
short low = 0;
short high = 0;
bytesRead = waveStream.Read(waveData, 0, samplesPerPixel * bytesPerSample);
if (bytesRead == 0)
break;
for (int n = 0; n < bytesRead; n += 2)
{
short sample = BitConverter.ToInt16(waveData, n);
if (sample < low) low = sample;
if (sample > high) high = sample;
}
float lowPercent = ((((float)low) - short.MinValue) / ushort.MaxValue);
float highPercent = ((((float)high) - short.MinValue) / ushort.MaxValue);
//if (_left)
e.Graphics.DrawLine(linePen_L, x, (this.Height * lowPercent) /2, x, (this.Height * highPercent)/2);
//if (_right)
//e.Graphics.DrawLine(linePen_R, x, ((this.Height * lowPercent) /2) + this.Height/2, x, ((this.Height * highPercent) /2) + this.Height / 2);
}
}

I found the way :)
if (waveStream != null)
{
waveStream.Position = 0;
int bytesRead;
byte[] waveData = new byte[samplesPerPixel * bytesPerSample];
waveStream.Position = startPosition + (e.ClipRectangle.Left * bytesPerSample * samplesPerPixel);
Pen linePen_L = new Pen(PenColor_L, PenWidth);
Pen linePen_R = new Pen(PenColor_R, PenWidth);
for (float x = e.ClipRectangle.X; x < e.ClipRectangle.Right; x += 1)
{
short low_L = 0;
short high_L = 0;
short low_R = 0;
short high_R = 0;
bytesRead = waveStream.Read(waveData, 0, samplesPerPixel * bytesPerSample);
if (bytesRead == 0)
break;
for (int n = 0; n < bytesRead; n += 2)
{
short sample_L = BitConverter.ToInt16(waveData, n);
if (sample_L < low_L) low_L = sample_L;
if (sample_L > high_L) high_L = sample_L;
n += 2;
short sample_R = BitConverter.ToInt16(waveData, n);
if (sample_R < low_R) low_R = sample_R;
if (sample_R > high_R) high_R = sample_R;
}
float lowPercent_L = ((((float)low_L) - short.MinValue) / ushort.MaxValue);
float highPercent_L = ((((float)high_L) - short.MinValue) / ushort.MaxValue);
float lowPercent_R = ((((float)low_R) - short.MinValue) / ushort.MaxValue);
float highPercent_R = ((((float)high_R) - short.MinValue) / ushort.MaxValue);
e.Graphics.DrawLine(linePen_L, x, (this.Height * lowPercent_L) / 2, x, (this.Height * highPercent_L) / 2);
e.Graphics.DrawLine(linePen_R, x, ((this.Height * lowPercent_R) / 2) + this.Height / 2, x, ((this.Height * highPercent_R) / 2) + this.Height / 2);
}
}

Related

Node isometric tile map render second layer problem

I'm building an isometric map tile image in Node and I'm stuck at the second layer rendering, I can't figure out how to adjust items in the y axis
Here's my code so far:
let i = 0;
for (let layer of map) {
const xTiles = layer.length;
const yTiles = layer[0].length;
for (let Xi = xTiles - 1; Xi >= 0; Xi--) {
for (let Yi = 0; Yi < yTiles; Yi++) {
const imgIndex = layer[Xi][Yi];
if (imgIndex == null || imgIndex == -1) {
continue;
}
const tile = tiles[imgIndex];
const offX = (Xi * tileColOffset / 2 + Yi * tileColOffset / 2 + originX) + (i * ((tileColOffset - tile.width) / 2));
const offY = (Yi * tileRowOffset / 2 - Xi * tileRowOffset / 2 + originY) - (i * ((tileRowOffset / 2)));
ctx.drawImage(tile, offX, offY);
}
}
i++;
}
I can center the sprite on the x axis but not on the y one, probably because sprites have different heights. The code above reproduces this
As you can see the taller sprites are quite centered, but the small ones are not. Any suggestion?
Thanks!
Just found out that I have to calculate the difference between the half height of the ground tile and the height of the sprite:
let i = 0;
for (let layer of map) {
const xTiles = layer.length;
const yTiles = layer[0].length;
for (let Xi = xTiles - 1; Xi >= 0; Xi--) {
for (let Yi = 0; Yi < yTiles; Yi++) {
const imgIndex = layer[Xi][Yi];
if (imgIndex == null || imgIndex == -1) {
continue;
}
const tile = tiles[imgIndex];
let offX, offY
if (i === 0) {
offX = (Xi * tileColOffset / 2 + Yi * tileColOffset / 2 + originX);
offY = (Yi * tileRowOffset / 2 - Xi * tileRowOffset / 2 + originY);
} else {
offX = (Xi * tileColOffset / 2 + Yi * tileColOffset / 2 + originX) + (i * ((tileColOffset - tile.width) / 2));
offY = (Yi * tileRowOffset / 2 - Xi * tileRowOffset / 2 + originY) + ((i * (tileRowOffset / 2 - tile.height)));
}
ctx.drawImage(tile, offX, offY);
}
}
i++;
}

Multithreaded Nagel–Schreckenberg model (traffic simulation) with OpenMP

I'm trying to write a multithreaded Nagel–Schreckenberg model simulation in c language and have some problems when a thread accesses the data which wasn't calculated yet.
Here is a working code which only parallelizes velocity calculation per line:
#define L 3000 // number of cells in row
#define num_iters 3000 // number of iterations
#define density 0.48 // how many positives
#define vmax 2
#define p 0.2
for (int i = 0; i < num_iters - 1; i++)
{
int temp[L] = {0};
#pragma omp parallel for
for (int x = 0; x < L; x++)
{
if (iterations[i][x] > -1)
{
int vi = iterations[i][x]; // velocity of previews iteration
int d = 1; // index of the next vehicle
while (iterations[i][(x + d) % L] < 0)
d++;
int vtemp = min(min(vi + 1, d - 1), vmax); // increase speed, but avoid hitting the next car
int v = r2() < p ? max(vtemp - 1, 0) : vtemp; // stop the vehicle with probability p
temp[x] = v;
}
}
for (int x = 0; x < L; x++) // write the velocities to the next line
{
if (iterations[i][x] > -1)
{
int v = temp[x];
iterations[i + 1][(x + v) % L] = v;
}
}
}
This works fine, but it's not fast enough. I'm trying to use convolution to increase the performance, but it can't read neighbor thread's data half of the time because it wasn't calculated yet. Here is the code I used:
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <sys/time.h>
#define L 4000 // number of cells in row
#define num_iters 4000 // number of iterations
#define density 0.48 // how many positives
#define vmax 2
#define p 0.2
#define BLOCKS_Y 4
#define BLOCKS_X 4
#define BLOCKSIZEY (L / BLOCKS_Y)
#define BLOCKSIZEX (L / BLOCKS_X)
time_t t;
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
void shuffle(int *array, size_t n)
{
if (n > 1)
{
size_t i;
for (i = 0; i < n - 1; i++)
{
size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
int t = array[j];
array[j] = array[i];
array[i] = t;
}
}
}
double r2()
{
return (double)rand() / (double)RAND_MAX;
}
void writeImage(int *iterations[], char filename[])
{
int h = L;
int w = num_iters;
FILE *f;
unsigned char *img = NULL;
int filesize = 54 + 3 * w * h;
img = (unsigned char *)malloc(3 * w * h);
memset(img, 0, 3 * w * h);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
int x = i;
int y = (h - 1) - j;
int color = iterations[i][j] == 0 ? 0 : 255;
img[(x + y * w) * 3 + 2] = (unsigned char)(color);
img[(x + y * w) * 3 + 1] = (unsigned char)(color);
img[(x + y * w) * 3 + 0] = (unsigned char)(color);
}
}
unsigned char bmpfileheader[14] = {'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0};
unsigned char bmpinfoheader[40] = {40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0};
unsigned char bmppad[3] = {0, 0, 0};
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
bmpinfoheader[4] = (unsigned char)(w);
bmpinfoheader[5] = (unsigned char)(w >> 8);
bmpinfoheader[6] = (unsigned char)(w >> 16);
bmpinfoheader[7] = (unsigned char)(w >> 24);
bmpinfoheader[8] = (unsigned char)(h);
bmpinfoheader[9] = (unsigned char)(h >> 8);
bmpinfoheader[10] = (unsigned char)(h >> 16);
bmpinfoheader[11] = (unsigned char)(h >> 24);
f = fopen(filename, "wb");
fwrite(bmpfileheader, 1, 14, f);
fwrite(bmpinfoheader, 1, 40, f);
for (int i = 0; i < h; i++)
{
fwrite(img + (w * (h - i - 1) * 3), 3, w, f);
fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f);
}
free(img);
fclose(f);
}
void simulation()
{
printf("L=%d, num_iters=%d\n", L, num_iters);
int z = 0;
z++;
int current_index = 0;
int success_moves = 0;
const int cars_num = (int)(density * L);
int **iterations = (int **)malloc(num_iters * sizeof(int *));
for (int i = 0; i < num_iters; i++)
iterations[i] = (int *)malloc(L * sizeof(int));
for (int i = 0; i < L; i++)
{
iterations[0][i] = i <= cars_num ? 0 : -1;
}
shuffle(iterations[0], L);
for (int i = 0; i < num_iters - 1; i++)
for (int x = 0; x < L; x++)
iterations[i + 1][x] = -1;
double *randoms = (double *)malloc(L * num_iters * sizeof(double));
for (int i = 0; i < L * num_iters; i++) {
randoms[i] = r2();
}
#pragma omp parallel for collapse(2)
for (int blocky = 0; blocky < BLOCKS_Y; blocky++)
{
for (int blockx = 0; blockx < BLOCKS_X; blockx++)
{
int ystart = blocky * BLOCKSIZEY;
int yend = ystart + BLOCKSIZEY;
int xstart = blockx * BLOCKSIZEX;
int xend = xstart + BLOCKSIZEX;
for (int y = ystart; y < yend; y++)
{
for (int x = xstart; x < xend; x++)
{
if (iterations[y][x] > -1)
{
int vi = iterations[y][x];
int d = 1;
int start = (x + d) % L;
int i;
for (i = start; i < L && iterations[y][i] < 0; ++i);
d += i - start;
if (i == L)
{
for (i = 0; i < start && iterations[y][i] < 0; ++i);
d += i;
}
int vtemp = min(min(vi + 1, d - 1), vmax);
int v = randoms[x * y] < p ? max(vtemp - 1, 0) : vtemp;
iterations[y + 1][(x + v) % L] = v;
}
}
}
}
}
if (L <= 4000)
writeImage(iterations, "img.bmp");
free(iterations);
}
void main() {
srand((unsigned)time(&t));
simulation();
}
As you can see, as the second block gets calculated the first one didn't probably calculate yet which produces that empty space.
I think it's possible to solve this with the convolution, but I'm just doing something wrong and I'm not sure what. If you could give any advice on how to fix this problem, I would really appreciate it.
There is a race condition in the second code because iterations can be read by a thread and written by another. More specifically, iterations[y + 1][(x + v) % L] = v set a value that another thread should read when checking iterations[y][x] or iterations[y][(x + d) % L] when two threads are working on consecutive y values (of two consecutive blocky values).
Moreover, the r2 function have to be thread-safe. It appears to be a random number generator (RNG), but such random function is generally implemented using global variables that are often not thread-safe. One simple and efficient solution is to use thread_local variables instead. An alternative solution is to explicitly pass in parameter a mutable state to the random function. The latter is a good practice when you design parallel applications since it makes visible the mutation of an internal state and it provides way to better control the determinism of the RNG.
Besides this, please note that modulus are generally expensive, especially if L is not a compile-time constant. You can remove some of them by pre-computing the remainder before a loop or splitting a loop so to perform checks only near the boundaries. Here is an (untested) example for the while:
int start = (x + d) % L;
int i;
for(i=start ; i < L && iterations[y][i] < 0 ; ++i);
d += i - start;
if(i == L) {
for(i=0 ; i < start && iterations[y][i] < 0 ; ++i);
d += i;
}
Finally, please note that the blocks should be divisible by 4. Otherwise, the current code is not valid (a min/max clamping is likely needed).

CS50 Pset4 Sepia Filter, where is the bug? The code doesn't pass the CS50 tests

So this is the code I have for Pset4 for the Sepia filter...it's heading in the right direction but I've been trying to figure out why it isn't passing the tests. Cannot filter a simple 3 x 3 image or complex 3 x 3 image or the 4 x 4 image. Trying to figure out where the bug is, any tips would be wonderful!
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// get values of each colour in the image
int red = image[i][j].rgbtRed;
int blue = image[i][j].rgbtBlue;
int green = image[i][j].rgbtGreen;
// find average of the pixel RBG colors
float average = (round(red) + round(blue) + round(green)) / 3;
average = round(average);
//puts the value average into the pixel colors
image[i][j].rgbtRed = average;
image[i][j].rgbtBlue = average;
image[i][j].rgbtGreen = average;
}
}
return;
}
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
//gets the values of each color in the image
int red = image[i][j].rgbtRed;
int blue = image[i][j].rgbtBlue;
int green = image[i][j].rgbtGreen;
// gets the sepia value of the pixels
int sepiaRed = round(0.393 * red + 0.769 * green + 0.189 * blue);
int sepiaGreen = round(0.349 * red + 0.686 * green + 0.168 * blue);
int sepiaBlue = round(0.272 * red + 0.534 * green + 0.131 * blue);
if (sepiaRed >= 256)
{
sepiaRed = 255;
}
if (sepiaGreen >= 256)
{
sepiaGreen = 255;
}
if (sepiaBlue >= 256)
{
sepiaBlue= 255;
}
image[i][j].rgbtRed = sepiaRed;
image[i][j].rgbtBlue = sepiaBlue;
image[i][j].rgbtGreen = sepiaGreen;
}
return;
}
}
I'm not sure, without seeing more of the code. But shouldn't these three ifs at the end be placed before you save their values to the image? Like this:
...
if (sepiaRed >= 256)
{
sepiaRed = 255;
}
if (sepiaGreen >= 256)
{
sepiaGreen = 255;
}
if (sepiaBlue >= 256)
{
sepiaBlue = 255;
}
image[i][j].rgbtRed = sepiaRed;
image[i][j].rgbtBlue = sepiaBlue;
image[i][j].rgbtGreen = sepiaGreen;
...
First You check if calculated values are not higher than 255. Then save these values to the image.
Also you should replace 'else if' with 'if' to check all 3 values not up to one. And then edit value of sepiaRed, sepiaBlue, sepiaGreen not red, blue, green.
I'm not sure if I get right what that function suppose to do.
you have to use the math function round(), mine just working fine.
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
//gets the values of each color in the image
int red = image[i][j].rgbtRed;
int blue = image[i][j].rgbtBlue;
int green = image[i][j].rgbtGreen;
// gets the sepia value of the pixels
int sepiaRed = round(0.393 * red + 0.769 * green + 0.189 * blue) ;
int sepiaGreen = round(0.349 * red + 0.686 * green + 0.168 * blue) ;
int sepiaBlue = round(0.272 * red + 0.534 * green + 0.131 * blue) ;
if (sepiaRed >= 256)
{
sepiaRed = 255;
}
if (sepiaGreen >= 256)
{
sepiaGreen = 255;
}
if (sepiaBlue >= 256)
{
sepiaBlue= 255;
}
image[i][j].rgbtRed = sepiaRed;
image[i][j].rgbtBlue = sepiaBlue;
image[i][j].rgbtGreen = sepiaGreen;
}
}

How to detect the fuzzy edge of a raindrop?

I want to extract the edge of the raindrop.
This is raindrop's photo.
I divide the picture into 8*8 blocks and extract the edges using sobel and canny. Now I can get a rough edge.
This is the edge I got.
I can't get the fuzzy edge of the raindrop.
This fuzzy edge I can't get
//sobel
Mat SobelProcess(Mat src)
{
Mat Output;
Mat grad_x, grad_y, abs_grad_x, abs_grad_y, SobelImage;
Sobel(src, grad_x, CV_16S, 1, 0, CV_SCHARR, 1, 1, BORDER_DEFAULT);
Sobel(src, grad_y, CV_16S, 0, 1, CV_SCHARR, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
convertScaleAbs(grad_y, abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, Output);
//subtract(grad_x, grad_y, SobelImage);
//convertScaleAbs(SobelImage, Output);
return Output;
}
int main()
{
Mat Src;
Src = imread("rain.bmp",0)
imshow("src", Src);
Mat Gauss;
GaussianBlur(Src, Src, Size(5, 5), 0.5);
imshow("Gauss", Src);
//M * N = 8 * 8
int OtsuThresh[M * N];
vector<Mat>tempThresh = ImageSegment(Src);
for (int i = 0; i < M * N; i++)
{
OtsuThresh[i] = Otsu(tempThresh[i]); //get Otsu Threshold
}
vector<Mat>temp;
temp = ImageSegment(Src);//ImageSegment() is a function to divide the picture into 8*8 blocks
for (int i = 0; i < M * N; i++)
{
temp[i] = SobelProcess(temp[i]);
GaussianBlur(temp[i], temp[i], Size(3, 3), 0.5);
Canny(temp[i], temp[i], OtsuThresh[i] / 3, OtsuThresh[i]);
}
Mat Tem;
Tem = ImageMerge(temp);//ImageMerge() is a function to merge the blocks
imshow("Tem", Tem);
}
Then I use watershed. But I can't use it get an ideal result.

(computer graphics) radial image distortion

I need to create an effect, that radially distorts a bitmap, by stretching or shrinking its "layers of pixels" radially (as shown on the image):
http://i.stack.imgur.com/V6Voo.png
by colored circles (their thickness) is shown the transform, that is applied to the image
What approach should I take? I have a bitmap (array of pixels) and an another bitmap, that should be the result of such a filter applied (as a result, there should be some kind of a round water ripple on the bitmap).
Where could I read about creating such effects?
Thank you.
Try to look here
http://www.jhlabs.com/ip/blurring.html
Zoom and Spin Blur
it is Java but nevertheless it could be fit to your request.
Well, the most accurate results would come from mapping the euclidean coordinates to a polar matrix. Then you would very easily be able to stretch them out. Then just translate them back to a euclidean representation and save. I'll write and edit with some code in a second.
Alright I got a bit carried away but here's my code. It will take a bitmap, convert it to and from polar coordinates and save it. now, radial based distortion should be a breeze.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define PI 3.141592654
#define C_R 1000
#define C_S 1000
#define C_M 2000
typedef struct{ int r,g,b; } color;
typedef struct{ int t; color* data; int w, h; } bitmap;
typedef struct{ int t; color* data; int r, s, w, h; } r_bitmap;
bitmap* bmp_load_from_file( const char* fname ){
FILE* b = fopen( fname, "rb" );
if( b <= 0 ) return 0;
int num;
fscanf( b, "BM%n", &num );
if( num < 2 ) return 0;
struct{ int size, reserved, offset;
int hsize, wid, hig, planes:16, bpp:16, comp, bmpsize, hres, vres, colors, important; } head;
fread( &head, 13, 4, b );
bitmap* bmp = malloc( sizeof( bitmap ) );
bmp->data = malloc( head.wid * head.hig * sizeof( color ) );
bmp->w = head.wid;
bmp->h = head.hig;
for( int y = head.hig - 1; y >= 0; --y ){
int x;
for( x = 0; x < head.wid; ++x ){
color t;
t.r = fgetc( b );
t.g = fgetc( b );
t.b = fgetc( b );
bmp->data[x+y*bmp->w] = t;
}
x*=3;
while( x%4 != 0 ){
++x;
fgetc( b );
}
}
bmp->t = 0;
fclose( b );
return bmp;
}
void bmp_save( const char* fname, bitmap* bmp ){
FILE* b = fopen( fname, "wb" );
if( b <= 0 ) return 0;
struct{ int size, reserved, offset;
int hsize, wid, hig, planes:16, bpp:16, comp, bmpsize, hres, vres, colors, important; } head;
fprintf( b, "BM" );
head.size = 3 * (bmp->w+4)/4*4 * bmp->h + 54;
head.offset = 54;
head.hsize = 40;
head.wid = bmp->w;
head.hig = bmp->h;
head.planes = 1;
head.bpp = 24;
head.comp = 0;
head.bmpsize = 3 * (bmp->w+4)/4*4 * bmp->h;
head.hres = 72;
head.vres = 72;
head.colors = 0;
head.important = 0;
fwrite( &head, 13, 4, b );
for( int y = bmp->h - 1; y >= 0; --y ){
int x;
for( x = 0; x < bmp->w; ++x ){
fputc( bmp->data[x + y * bmp->w].r, b );
fputc( bmp->data[x + y * bmp->w].g, b );
fputc( bmp->data[x + y * bmp->w].b, b );
}
x*=3;
while( x % 4 != 0 ){
++x;
fputc(0, b);
}
}
fclose( b );
}
color color_mix( color a, color b, int offset ){ /*offset is a value between 0 and 255 to determine the weight. the lower it is the more color a gets*/
//if( offset > 255 || offset < 0)
//printf("%i\t", offset);
a.r += ( b.r - a.r ) * offset / 255;
a.g += ( b.g - a.g ) * offset / 255;
a.b += ( b.b - a.b ) * offset / 255;
return a;
}
r_bitmap* bmp_to_r( bitmap* b ){
r_bitmap* r = malloc( sizeof( r_bitmap ) );
r->t = 1;
int radius = sqrt( b->w * b->w + b->h * b->h ) / 2 * C_R / C_M + 2;
int step = C_S * ( b->w + b->h ) / C_M;
r->data = malloc( radius * step * sizeof( color ) );
r->r = radius;
r->s = step;
r->w = b->w;
r->h = b->h;
color black = {0, 0, 0};
for( double i = 0; i < radius; ++ i ){
for( double j = 0; j < step; ++j ){
double x = i * C_M * cos( 2 * PI * j / step ) / C_R + b->w / 2;
double y = i * C_M * sin( 2 * PI * j / step ) / C_R + b->h / 2;
int ix = x;
int iy = y;
if( x < 0 || x >= b->w || y < 0 || y >= b->h )
r->data[(int)(j + i * step)] = black;
else{
color tmp = b->data[ix + iy * b->w];
if( iy < b->h - 1 ){
int off = 255 * (y - iy);
tmp = color_mix( tmp, b->data[ix + (iy+1) * b->w], off );
}
if( ix < b->w - 1 ){
int off = 255 * ( x - ix );
tmp = color_mix( tmp, b->data[ix +1 + iy * b->w], off );
}
r->data[(int)(j + i * step)] = tmp;
}
}
}
return r;
}
bitmap* bmp_from_r( r_bitmap* r ){
bitmap* b = malloc( sizeof( bitmap ) );
b->t = 0;
b->data = malloc( r->w * r->h * sizeof( color ) );
b->w = r->w;
b->h = r->h;
for( int y = 0; y < b->h; ++y ){
for( int x = 0; x < b->w; ++x ){
int tx = x - b->w/2;
int ty = y - b->h/2;
double rad = sqrt( tx*tx+ty*ty ) * C_R / C_M;
double s = atan2( ty, tx );
if( s < 0 ) s += 2 * PI;
s *= r->s / ( 2 * PI );
int is = s;
int irad = rad;
color tmp = r->data[(int)(is + irad * r->s)];
/*if( x > 0 && x < r->w - 1 && y > 0 && y < r->h - 1 ){
tmp = color_mix(tmp, r->data[((int)(is+1)%r->s + irad * r->s)], abs(255* rad - floor(rad)));
tmp = color_mix(tmp, r->data[(is + (irad + 1) * r->s)], abs(255* s - floor(s)));
}*/
b->data[x+y*b->w] = tmp;
}
}
return b;
}
int main( ) {
bitmap* b = bmp_load_from_file( "foo.bmp" );
r_bitmap* r = bmp_to_r( b );
bitmap* c = bmp_from_r( r );
bmp_save( "lol.bmp", c );
}

Resources