Add PNG save support

pull/2/head
Stelios Bounanos 2008-04-15 08:01:37 +01:00
rodzic c85ee8da3c
commit 226e560cb4
3 zmienionych plików z 115 dodań i 39 usunięć

Wyświetl plik

@ -61,7 +61,8 @@ public:
void clear();
void image(Fl_Image *img) {Fl_Widget::image(img);}
void resize(int, int, int, int);
int save_jpeg(const char *);
int save_jpeg(const char *);
int save_png(const char *);
};
#endif

Wyświetl plik

@ -253,8 +253,8 @@ void mfsk::recvpic(complex z)
if (color) {
pixelnbr = rgb + row + 3*col;
updateRxPic(byte, pixelnbr);
// REQ(&mfsk::updateRxPic, this, byte, pixelnbr);
//! updateRxPic(byte, pixelnbr);
REQ(updateRxPic, byte, pixelnbr);
if (++col == picW) {
col = 0;
if (++rgb == 3) {
@ -264,8 +264,8 @@ void mfsk::recvpic(complex z)
}
} else {
for (int i = 0; i < 3; i++)
updateRxPic(byte, pixelnbr);
// REQ(&mfsk::updateRxPic, this, byte, pixelnbr++);
//! updateRxPic(byte, pixelnbr++);
REQ(updateRxPic, byte, pixelnbr++);
}
picf = 0.0;
@ -566,10 +566,10 @@ int mfsk::rx_process(const double *buf, int len)
rxstate = RX_STATE_DATA;
// REQ_FLUSH();
put_status("");
#ifndef __CYGWIN__
//#ifndef __CYGWIN__
string autosave_dir = HomeDir + "mfsk_pics/";
picRx->save_jpeg(autosave_dir.c_str());
#endif
picRx->save_png(autosave_dir.c_str());
//#endif
} else
recvpic(z);
continue;
@ -696,8 +696,8 @@ void mfsk::sendpic(unsigned char *data, int len)
for (i = 0; i < len; i++) {
if (txstate == TX_STATE_PICTURE)
updateTxPic(data[i], this);
// REQ(&mfsk::updateTxPic, this, data[i]);
//! updateTxPic(data[i], this);
REQ(updateTxPic, data[i], this);
if (reverse)
f = get_txfreq_woffset() - bandwidth * (data[i] - 128) / 256.0;
else
@ -877,14 +877,14 @@ void cb_picRxSave( Fl_Widget *w, void *who)
{
// mfsk *me = (mfsk *)who;
const char *fn =
file_saveas( "Save image as:", "Independent JPEG Group\t*.{jpg,jpeg}", NULL );
file_saveas( "Save image as:", "Portable Network Graphics\t*.png", "." );
if (!fn) return;
picRx->save_jpeg(fn);
picRx->save_png(fn);
}
void createRxViewer(mfsk *who)
{
FL_LOCK_E();
FL_LOCK_D();
picRxWin = new Fl_Double_Window(200, 140);
picRxWin->xclass(PACKAGE_NAME);
picRx = new picture(2, 2, 136, 104);
@ -898,11 +898,12 @@ void createRxViewer(mfsk *who)
btnpicRxClose = new Fl_Button(135, 140 - 30, 60, 24, "Hide");
btnpicRxClose->callback(cb_picRxClose, who);
activate_mfsk_image_item(true);
FL_UNLOCK_E();
FL_UNLOCK_D();
}
void showRxViewer(int W, int H, mfsk *who)
{
FL_LOCK_E();
if (!picRxWin) createRxViewer(who);
int winW, winH;
int picX, picY;
@ -910,7 +911,6 @@ void showRxViewer(int W, int H, mfsk *who)
winH = H + 34;
picX = (winW - W) / 2;
picY = 2;
FL_LOCK_D();
picRxWin->size(winW, winH);
picRx->resize(picX, picY, W, H);
btnpicRxSave->resize(winW/2 - 65, H + 6, 60, 24);
@ -919,7 +919,7 @@ void showRxViewer(int W, int H, mfsk *who)
#ifndef __CYGWIN__
picRxWin->show();
#endif
FL_UNLOCK_D();
FL_UNLOCK_E();
}
void load_file(const char *n) {

Wyświetl plik

@ -57,6 +57,7 @@ extern "C" {
//# include "transupp.h"
};
#include <png.h>
#include "picture.h"
@ -237,6 +238,43 @@ int picture::handle(int event)
return 0;
}
static FILE* open_file(const char* name, const char* suffix)
{
FILE* fp;
size_t flen = strlen(name);
if (name[flen - 1] == '/') {
// if the name ends in a slash we will generate
// a timestamped name in the following format:
const char t[] = "pic_YYYY-MM-DD_HHMMSSz";
size_t newlen = flen + sizeof(t);
if (suffix)
newlen += 5;
char* newfn = new char[newlen];
memcpy(newfn, name, flen);
time_t time_sec = time(0);
struct tm ztime;
(void)gmtime_r(&time_sec, &ztime);
size_t sz;
if ((sz = strftime(newfn + flen, newlen - flen, "pic_%F_%H%M%Sz", &ztime)) > 0) {
strncpy(newfn + flen + sz, suffix, newlen - flen - sz);
newfn[newlen - 1] = '\0';
mkdir(name, 0777);
fp = fopen(newfn, "wb");
}
else
fp = NULL;
delete [] newfn;
}
else
fp = fopen(name, "wb");
return fp;
}
//
// save_jpeg - Write a captured picture to a JPEG format file.
//
@ -248,29 +286,8 @@ int picture::save_jpeg(const char *filename)
struct jpeg_compress_struct info; // Compressor info
struct jpeg_error_mgr err; // Error handler info
size_t flen = strlen(filename);
if (filename[flen - 1] == '/') {
// if the filename ends in a slash we will generate
// a timestamped filename in the following format:
const char t[] = "pic_YYYY-MM-DD_HH:MM:SSz.jpg";
size_t newlen = flen + sizeof(t);
char newfn[newlen];
memcpy(newfn, filename, flen);
time_t time_sec = time(0);
struct tm ztime;
(void)gmtime_r(&time_sec, &ztime);
if (strftime(newfn + flen, newlen - flen, "pic_%F_%Tz.jpg", &ztime) > 0) {
mkdir(filename, 0777);
if ((fp = fopen(newfn, "wb")) == NULL)
return -1;
}
}
else
if ((fp = fopen(filename, "wb")) == NULL)
return -1;
if ((fp = open_file(filename, ".jpg")) == NULL)
return -1;
// Setup the JPEG compression stuff...
info.err = jpeg_std_error(&err);
@ -302,3 +319,61 @@ int picture::save_jpeg(const char *filename)
return 0;
}
int picture::save_png(const char* filename)
{
FILE* fp;
if ((fp = open_file(filename, ".png")) == NULL)
return -1;
// set up the png structures
png_structp png;
png_infop info;
if ((png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) {
fclose(fp);
return -1;
}
if ((info = png_create_info_struct(png)) == NULL) {
png_destroy_write_struct(&png, png_infopp_NULL);
fclose(fp);
return -1;
}
if (setjmp(png_jmpbuf(png))) {
png_destroy_write_struct(&png, &info);
fclose(fp);
return -1;
}
// use an stdio stream
png_init_io(png, fp);
// set png header
png_set_IHDR(png, info, width, height, 1 << depth,
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// TODO: write more useful image comments
png_text text;
text.key = strdup("Comment");
text.text = strdup("MFSK-16 image decoded by " PACKAGE_STRING);
text.compression = PNG_TEXT_COMPRESSION_NONE;
png_set_text(png, info, &text, 1);
// write header
png_write_info(png, info);
// write image
png_bytep row;
for (int i = 0; i < height; i++) {
row = &vidbuf[i * width * depth];
png_write_rows(png, &row, 1);
}
png_write_end(png, info);
// clean up
free(text.key);
free(text.text);
png_destroy_write_struct(&png, &info);
fclose(fp);
return 0;
}