On Fri, 2024-12-20 at 11:10 +0800, wij wrote:
On Thu, 2024-12-19 at 18:09 -0800, Keith Thompson wrote:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ross Finlayson <ross.a.finlayson@gmail.com> writes:
On 12/18/2024 08:14 PM, Keith Thompson wrote:
wij <wyniijj5@gmail.com> writes:
[...]
But, what is the true thing the program is dealing with? What is 'pixel'?
Do you really not know what a pixel is?
[...]
Pixel = "picture element"
You do know what a pixel is. So why did you ask?
My apologies, I didn't pay enough attention to the attribution lines.
wij write "What is 'pixel'"; Ross wrote 'Pixel = "picture element"'.
class Pixel { /* Whatever suitable */ };
int main() {
Array2D<Pixel> img;
load_picture(img, "mydog.jpg");
draw_circle(img, cx,cy, dim);
// cout.set_graphics_mode(...); // if necessary
// for(ssize_t y=img.height()-1; y>=0; --y) {
// cout << StrSeg(&img(0,y), img.width()) << WY_ENDL;
// }
cout << img; // the about can be simplified to one line
};
'Pixel' is just something you can write into Array2D
---------- a_rawkey.cpp
#include <Wy.stdio.h>
#include <Wy.string.h>
using namespace Wy;
int main(int, char* [])
try {
const char usage[]="Type arrow keys (Up,Down,Left,Down) to move around, 'ESC' to exit." WY_ENDL;
Errno r;
cout << usage;
constexpr WeeStr KeyESC("\33");
constexpr WeeStr KeyUp("\33[A");
constexpr WeeStr KeyDown("\33[B");
constexpr WeeStr KeyRight("\33[C");
constexpr WeeStr KeyLeft("\33[D");
constexpr WeeStr CursorUp("\33[1A");
constexpr WeeStr CursorDown("\33[1B");
constexpr WeeStr CursorRight("\33[1C");
constexpr WeeStr CursorLeft("\33[1D");
WeeStr stroke;
for(;;) {
if((r=_get_rawkey(cin,stroke))!=Ok) {
WY_THROW(r);
}
if(stroke==KeyESC) {
break;
}
if(stroke==KeyUp) {
cout << CursorUp;
} else if(stroke==KeyLeft) {
cout << CursorLeft;
} else if(stroke==KeyDown) {
cout << CursorDown;
} else if(stroke==KeyRight) {
cout << CursorRight;
} else {};
}
return 0;
}
catch(const Errno& e) {
cerr << wrd(e) << WY_ENDL;
return e.c_errno();
}
catch(...) {
cerr << "main caught(...)" WY_ENDL;
throw;
};
------------
If the key code from raw mode tty is defined (maybe, but I don't know),
I think C++ writing vi like editor should be much simpler, no need for ncurses.
If back to 'graphics', Pixel can be CSI sequence in this case.
My purpose is a 'C++ graphics'. No need to consider various kinds of
graphics accelerators or 'GUI', which cannot be standardized and would be
wrong goal.
What I now trying to experiment is separating graphics things to another
process. By doing so, 'the C++ code' just plays with Array2D<Pixel>, no need
to include those (mostly) heavy graphics library.
I just wrote two program (face_svr.cpp, face_cli.cpp) to test what I thought.
It looks plausible using C++ to write graphic programs without using any
graphic library. Dream come true! 'C++ graphics' is possible and easy.
'face' just implemented basic capability of showing image. GUI has many
graphics user interactions. From current result, I think simple GUI program
can be done easily.
face_svr.cpp has 140 lines, not shown.
------- face.h
/* Copyright is licensed by GNU LGPL, see file COPYING. by I.J.Wang 2024
<!!=ddd........>
<RS=n w h pixtype>xxx // n=size of next packet, pixtype=RGB32
*/
#ifndef WY__FACE_H__
#define WY__FACE_H__
#include <CSCall/Vect.h>
#include <CSCall/WeeStr.h>
constexpr Wy::WeeStr RGB32("RGB32");
typedef Wy::Vect<unsigned char,4> Pixel;
constexpr Pixel RGB32_White({255,255,255,0xff}); // blue,green,red
constexpr Pixel RGB32_Black({0,0,0,0xff});
#endif // WY__FACE_H__
------- face_cli.cpp
include <Wy.stdio.h>
#include <Wy.unistd.h>
#include <Wy.signal.h>
#include <CSCall/DrawPlane.h>
#include <CSCall/Array2D.h>
#include <CSCall/XnStream.h>
#include "face.h"
using namespace Wy;
// [Syn] Draw demo image
void draw_demo(Array2D<Pixel>& pic) {
const unsigned int cx=pic.width()/2;
const unsigned int cy=pic.height()/2;
pic.fill(RGB32_Black);
draw_solid_circle(pic.header(),cx,cy,30,RGB32_White);
for(unsigned int rad=45; rad<=150; rad+=15) {
draw_circle(pic.header(),cx,cy,rad,RGB32_White);
}
};
// [Syn] Make RS packet (for sending image)
String mkpkt_RS(unsigned int w, unsigned h, WeeStr pixtype, size_t psize) {
String str("<RS=");
str << wrd(psize) << ' ' << wrd(w) << ' ' << wrd(h) << ' ' << pixtype.c_str() << '>';
return str;
};
// [Syn] Fork a process exec 'face' program and send $image for it to display
// $cpid= pid of the 'face' program
//
Errno face_set_image(const Array2D<Pixel>& image, ProcessID& cpid) try {
Errno r;
String rspkt;
rspkt= mkpkt_RS(image.width(),image.height(),RGB32,image.size()*sizeof(Pixel));
FifoFile ffrd,ffwr;
char arg0[]="./face";
char* argarr[]={arg0,NULL};
if((r=popen(cpid,ffrd,ffwr,"./face",argarr))!=Ok) {
WY_THROW(r);
}
char buf[20];
if(_write_sizepacket(buf,rspkt.size())==NULL) {
WY_THROW( Errno(errno) );
}
ffwr << StrSeg(buf,PktHeaderSize);
ffwr << rspkt;
ffwr << StrSeg(reinterpret_cast<const char*>(image._data()),
image.size()*sizeof(Pixel));
return Ok;
}
catch(const Errno& e) {
return e;
};
int main(int argc, const char* argv[])
try {
const unsigned int PicWidth=800;
const unsigned int PicHeight=600;
Errno r;
Array2D<Pixel> pic(PicWidth,PicHeight);
String rspkt;
ProcessID cpid;
draw_demo(pic);
face_set_image(pic,cpid); // two windows
face_set_image(pic,cpid);
WaitStat wstt;
if((r=waitpid(cpid,&wstt,0))!=Ok) {
WY_THROW(r);
}
cout << "Child exit " << wstt.exit_status() << WY_ENDL;
return 0;
}
catch(const Errno& e) {
cerr << wrd(e) << WY_ENDL;
return -1; // e.c_errno();
}
catch(...) {
cerr << "main() caught(...)" WY_ENDL;
throw;
};