const char * UsageLines [] = {
"Usage: linetopbm (width) (height)",
"Reads space-separated points, from standard input, in the form",
"\tacross,down",
"\twhere across and down are positive or negative integers.",
"Writes, to standard output, a P4 PBM image.",
"A line one pixel wide will join the points on each input line",
"\t(that has at least two points).",
"On each input line, everything after # is treated as a comment.",
"The leftmost column of pixels is considered - (width)/2 across.",
"The topmost row of pixels is considered - (height)/2 down.",
"August 26, 2011. Newest is at gopher -p users/julianbr sdf.org",
};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );
struct Segment {
int across1;
int down1;
int across2;
int down2;
struct Segment * next;
};
#include <stdlib.h>
#include <stdio.h>
int ReadSegments (struct Segment * * SegmentsPtr)
{
struct Segment * * SegmentPtr;
unsigned int LineNum;
int IsNegative, FoundAcross, across, FoundDown, down;
int PreviousAcross, PreviousDown, PreviousPoint;
int c, ok;
ok = 1;
LineNum = 0;
SegmentsPtr [0] = NULL;
SegmentPtr = SegmentsPtr;
c = getchar ();
while (c != EOF) {
LineNum++;
PreviousPoint = 0;
while (c != EOF && c != '\n') {
while (c == ' ')
c = getchar ();
/* read across */
IsNegative = 0;
if (c == '+')
c = getchar ();
else if (c == '-') {
IsNegative = 1;
c = getchar ();
}
FoundAcross = 0;
across = 0;
while (c >= '0' && c <= '9') {
FoundAcross = 1;
across = 10*across + (c - '0');
c = getchar ();
}
if (IsNegative)
across = - across;
if (c == ',')
c = getchar ();
else
FoundAcross = 0;
/* read down */
IsNegative = 0;
if (c == '+')
c = getchar ();
else if (c == '-') {
IsNegative = 1;
c = getchar ();
}
FoundDown = 0;
down = 0;
while (c >= '0' && c <= '9') {
FoundDown = 1;
down = 10*down + (c - '0');
c = getchar ();
}
if (IsNegative)
down = - down;
if (c != EOF && c != '\n' && c != ' ' && c != '#') {
fprintf (stderr, "***linetopbm: Improper");
fprintf (stderr, " '%c'", c);
fprintf (stderr, " in line #%u.\n", LineNum);
while (c != EOF && c != '\n' && c != ' '
&& c != '#')
c = getchar ();
ok = 0;
}
else if (FoundAcross && !FoundDown) {
fprintf (stderr, "***linetopbm: Incomplete");
fprintf (stderr, " across,down");
fprintf (stderr, " in line #%u.\n", LineNum);
ok = 0;
}
else if (FoundAcross && FoundDown) {
if (PreviousPoint) {
/* Add segment */;
SegmentPtr [0] = malloc (
sizeof (SegmentPtr [0] [0] ) );
if (SegmentPtr [0] == NULL) {
fprintf (stderr, "***");
fprintf (stderr, "linetopbm:");
fprintf (stderr, " Not enough");
fprintf (stderr, " memory.\n");
ok = 0;
}
else {
SegmentPtr [0]->across1
= PreviousAcross;
SegmentPtr [0]->down1
= PreviousDown;
SegmentPtr [0]->across2
= across;
SegmentPtr [0]->down2
= down;
SegmentPtr [0]->next
= NULL;
SegmentPtr
= & SegmentPtr [0]->next;
}
}
PreviousPoint = 1;
PreviousAcross = across;
PreviousDown = down;
}
if (c == '#') {
while (c != EOF && c != '\n')
c = getchar ();
}
}
if (c != EOF)
c = getchar ();
}
return ok;
}
int IsOnSegment (int across, int down, struct Segment * Segments)
{
struct Segment * Segment;
int m, n, x, y, temp;
Segment = Segments;
while (Segment != NULL) {
if (Segment->across1 > Segment->across2) {
m = Segment->across1 - Segment->across2 + 1;
y = Segment->across1 - across;
}
else {
m = Segment->across2 - Segment->across1 + 1;
y = across - Segment->across1;
}
if (Segment->down1 > Segment->down2) {
n = Segment->down1 - Segment->down2 + 1;
x = Segment->down1 - down;
}
else {
n = Segment->down2 - Segment->down1 + 1;
x = down - Segment->down1;
}
if (m > n) {
temp = n;
n = m;
m = temp;
temp = y;
y = x;
x = temp;
}
if (x >= 0 && x < n) {
if (y == (m/2 + m*x)/n)
return 1;
}
Segment = Segment->next;
}
return 0;
}
void WriteSegments (
struct Segment * Segments,
int width,
int height)
{
/* int i, j, k, m, LineSize, OutputBuffer, pixel; */
int across, down, OutputWeight, OutputValue;
printf ("P4\n%d %d\n", width, height);
for (down = - height/2; down < height - height/2; down++) {
OutputWeight = 128;
OutputValue = 0;
for (across = - width/2; across < width - width/2; across++) {
if (IsOnSegment (across, down, Segments) )
OutputValue += OutputWeight;
OutputWeight /= 2;
if (OutputWeight == 0) {
putchar (OutputValue);
OutputWeight = 128;
OutputValue = 0;
}
}
if (OutputWeight < 128)
putchar (OutputValue);
}
}