Lively
Lively

Reputation: 111

Drawing like "from-to" in bitmap image

We know the streight line that mspaint can draw into a picture. Since nested loops fill the whole area (x/y) i was wondering whats the way of doing this. Drawing a line from (x0 y0) of the image to desired x/y. Im using this function for finding the x/y pixel of the bmp:

dword find (FILE* fp, dword xp, dword yp)
{
    word bpx = (3*8);
    dword offset = (2+sizeof(BMP)+sizeof(DIB));
    dword w = 500;

    dword row = (((bpx * w) * 4) / 32);
    dword pixAddress = (offset) + row * yp + ((xp * bpx) / 8);

    return pixAddress;
}

And I've tried with many functions for drawing line from 0x0 to xy, their results are close.. but not entirely.

Upvotes: 0

Views: 158

Answers (3)

Floris
Floris

Reputation: 46375

Take a look at the following code - I adapted this from Rosetta Code

#include <stdio.h>
#include <stdlib.h>

#define NX 40
#define NY 20
typedef unsigned char byte;

typedef struct {
  int x;
  int y;
} point;

typedef struct{
  char M[NX][NY];
} bitmap;

void drawLine(point *a, point*b, bitmap *B, FILE* fp, byte *color_pattern) {
  int x0 = a->x, y0 = a->y;
  int x1 = b->x, y1 = b->y;
  int dx = abs(x1-x0), sx = (x0<x1) ? 1 : -1;
  int dy = abs(y1-y0), sy = (y0<y1) ? 1 : -1;
  int err = (dx>dy ? dx : -dy)/2, e2;
  int index;
  while(1){
    // the next three lines put the pixel right in the file:
    index = (y0 * NX + x0)*3;
    fseek(fp, index, SEEK_SET); 
    fwrite(color_pattern, 1, 3, fp);

    B->M[x0][y0]=1;  // for code testing

    if (x0==x1 && y0==y1) break;
    e2 = err;
    if (e2 >-dx) { err -= dy; x0 += sx; }
    if (e2 < dy) { err += dx; y0 += sy; }
  }
}

void printLine(bitmap *B){
  int ii, jj;
  for(ii=0; ii<NY; ii++) {
    for(jj=0; jj<NX; jj++) {
      printf("%d", (int)B->M[jj][ii]);
    }
    printf("\n");
  }
}

int main(void) {
  FILE *fp;
  point start = {34,7};
  point end = {14, 17};
  bitmap B;
  byte color[]={255,255,255};

  // initialize map to zero. Want to do same with file I suppose
  int ii, jj;
  for(ii=0; ii<NX; ii++) {
    for(jj=0; jj<NY; jj++) {
      B.M[ii][jj]=0;
    }
  }
  fp = fopen("mypicture.bmp", "wb");

  drawLine(&start, &end, &B, fp, color);
  printLine(&B);

  fclose(fp);
}

I think it should be easy to adapt it for your situation. Note I have tried to separate / localize variables a little more - that is usually a good idea; there are still many ways to further improve this code (this is a situation where C++ might be a better language...)

Output of the above:

0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000001100000
0000000000000000000000000000000110000000
0000000000000000000000000000011000000000
0000000000000000000000000001100000000000
0000000000000000000000000110000000000000
0000000000000000000000011000000000000000
0000000000000000000001100000000000000000
0000000000000000000110000000000000000000
0000000000000000011000000000000000000000
0000000000000001100000000000000000000000
0000000000000010000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000

Looks like the "right" line to me... even though it's got the X going in the negative direction. That's the advantage of starting with proven code (in this case, Bresenham's algorithm as implemented on Rosettacode).

Upvotes: 1

Lively
Lively

Reputation: 111

byte color_pattern[] = { 255, 255, 255 };
dword xy_offset[] = {1, 1};

void bmp_lineto(dword endx, dword endy)
{
    int dx = endx - xy_offset[0];
    int dy = endy - xy_offset[1];
    int twody = 2 * dy;
    int twodxdy = 2 * (dy - dx);
    int dp = twody - dx;
    int X, Y, xEnd, yEnd;
    FILE* fp = fopen(convert(FILENAME.text), "rb+");

    if(xy_offset[0] > endx)
    {
        X = endx;
        Y = endy;
        xEnd = xy_offset[0];
    }
    else
    {
        X = xy_offset[0];
        Y = xy_offset[1];
        xEnd = endx;
    }
    while(X < xEnd)
    {
        X = X + 1;
        if(dp < 0)
        {
            dp = dp + twody;
        } else { Y = Y + 1; dp = dp + twodxdy;
        }
    fseek(fp, find(fp, X, Y), SEEK_SET);
    fwrite(&color_pattern, 1, 3, fp);
    }
}

But the result on the bmp from this code is so... uncertain: bmp_lineto(200, 230); The entire image is x500 : y460 UPDATED. The y coordinate is same as x. Thats the problem

enter image description here

Upvotes: 1

Phyllostachys
Phyllostachys

Reputation: 161

You can look into Bresenham's line algorithm. There are extensions to it that handle anti-aliasing too.

Upvotes: 0

Related Questions