To run it, change to this directory, type `make', and then:
./ypp-commodities --tsv >commods.tsv
+or
+ ./ypp-commodities --upload
While it is capturing the screenshots, do not move the mouse or use
the keyboard. Keyboard focus must stay in the YPP client window.
typedef struct {
int w,h;
+ struct RgbImage *rgb;
char d[];
} CanonImage;
}
if (o_mode & mf_analyse) {
if (o_flags & ff_needisland) {
- find_islandname(page0_rgbimage);
+ find_islandname(page_images[0]->rgb);
if (o_flags & ff_printisland)
printf("%s, %s\n", archipelago, island);
sysassert(! setenv("YPPSC_ISLAND",island,1) );
*/
} RgbImage;
+typedef unsigned long Rgb;
+
void identify_rgbimage(const RgbImage *base, Rect portion,
char result[MAXIMGIDENT], const char *what);
RgbImage *alloc_rgb_image(int w, int h);
#define RI_PIXEL(ri,x,y) ((ri)->data + ((y)*(ri)->w + (x)) * 3)
+static inline Rgb ri_rgb(const RgbImage *ri, int x, int y) {
+ const unsigned char *rip= RI_PIXEL(ri,x,y);
+ return (rip[0] << 16) |
+ (rip[1] << 8) |
+ (rip[2] );
+}
+
/*----- from structure.c -----*/
void find_structure(const CanonImage *im, int *max_relevant_y_r);
#define MAX_PAGES 100
extern CanonImage *page_images[MAX_PAGES];
extern int npages;
-RgbImage *page0_rgbimage;
extern const char *ocean, *pirate;
extern char *archipelago, *island;
CanonImage *page_images[MAX_PAGES];
int npages;
-RgbImage *page0_rgbimage;
const char *ocean, *pirate;
last=*output; *output=0;
} else if (!identical(*output,last)) {
debugf("PAGING wait_for_stability changed...\n");
- free(last); last=*output; *output=0;
+ free_snapshot(&last); last=*output; *output=0;
nidentical=0;
if (!with_keypress) {
min_interval *= 3.0;
debugf("PAGING raise_and_set_focus done.\n");
}
-static CanonImage *convert_page(Snapshot *sn, RgbImage *ri) {
+static CanonImage *convert_page(Snapshot *sn) {
CanonImage *im;
fwrite_ppmraw(screenshot_file, sn);
- if (ri) memcpy(ri->data, sn->data, ri->h * ri->w * 3);
unsigned char *pixel= sn->data;
CANONICALISE_IMAGE(im, sn->w, sn->h, {
raise_and_get_details();
wait_for_stability(¤t,0,0, "checking current YPP client screen...");
- test= convert_page(current, 0);
+ test= convert_page(current);
find_structure(test, &max_relevant_y);
check_correct_commodities();
Rect sunshine= find_sunshine_widget();
void take_screenshots(void) {
Snapshot *current=0, *last=0;
- RgbImage *page0_store;
prepare_ypp_client();
wait_for_stability(¤t,0, send_pgup_many,
"paging up to top of commodity list...");
- page0_rgbimage= page0_store= alloc_rgb_image(current->w, current->h);
-
/* now to actually page down */
for (;;) {
debugf("paging page %d\n",npages);
fatal("Paging down seems to generate too many pages - max is %d.",
MAX_PAGES);
- page_images[npages]= convert_page(current, page0_store);
- free_snapshot(&last); last=current; current=0; page0_store=0;
+ page_images[npages]= convert_page(current);
+ free_snapshot(&last); last=current; current=0;
debugf("PAGING page %d converted\n",npages);
debugf("PAGING all done.\n");
progress_log("collected %d screenshots.",npages);
- assert(!page0_store);
}
void take_one_screenshot(void) {
prepare_ypp_client();
wait_for_stability(¤t,0,0, "taking screenshot...");
- page0_rgbimage= alloc_rgb_image(current->w, current->h);
- page_images[0]= convert_page(current, page0_rgbimage);
+ page_images[0]= convert_page(current);
npages= 1;
progress_log("collected single screenshot.");
}
#define REQUIRE_RECTANGLE(tlx,tly,brx,bry,ok) \
require_rectangle(tlx, tly, brx, bry, ok, __LINE__);
-static void require_rectangle(int tlx, int tly, int brx, int bry,
- const char *ok, int lineno) {
+#define FOR_P_RECT(p,rect) \
+ for ((p).x=(rr).tl.x; (p).x<=(rr).br.x; (p).x++) \
+ for ((p).y=(rr).tl.y; (p).y<=(rr).br.y; (p).y++)
+
+static void require_rectangle_r(Rect rr, const char *ok, int lineno) {
Point p;
- for (p.x=tlx; p.x<=brx; p.x++)
- for (p.y=tly; p.y<=bry; p.y++) {
- int c= get_p(p);
- MUST( strchr(ok,c), ({
- Rect rm={{tlx,tly},{brx,bry}};
- MI(lineno),MR(rm);MP(p);MS(ok);
- }));
- }
+ FOR_P_RECT(p,rr) {
+ int c= get_p(p);
+ MUST( strchr(ok,c), ({
+ MI(lineno),MR(rr);MP(p);MS(ok);
+ }));
+ }
}
-static void require_rectangle_r(Rect rr, const char *ok, int lineno) {
- require_rectangle(rr.tl.x,rr.tl.y, rr.br.x,rr.br.y, ok, lineno);
+static void require_rectangle(int tlx, int tly, int brx, int bry,
+ const char *ok, int lineno) {
+ Rect rr= {{tlx,tly},{brx,bry}};
+ require_rectangle_r(rr, ok, lineno);
}
static void debug_rect(const char *what, int whati, Rect rr) {
struct pam inpam;
unsigned char rgb_buf[3];
CanonImage *im;
- RgbImage *ri=0;
pnm_readpaminit(f, &inpam, sizeof(inpam));
if (!(inpam.maxval == 255 &&
inpam.format == RPPM_FORMAT))
fatal("PNM screenshot(s) file must be 8bpp 1 byte per sample RGB");
- if (!npages)
- page0_rgbimage= ri= alloc_rgb_image(inpam.width, inpam.height);
-
CANONICALISE_IMAGE(im, inpam.width, inpam.height, {
int r= fread(&rgb_buf,1,3,f);
sysassert(!ferror(f));
((unsigned long)rgb_buf[1]<<8) |
(rgb_buf[2]);
- if (ri)
- CANONIMG_ALSO_STORERGB(ri);
});
sysassert(!ferror(screenshot_file));
const unsigned char *srcp;
unsigned char *destp, *endp;
- for (srcp=page0_rgbimage->data, destp=ri->data,
+ for (srcp=page_images[0]->rgb->data, destp=ri->data,
endp= ri->data + 3 * ri->w * ri->h;
destp < endp;
srcp++, destp++) {
typedef struct {
- unsigned long rgb; /* on screen */
+ Rgb rgb; /* on screen */
char c; /* canonical */
} CanonColourInfo;
CanonImage *alloc_canon_image(int w, int h);
-#define CANONICALISE_IMAGE(im,w,h, COMPUTE_RGB) do{ \
- /* compute_rgb should be a number of statements, or \
- * a block, which assigns to \
- * unsigned long rgb; \
- * given the values of \
- * int x,y; \
- * all of which are anamorphic. Result is stored in im. \
- * The COMPUTE_RGB is executed exactly once for \
- * each pixel in reading order. \
- */ \
- (im)= alloc_canon_image((w), (h)); \
- \
- int x,y; \
- unsigned long last_rgb= ~0UL; \
- int last_c= -1; \
- for (y=0; y<(h); y++) { \
- for (x=0; x<(w); x++) { \
- const CanonColourInfo *cci; \
- unsigned long rgb; \
- COMPUTE_RGB; \
- if (rgb == last_rgb) { \
- (im)->d[y*(w) + x]= last_c; \
- } else { \
- for (cci=canoncolourinfos; cci->c; cci++) { \
- if (cci->rgb == rgb) { \
- last_rgb= rgb; \
- (im)->d[y*(w) + x]= last_c= cci->c; \
- break; \
- } \
- } \
- } \
- } \
- if (DEBUGP(rect)) { \
- fprintf(debug, "%4d ",y); \
- fwrite(im->d + y*w, 1,w, debug); \
- fputc('\n',debug); \
- } \
- } \
- debug_flush(); \
+#define CANONICALISE_IMAGE(im,w,h, COMPUTE_RGB) do{ \
+ /* compute_rgb should be a number of statements, or \
+ * a block, which assigns to \
+ * Rgb rgb; \
+ * given the values of \
+ * int x,y; \
+ * all of which are anamorphic. Result is stored in im. \
+ * The COMPUTE_RGB is executed exactly once for \
+ * each pixel in reading order. \
+ */ \
+ (im)= alloc_canon_image((w), (h)); \
+ (im)->rgb= alloc_rgb_image((w), (h)); \
+ \
+ int x,y; \
+ unsigned long last_rgb= ~0UL; \
+ int last_c= -1; \
+ for (y=0; y<(h); y++) { \
+ for (x=0; x<(w); x++) { \
+ const CanonColourInfo *cci; \
+ unsigned long rgb; \
+ COMPUTE_RGB; \
+ CANONIMG_ALSO_STORERGB((im)->rgb); \
+ if (rgb == last_rgb) { \
+ (im)->d[y*(w) + x]= last_c; \
+ } else { \
+ for (cci=canoncolourinfos; cci->c; cci++) { \
+ if (cci->rgb == rgb) { \
+ last_rgb= rgb; \
+ (im)->d[y*(w) + x]= last_c= cci->c; \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ if (DEBUGP(rect)) { \
+ fprintf(debug, "%4d ",y); \
+ fwrite(im->d + y*(w), 1,(w), debug); \
+ fputc('\n',debug); \
+ } \
+ } \
+ debug_flush(); \
}while(0)