kopia lustrzana https://github.com/jamescoxon/dl-fldigi
514 wiersze
13 KiB
C++
514 wiersze
13 KiB
C++
// ----------------------------------------------------------------------------
|
|
// mfsk-pic.cxx -- mfsk support functions
|
|
//
|
|
// Copyright (C) 2006
|
|
// Dave Freese, W1HKJ
|
|
//
|
|
// This file is part of fldigi. Adapted from code contained in gmfsk source code
|
|
// distribution.
|
|
// gmfsk Copyright (C) 2001, 2002, 2003
|
|
// Tomi Manninen (oh2bns@sral.fi)
|
|
//
|
|
// fldigi is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// fldigi is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with fldigi; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "gettext.h"
|
|
|
|
Fl_Double_Window *picRxWin = (Fl_Double_Window *)0;
|
|
|
|
picture *picRx = (picture *)0;
|
|
Fl_Button *btnpicRxSave = (Fl_Button *)0;
|
|
Fl_Button *btnpicRxAbort = (Fl_Button *)0;
|
|
Fl_Button *btnpicRxClose = (Fl_Button *)0;
|
|
|
|
Fl_Double_Window *picTxWin = (Fl_Double_Window *)0;
|
|
|
|
picture *picTx = (picture *)0;
|
|
picbox *picTxBox = 0;
|
|
Fl_Button *btnpicTxSPP = (Fl_Button *)0;
|
|
Fl_Button *btnpicTxSendColor = (Fl_Button *)0;
|
|
Fl_Button *btnpicTxSendGrey = (Fl_Button *)0;
|
|
Fl_Button *btnpicTxSendAbort = (Fl_Button *)0;
|
|
Fl_Button *btnpicTxLoad = (Fl_Button *)0;
|
|
Fl_Button *btnpicTxClose = (Fl_Button *)0;
|
|
|
|
Fl_Shared_Image *TxImg = (Fl_Shared_Image *)0;
|
|
unsigned char *xmtimg = (unsigned char *)0;
|
|
unsigned char *xmtpicbuff = (unsigned char *)0;
|
|
|
|
mfsk *serviceme = 0;
|
|
int txSPP = 8;
|
|
|
|
char txclr_tooltip[24];
|
|
char txgry_tooltip[24];
|
|
|
|
void updateRxPic(unsigned char data, int pos)
|
|
{
|
|
picRx->pixel(data, pos);
|
|
}
|
|
|
|
void cb_picRxClose( Fl_Widget *w, void *)
|
|
{
|
|
picRxWin->hide();
|
|
}
|
|
|
|
void cb_picRxAbort( Fl_Widget *w, void *)
|
|
{
|
|
if (serviceme != active_modem) return;
|
|
serviceme->rxstate = serviceme->RX_STATE_DATA;
|
|
put_status("");
|
|
picRx->clear();
|
|
}
|
|
|
|
void cb_picRxSave( Fl_Widget *w, void *)
|
|
{
|
|
const char ffilter[] = ""
|
|
#if USE_LIBPNG
|
|
"Portable Network Graphics\t*.png\n"
|
|
#endif
|
|
#if USE_LIBJPEG
|
|
"Independent JPEG Group\t*.{jpg,jpeg}"
|
|
#endif
|
|
;
|
|
const char dfname[] = "image."
|
|
#if USE_LIBPNG
|
|
"png"
|
|
#else
|
|
"jpg"
|
|
#endif
|
|
;
|
|
|
|
int fsel;
|
|
const char *fn = FSEL::saveas(_("Save image as:"), ffilter, dfname, &fsel);
|
|
if (!fn) return;
|
|
// selected filter determines format
|
|
switch (fsel) {
|
|
case 0:
|
|
#if USE_LIBPNG
|
|
picRx->save_png(fn);
|
|
break;
|
|
#endif
|
|
// fall through if no libpng
|
|
case 1:
|
|
#if USE_LIBJPEG
|
|
picRx->save_jpeg(fn);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
void createRxViewer()
|
|
{
|
|
FL_LOCK_D();
|
|
picRxWin = new Fl_Double_Window(200, 140);
|
|
picRxWin->xclass(PACKAGE_NAME);
|
|
picRxWin->begin();
|
|
|
|
picRx = new picture(2, 2, 136, 104);
|
|
btnpicRxSave = new Fl_Button(5, 140 - 30, 60, 24,_("Save..."));
|
|
btnpicRxSave->callback(cb_picRxSave, 0);
|
|
btnpicRxSave->hide();
|
|
#if !(USE_LIBPNG || USE_LIBJPEG)
|
|
btnpicRxSave->deactivate();
|
|
#endif
|
|
btnpicRxAbort = new Fl_Button(70, 140 - 30, 60, 24, _("Abort"));
|
|
btnpicRxAbort->callback(cb_picRxAbort, 0);
|
|
btnpicRxClose = new Fl_Button(135, 140 - 30, 60, 24, _("Hide"));
|
|
btnpicRxClose->callback(cb_picRxClose, 0);
|
|
|
|
picRxWin->end();
|
|
FL_UNLOCK_D();
|
|
}
|
|
|
|
void showRxViewer(int W, int H)
|
|
{
|
|
FL_LOCK_E();
|
|
if (!picRxWin) createRxViewer();
|
|
int winW, winH;
|
|
int picX, picY;
|
|
winW = W < 136 ? 140 : W + 4;
|
|
winH = H + 34;
|
|
picX = (winW - W) / 2;
|
|
picY = 2;
|
|
picRxWin->size(winW, winH);
|
|
picRx->resize(picX, picY, W, H);
|
|
btnpicRxSave->resize(winW/2 - 65, H + 6, 60, 24);
|
|
btnpicRxSave->hide();
|
|
btnpicRxAbort->resize(winW/2 - 65, H + 6, 60, 24);
|
|
btnpicRxAbort->show();
|
|
btnpicRxClose->resize(winW/2 + 5, H + 6, 60, 24);
|
|
picRx->clear();
|
|
picRxWin->show();
|
|
FL_UNLOCK_E();
|
|
}
|
|
|
|
void load_image(const char *n) {
|
|
|
|
if (serviceme != active_modem) return;
|
|
|
|
int W, H, D;
|
|
unsigned char *img_data;
|
|
|
|
if (TxImg) {
|
|
TxImg->release();
|
|
TxImg = 0;
|
|
}
|
|
TxImg = Fl_Shared_Image::get(n);
|
|
if (!TxImg)
|
|
return;
|
|
if (TxImg->count() > 1) { // we only handle rgb images
|
|
TxImg->release();
|
|
TxImg = 0;
|
|
return;
|
|
}
|
|
img_data = (unsigned char *)TxImg->data()[0];
|
|
W = TxImg->w();
|
|
H = TxImg->h();
|
|
D = TxImg->d();
|
|
if (xmtimg) delete [] xmtimg;
|
|
xmtimg = new unsigned char [W * H * 3];
|
|
if (D == 3)
|
|
memcpy(xmtimg, img_data, W*H*3);
|
|
else if (D == 4) {
|
|
int i, j, k;
|
|
for (i = 0; i < W*H; i++) {
|
|
j = i*3; k = i*4;
|
|
xmtimg[j] = img_data[k];
|
|
xmtimg[j+1] = img_data[k+1];
|
|
xmtimg[j+2] = img_data[k+2];
|
|
}
|
|
} else if (D == 1) {
|
|
int i, j;
|
|
for (i = 0; i < W*H; i++) {
|
|
j = i * 3;
|
|
xmtimg[j] = xmtimg[j+1] = xmtimg[j+2] = img_data[i];
|
|
}
|
|
} else
|
|
return;
|
|
|
|
TxViewerResize(W, H);
|
|
char* label = strdup(n);
|
|
picTxWin->copy_label(basename(label));
|
|
free(label);
|
|
picTxBox->label(0);
|
|
// load the picture widget with the rgb image
|
|
FL_LOCK_D();
|
|
picTx->show();
|
|
picTx->clear();
|
|
picTxWin->redraw();
|
|
picTx->video(xmtimg, W * H * 3);
|
|
if (print_time_left( (W * H * 3) * 0.000125 * serviceme->TXspp,
|
|
txclr_tooltip, sizeof(txclr_tooltip), _("Time needed: ")) > 0)
|
|
btnpicTxSendColor->tooltip(txclr_tooltip);
|
|
btnpicTxSendColor->activate();
|
|
if (print_time_left( (W * H) * 0.000125 * serviceme->TXspp,
|
|
txgry_tooltip, sizeof(txgry_tooltip), _("Time needed: ")) > 0)
|
|
btnpicTxSendGrey->tooltip(txgry_tooltip);
|
|
btnpicTxSendGrey->activate();
|
|
FL_UNLOCK_D();
|
|
}
|
|
|
|
void updateTxPic(unsigned char data)
|
|
{
|
|
if (serviceme != active_modem) return;
|
|
if (serviceme->color) {
|
|
serviceme->pixelnbr = serviceme->rgb + serviceme->row + 3*serviceme->col;
|
|
picTx->pixel(data, serviceme->pixelnbr);
|
|
if (++serviceme->col == TxImg->w()) {
|
|
serviceme->col = 0;
|
|
if (++serviceme->rgb == 3) {
|
|
serviceme->rgb = 0;
|
|
serviceme->row += 3 * TxImg->w();
|
|
}
|
|
}
|
|
} else {
|
|
picTx->pixel( data, serviceme->pixelnbr++ );
|
|
picTx->pixel( data, serviceme->pixelnbr++ );
|
|
picTx->pixel( data, serviceme->pixelnbr++ );
|
|
}
|
|
}
|
|
|
|
void cb_picTxLoad(Fl_Widget *, void *)
|
|
{
|
|
const char *fn =
|
|
FSEL::select(_("Load image file"), "Portable Network Graphics\t*.png\n"
|
|
"Independent JPEG Group\t*.{jpg,jif,jpeg,jpe}\n"
|
|
"Graphics Interchange Format\t*.gif");
|
|
if (!fn) return;
|
|
load_image(fn);
|
|
}
|
|
|
|
void cb_picTxClose( Fl_Widget *w, void *)
|
|
{
|
|
FL_LOCK_D();
|
|
picTxWin->hide();
|
|
FL_UNLOCK_D();
|
|
}
|
|
|
|
void cb_picTxSendColor( Fl_Widget *w, void *)
|
|
{
|
|
int W, H, rowstart;
|
|
W = TxImg->w();
|
|
H = TxImg->h();
|
|
if (xmtpicbuff) delete [] xmtpicbuff;
|
|
xmtpicbuff = new unsigned char [W*H*3];
|
|
unsigned char *outbuf = xmtpicbuff;
|
|
unsigned char *inbuf = xmtimg;
|
|
int iy, ix, rgb;
|
|
for (iy = 0; iy < H; iy++) {
|
|
rowstart = iy * W * 3;
|
|
for (rgb = 0; rgb < 3; rgb++)
|
|
for (ix = 0; ix < W; ix++)
|
|
outbuf[rowstart + rgb*W + ix] = inbuf[rowstart + rgb + ix*3];
|
|
}
|
|
if (serviceme->TXspp == 8)
|
|
snprintf(serviceme->picheader, PICHEADER, "\nSending Pic:%dx%dC;", W, H);
|
|
else
|
|
snprintf(serviceme->picheader, PICHEADER, "\nSending Pic:%dx%dCp%d;", W, H,serviceme->TXspp);
|
|
serviceme->xmtbytes = W * H * 3;
|
|
serviceme->color = true;
|
|
serviceme->rgb = 0;
|
|
serviceme->col = 0;
|
|
serviceme->row = 0;
|
|
serviceme->pixelnbr = 0;
|
|
FL_LOCK_D();
|
|
btnpicTxSPP->hide();
|
|
btnpicTxSendColor->hide();
|
|
btnpicTxSendGrey->hide();
|
|
btnpicTxLoad->hide();
|
|
btnpicTxClose->hide();
|
|
btnpicTxSendAbort->show();
|
|
picTx->clear();
|
|
FL_UNLOCK_D();
|
|
// start the transmission
|
|
start_tx();
|
|
serviceme->startpic = true;
|
|
}
|
|
|
|
void cb_picTxSendGrey( Fl_Widget *w, void *)
|
|
{
|
|
if (serviceme != active_modem) return;
|
|
|
|
int W, H;
|
|
W = TxImg->w();
|
|
H = TxImg->h();
|
|
if (xmtpicbuff) delete [] xmtpicbuff;
|
|
xmtpicbuff = new unsigned char [W*H];
|
|
unsigned char *outbuf = xmtpicbuff;
|
|
unsigned char *inbuf = xmtimg;
|
|
for (int i = 0; i < W*H; i++)
|
|
outbuf[i] = ( 31 * inbuf[i*3] + 61 * inbuf[i*3 + 1] + 8 * inbuf[i*3 + 2])/100;
|
|
if (serviceme->TXspp == 8)
|
|
snprintf(serviceme->picheader, PICHEADER, "\nSending Pic:%dx%d;", W, H);
|
|
else
|
|
snprintf(serviceme->picheader, PICHEADER, "\nSending Pic:%dx%dp%d;", W, H,serviceme->TXspp);
|
|
serviceme->xmtbytes = W * H;
|
|
serviceme->color = false;
|
|
serviceme->col = 0;
|
|
serviceme->row = 0;
|
|
serviceme->pixelnbr = 0;
|
|
FL_LOCK_D();
|
|
btnpicTxSPP->hide();
|
|
btnpicTxSendColor->hide();
|
|
btnpicTxSendGrey->hide();
|
|
btnpicTxLoad->hide();
|
|
btnpicTxClose->hide();
|
|
btnpicTxSendAbort->show();
|
|
picTx->clear();
|
|
FL_UNLOCK_D();
|
|
// start the transmission
|
|
start_tx();
|
|
serviceme->startpic = true;
|
|
}
|
|
|
|
|
|
void cb_picTxSendAbort( Fl_Widget *w, void *)
|
|
{
|
|
if (serviceme != active_modem) return;
|
|
|
|
serviceme->abortxmt = true;
|
|
// reload the picture widget with the rgb image
|
|
FL_LOCK_D();
|
|
picTx->video(xmtimg, TxImg->w() * TxImg->h() * 3);
|
|
FL_UNLOCK_D();
|
|
}
|
|
|
|
void cb_picTxSPP( Fl_Widget *w, void *)
|
|
{
|
|
if (serviceme != active_modem) return;
|
|
|
|
Fl_Button *b = (Fl_Button *)w;
|
|
if (progdefaults.slowcpu == true)
|
|
serviceme->TXspp = 8;
|
|
else {
|
|
if (serviceme->TXspp == 8) serviceme->TXspp = 4;
|
|
else if (serviceme->TXspp == 4) serviceme->TXspp = 2;
|
|
else serviceme->TXspp = 8;
|
|
}
|
|
if (serviceme->TXspp == 8) b->label("X1");
|
|
else if (serviceme->TXspp == 4) b->label("X2");
|
|
else b->label("X4");
|
|
b->redraw_label();
|
|
txSPP = serviceme->TXspp;
|
|
|
|
if (TxImg == 0) return;
|
|
if (TxImg->w() > 0 && TxImg->h() > 0) {
|
|
if (print_time_left( (TxImg->w() * TxImg->h() * 3) * 0.000125 * serviceme->TXspp,
|
|
txclr_tooltip, sizeof(txclr_tooltip), _("Time needed: ")) > 0)
|
|
btnpicTxSendColor->tooltip(txclr_tooltip);
|
|
if (print_time_left( (TxImg->w() * TxImg->h()) * 0.000125 * serviceme->TXspp,
|
|
txgry_tooltip, sizeof(txgry_tooltip), _("Time needed: ")) > 0)
|
|
btnpicTxSendGrey->tooltip(txgry_tooltip);
|
|
}
|
|
}
|
|
|
|
void createTxViewer()
|
|
{
|
|
FL_LOCK_D();
|
|
picTxWin = new Fl_Double_Window(290, 180, _("Send image"));
|
|
picTxWin->xclass(PACKAGE_NAME);
|
|
picTxWin->begin();
|
|
|
|
picTx = new picture (2, 2, 286, 150);
|
|
picTx->hide();
|
|
picTxBox = new picbox(picTxWin->x(), picTxWin->y(), picTxWin->w(), picTxWin->h(),
|
|
_("Load or drop an image file\nSupported types: PNG, JPEG, BMP"));
|
|
picTxBox->labelfont(FL_HELVETICA_ITALIC);
|
|
|
|
btnpicTxSPP = new Fl_Button(5, 180 - 30, 40, 24, "X1");
|
|
btnpicTxSPP->tooltip(_("Transfer speed, X1-normal"));
|
|
btnpicTxSPP->callback( cb_picTxSPP, 0);
|
|
|
|
btnpicTxSendColor = new Fl_Button(45, 180 - 30, 60, 24, "XmtClr");
|
|
btnpicTxSendColor->callback(cb_picTxSendColor, 0);
|
|
|
|
btnpicTxSendGrey = new Fl_Button(105, 180 - 30, 60, 24, "XmtGry");
|
|
btnpicTxSendGrey->callback( cb_picTxSendGrey, 0);
|
|
|
|
btnpicTxSendAbort = new Fl_Button(84, 180 - 30, 122, 24, "Abort Xmt");
|
|
btnpicTxSendAbort->callback(cb_picTxSendAbort, 0);
|
|
|
|
btnpicTxLoad = new Fl_Button(165, 180 - 30, 60, 24, _("Load"));
|
|
btnpicTxLoad->callback(cb_picTxLoad, 0);
|
|
|
|
btnpicTxClose = new Fl_Button(225, 180 - 30, 60, 24, _("Close"));
|
|
btnpicTxClose->callback(cb_picTxClose, 0);
|
|
|
|
btnpicTxSendAbort->hide();
|
|
btnpicTxSendColor->deactivate();
|
|
btnpicTxSendGrey->deactivate();
|
|
|
|
picTxWin->end();
|
|
FL_UNLOCK_D();
|
|
}
|
|
|
|
void TxViewerResize(int W, int H)
|
|
{
|
|
int winW, winH;
|
|
int picX, picY;
|
|
winW = W < 288 ? 290 : W + 4;
|
|
winH = H < 180 ? 180 : H + 30;
|
|
picX = (winW - W) / 2;
|
|
picY = (winH - 30 - H)/2;
|
|
FL_LOCK_D();
|
|
picTxWin->size(winW, winH);
|
|
picTx->resize(picX, picY, W, H);
|
|
picTx->clear();
|
|
picTxBox->size(winW, winH);
|
|
btnpicTxSPP->resize(winW/2 - 140, winH - 28, 40, 24);
|
|
btnpicTxSendColor->resize(winW/2 - 100, winH - 28, 60, 24);
|
|
btnpicTxSendGrey->resize(winW/2 - 40, winH - 28, 60, 24);
|
|
btnpicTxSendAbort->resize(winW/2 - 61, winH - 28, 122, 24);
|
|
btnpicTxLoad->resize(winW/2 + 20, winH - 28, 60, 24);
|
|
btnpicTxClose->resize(winW/2 + 80, winH - 28, 60, 24);
|
|
FL_UNLOCK_D();
|
|
}
|
|
|
|
void showTxViewer(int W, int H)
|
|
{
|
|
if (picTxWin) {
|
|
picTxWin->show();
|
|
return;
|
|
}
|
|
|
|
int winW, winH;
|
|
int picX, picY;
|
|
winW = W < 288 ? 290 : W + 4;
|
|
winH = H < 180 ? 180 : H + 30;
|
|
picX = (winW - W) / 2;
|
|
picY = 2;
|
|
FL_LOCK_D();
|
|
picTxWin->size(winW, winH);
|
|
picTx->resize(picX, picY, W, H);
|
|
btnpicTxSPP->resize(winW/2 - 140, winH - 28, 40, 24);
|
|
btnpicTxSendColor->resize(winW/2 - 100, winH - 28, 60, 24);
|
|
btnpicTxSendGrey->resize(winW/2 - 40, winH - 28, 60, 24);
|
|
btnpicTxSendAbort->resize(winW/2 - 61, winH - 28, 122, 24);
|
|
btnpicTxLoad->resize(winW/2 + 20, winH - 28, 60, 24);
|
|
btnpicTxClose->resize(winW/2 + 80, winH - 28, 60, 24);
|
|
btnpicTxSPP->show();
|
|
btnpicTxSendColor->show();
|
|
btnpicTxSendGrey->show();
|
|
btnpicTxLoad->show();
|
|
btnpicTxClose->show();
|
|
btnpicTxSendAbort->hide();
|
|
picTxWin->show();
|
|
FL_UNLOCK_D();
|
|
}
|
|
|
|
void deleteTxViewer()
|
|
{
|
|
picTxWin->hide();
|
|
if (picTx) delete picTx;
|
|
delete [] xmtimg;
|
|
xmtimg = 0;
|
|
delete [] xmtpicbuff;
|
|
xmtpicbuff = 0;
|
|
delete picTxWin;
|
|
picTxWin = 0;
|
|
serviceme = 0;
|
|
}
|
|
|
|
void deleteRxViewer()
|
|
{
|
|
picRxWin->hide();
|
|
if (picRx) {
|
|
delete picRx;
|
|
picRx = 0;
|
|
}
|
|
delete picRxWin;
|
|
picRxWin = 0;
|
|
serviceme = 0;
|
|
}
|
|
|
|
int print_time_left(float time_sec, char *str, size_t len,
|
|
const char *prefix, const char *suffix)
|
|
{
|
|
int time_min = (int)(time_sec / 60);
|
|
time_sec -= time_min * 60;
|
|
|
|
if (time_min)
|
|
return snprintf(str, len, "%s%02dm%2.1fs%s",
|
|
prefix, time_min, time_sec, suffix);
|
|
else
|
|
return snprintf(str, len, "%s%2.1fs%s", prefix, time_sec, suffix);
|
|
}
|
|
|
|
void setpicture_link(mfsk *me)
|
|
{
|
|
serviceme = me;
|
|
}
|
|
|