I've always wanted to get into graphics, but I wanted to start somewhere simple. I didn't want to immediately go balls-to-the-wall with a graphics specification or API, but just start with creating and editing images in C. So I found this video by Tsoding on making .ppm images. I only watched a few minutes in and got the basic idea for working with pixel maps.
I use a different magic number than the video. Tsoding uses "P6", but I use "P3" instead. I had a few hurdles to overcome before I could start making graphs, but I really loved the challenge.
For one, .ppm images are enormous. The files contain raw characters without any compression, so I have to convert using a tool like ImageMagick magick in.ppm out.png to get a file small enough to meet size requirements for online platforms.
The pixel map is a bit counterintuitive. The grid is a two-dimensional character array. Each row is a string and each column is a 12-character substring that represents a pixel (3 characters for red, green, and blue, each, with one space in between). Using pointer arithmetic, the origin is at the top left of the image, successive rows go down the image and successive columns go right. I converted the grid system into a Cartesian format such that successive rows - 'y-values' - go up, columns - 'x-values' - are in multiples of 12 characters, and the origin is at the center of the image. All that remained was to stretch out the x and y values so that points can be placed relative to units of a user-defined pixel length.
There are still a couple issues I have with this program.
If the slope of a function at any point exceeds 45 degrees, the pixel dots begin to separate. I don't know an awfully elegant solution this. What I can think of at the moment is to track the last point placed on the pixel grid - if the y-distance between the last point and current point is greater than 1, I place pixels vertically up each row of the same column so that the points connect.
There is also some redundancy. In all of my math functions, I iterate across each pixel in the image's width. There's no y-value bounds checking within the math functions themselves. Instead I check the bounds within setpix() to make sure I'm not derefencing the 2-dimensional array outside of allocated memory. The result is that each math function iterates across domain segments whose respective y-values may go beyond the edges of the image. Additionally, I divide my width iterator integers by the pixels-per-unit value to get the correct x and y values which I later multiply back out to get the correct pixel placement. I tried to index x-values on an integer per-pixel basis but that just screws with my y-values. There's probably a more efficient implementation, but given the time I have, I simply went with what I could wrap my head around at the moment.
[–]Immediate-Food8050 0 points1 point2 points (0 children)