You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
9.9 KiB
484 lines
9.9 KiB
/*
|
|
* $Id: pilot-read-screenshot.c,v 1.16 2006/11/02 14:54:31 desrod Exp $
|
|
*
|
|
* pilot-read-screenshot.c
|
|
*
|
|
* Copyright (c) 2003-2004, Angus Ainslie
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#ifdef HAVE_STDINT_H
|
|
#include <stdint.h>
|
|
#endif
|
|
|
|
#include "pi-source.h"
|
|
#include "pi-file.h"
|
|
#include "pi-header.h"
|
|
#include "pi-userland.h"
|
|
|
|
#ifdef HAVE_PNG
|
|
# include "png.h"
|
|
# if (PNG_LIBPNG_VER < 10201)
|
|
# define png_voidp_NULL (png_voidp)NULL
|
|
# define png_error_ptr_NULL (png_error_ptr)NULL
|
|
# endif
|
|
#endif
|
|
|
|
#define pi_mktag(c1,c2,c3,c4) (((c1)<<24)|((c2)<<16)|((c3)<<8)|(c4))
|
|
|
|
#define OUT_PPM 1
|
|
#define OUT_PNG 2
|
|
|
|
struct ss_state {
|
|
int w,
|
|
h,
|
|
depth;
|
|
unsigned char *pix_map;
|
|
};
|
|
|
|
|
|
|
|
#define max(a,b) (( a > b ) ? a : b )
|
|
#define min(a,b) (( a < b ) ? a : b )
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: write_png
|
|
*
|
|
* Summary:
|
|
*
|
|
* Parameters: None
|
|
*
|
|
* Returns: Nothing
|
|
*
|
|
***********************************************************************/
|
|
#ifdef HAVE_PNG
|
|
void write_png ( char *fname, struct ss_state *state )
|
|
{
|
|
unsigned char *gray_buf;
|
|
int i, j;
|
|
png_structp png_ptr;
|
|
png_infop info_ptr;
|
|
FILE *f;
|
|
|
|
if( state->depth < 8 )
|
|
gray_buf = malloc( state->w );
|
|
|
|
png_ptr = png_create_write_struct
|
|
(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
|
|
png_error_ptr_NULL, png_error_ptr_NULL);
|
|
|
|
if (!png_ptr)
|
|
return;
|
|
|
|
info_ptr = png_create_info_struct (png_ptr);
|
|
if (!info_ptr)
|
|
{
|
|
png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
|
|
return;
|
|
}
|
|
|
|
if (setjmp (png_jmpbuf (png_ptr)))
|
|
{
|
|
png_destroy_write_struct (&png_ptr, &info_ptr);
|
|
fclose (f);
|
|
return;
|
|
}
|
|
|
|
f = fopen (fname, "wb");
|
|
|
|
png_init_io (png_ptr, f);
|
|
|
|
if( state->depth < 8 )
|
|
png_set_IHDR (png_ptr, info_ptr, state->w, state->h,
|
|
8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
|
|
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
|
else
|
|
png_set_IHDR (png_ptr, info_ptr, state->w, state->h,
|
|
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
|
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
|
|
|
|
|
png_write_info (png_ptr, info_ptr);
|
|
|
|
if( state->depth < 8 )
|
|
{
|
|
for (i = 0; i < state->h; i++)
|
|
{
|
|
for( j=0; j<state->w; j++ )
|
|
gray_buf[j] = state->pix_map[i*3*state->w+j*3];
|
|
|
|
png_write_row (png_ptr, gray_buf );
|
|
png_write_flush (png_ptr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < state->h; i++)
|
|
{
|
|
png_write_row (png_ptr, &state->pix_map[i*3*state->w] );
|
|
png_write_flush (png_ptr);
|
|
}
|
|
}
|
|
|
|
png_write_end (png_ptr, info_ptr);
|
|
png_destroy_write_struct (&png_ptr, &info_ptr);
|
|
|
|
fclose( f );
|
|
|
|
if( state->depth < 8 )
|
|
free( gray_buf );
|
|
}
|
|
#endif
|
|
|
|
void write_ppm ( char *fname, struct ss_state *state)
|
|
{
|
|
int i;
|
|
FILE *f;
|
|
|
|
f = fopen (fname, "wb");
|
|
|
|
fprintf (f, "P6\n# ");
|
|
|
|
fprintf (f, "%s\n", fname );
|
|
|
|
fprintf (f, "%d %d\n", state->w, state->h );
|
|
|
|
fprintf (f, "255\n" );
|
|
|
|
for( i = 0; i < 3*state->h*state->w; i += 3 )
|
|
fwrite( &state->pix_map[i], 3, 1, f);
|
|
|
|
fclose( f );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: WritePictures
|
|
*
|
|
* Summary: FIXME
|
|
*
|
|
* Parameters:
|
|
*
|
|
* Returns:
|
|
*
|
|
***********************************************************************/
|
|
void WritePictures (int sd, int db, int type )
|
|
{
|
|
char fname[FILENAME_MAX];
|
|
char extension[8];
|
|
int i, len, idx = 0, recs, imgNum = 0;
|
|
// unsigned char inBuf[61440], *pixelBuf;
|
|
pi_buffer_t *inBuf, *pixelBuf;
|
|
unsigned long clut[256], magic;
|
|
int attr, category, val, mask, j, k;
|
|
struct ss_state state;
|
|
|
|
if( type == OUT_PPM )
|
|
sprintf (extension, ".ppm");
|
|
else if( type == OUT_PNG )
|
|
sprintf (extension, ".png");
|
|
else
|
|
return;
|
|
|
|
inBuf = pi_buffer_new (61440);
|
|
|
|
if (sd)
|
|
while( 1 )
|
|
{
|
|
len =
|
|
dlp_ReadRecordByIndex (sd, db, idx, inBuf, 0, &attr, &category);
|
|
|
|
if( len <= 0 )
|
|
{
|
|
/* EOF */
|
|
break;
|
|
}
|
|
|
|
idx++;
|
|
state.w = ( inBuf->data[4] << 8 )+ inBuf->data[5];
|
|
state.h = ( inBuf->data[6] << 8 ) + inBuf->data[7];
|
|
recs = inBuf->data[9];
|
|
state.depth = inBuf->data[8];
|
|
magic = ((unsigned long *)inBuf->data)[0];
|
|
|
|
if( magic != 0xBECEDEFE && magic != 0xDEDEFEFE )
|
|
{
|
|
/* no magic must version 1 db */
|
|
// fprintf( stderr, "No Magic !\n" );
|
|
|
|
state.w = 160;
|
|
state.h = 160;
|
|
recs = 1;
|
|
|
|
switch( len )
|
|
{
|
|
case 3200:
|
|
state.depth = 1;
|
|
mask = 1;
|
|
break;
|
|
|
|
case 6400:
|
|
state.depth = 2;
|
|
mask = 3;
|
|
break;
|
|
|
|
case 12800:
|
|
state.depth = 4;
|
|
mask = 0x0f;
|
|
break;
|
|
|
|
case 26624:
|
|
state.depth = 8;
|
|
break;
|
|
|
|
case 51200:
|
|
state.depth = 16;
|
|
break;
|
|
|
|
default:
|
|
/* unknown record */
|
|
/* get next */
|
|
fprintf( stderr, "Unknown record" );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
pixelBuf
|
|
= pi_buffer_new (state.h * state.w * state.depth / 8 + 10 + 1024);
|
|
|
|
// pixelBuf = malloc( state.h * state.w * state.depth / 8 + 10 + 1024 );
|
|
state.pix_map = malloc( state.h * state.w * 3 );
|
|
|
|
if( !pixelBuf || !state.pix_map )
|
|
{
|
|
fprintf( stderr, "Memory Allocation failed\n" );
|
|
return;
|
|
}
|
|
|
|
if( magic == 0xBECEDEFE || magic == 0xDEDEFEFE )
|
|
memcpy( pixelBuf->data, &inBuf->data[10], len - 10 );
|
|
else
|
|
memcpy( pixelBuf->data, inBuf->data, len );
|
|
|
|
for( i=1; i< recs; i++ )
|
|
{
|
|
len =
|
|
dlp_ReadRecordByIndex (sd, db, idx, inBuf, 0, &attr, &category);
|
|
memcpy( &pixelBuf->data[i*61440-10], inBuf->data, len );
|
|
idx++;
|
|
}
|
|
|
|
sprintf (fname, "ScreenShot%d", ++imgNum );
|
|
|
|
if (plu_protect_files (fname, extension, sizeof(fname)) < 1) {
|
|
goto cleanup;
|
|
}
|
|
|
|
printf ("Generating %s...\n", fname);
|
|
fprintf( stderr, "height: %d width: %d records: %d bit depth: %d\n"
|
|
, state.h, state.w, recs, state.depth );
|
|
|
|
if( state.depth == 8 )
|
|
memcpy( clut, &inBuf->data[len-1024], 1024 );
|
|
|
|
switch( state.depth )
|
|
{
|
|
case 1:
|
|
case 2:
|
|
case 4:
|
|
for( i = 0; i < state.h*state.w/(8/state.depth); i++)
|
|
{
|
|
for( j=(8/state.depth-1), k=0; j >= 0; j--, k++ )
|
|
{
|
|
/* get right bits */
|
|
val = ((pixelBuf->data[i] >> (j * state.depth)) & mask);
|
|
/* invert */
|
|
val = mask - val;
|
|
/* stretch */
|
|
val *= (255/mask);
|
|
|
|
state.pix_map[3*(i*(8/state.depth)+k)] = val;
|
|
state.pix_map[3*(i*(8/state.depth)+k)+1] = val;
|
|
state.pix_map[3*(i*(8/state.depth)+k)+2] = val;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
for( i = 0; i < state.h*state.w; i++)
|
|
{
|
|
state.pix_map[3*i] =
|
|
*(1 + (char *)&clut[pixelBuf->data[i]]);
|
|
state.pix_map[3*i+1] =
|
|
*(2 + (char *)&clut[pixelBuf->data[i]]);
|
|
state.pix_map[3*i+2] =
|
|
*(3 + (char *)&clut[pixelBuf->data[i]]);
|
|
}
|
|
break;
|
|
|
|
case 16:
|
|
for( i = 0; i < state.h*state.w; i++)
|
|
{
|
|
state.pix_map[i*3] = pixelBuf->data[i*2] & 0xF8;
|
|
state.pix_map[i*3+1] = ((pixelBuf->data[i*2] & 0x07 ) << 5)
|
|
+ (( pixelBuf->data[i*2+1] & 0xE0 ) >> 3 );
|
|
state.pix_map[i*3+2] = ( pixelBuf->data[i*2+1] & 0x1F ) << 3;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fprintf( stderr, "I'm out of my depth :)\n" );
|
|
break;
|
|
}
|
|
|
|
if( type == OUT_PPM )
|
|
write_ppm( fname, &state );
|
|
#ifdef HAVE_PNG
|
|
else
|
|
write_png( fname, &state );
|
|
#endif
|
|
|
|
cleanup:
|
|
pi_buffer_free (pixelBuf);
|
|
// free( pixelBuf );
|
|
free( state.pix_map );
|
|
|
|
// fclose (f);
|
|
}
|
|
else
|
|
return;
|
|
|
|
pi_buffer_free (inBuf);
|
|
}
|
|
|
|
int main (int argc, const char *argv[])
|
|
{
|
|
int c, /* switch */
|
|
db,
|
|
sd = -1,
|
|
dbcount = 0,
|
|
type = OUT_PPM;
|
|
|
|
const char
|
|
*pformat;
|
|
|
|
struct PilotUser User;
|
|
|
|
poptContext po;
|
|
|
|
struct poptOption options[] = {
|
|
USERLAND_RESERVED_OPTIONS
|
|
{"format", 'f', POPT_ARG_STRING, &pformat, 0, "Specify picture output type (ppm or png)"},
|
|
POPT_TABLEEND
|
|
};
|
|
|
|
po = poptGetContext("pilot-read-screenshot", argc, argv, options, 0);
|
|
poptSetOtherOptionHelp(po,"\n\n");
|
|
|
|
if (argc<2) {
|
|
poptPrintUsage(po,stderr,0);
|
|
return 1;
|
|
}
|
|
|
|
while ((c = poptGetNextOpt(po)) >= 0) {
|
|
fprintf(stderr," ERROR: Unhandled option %d.\n",c);
|
|
return 1;
|
|
}
|
|
if (c<-1) {
|
|
plu_badoption(po,c);
|
|
}
|
|
|
|
if (!strncmp ("png", pformat, 3))
|
|
{
|
|
#ifdef HAVE_PNG
|
|
type = OUT_PNG;
|
|
#else
|
|
fprintf (stderr, " ERROR: pilot-read-screenshot was built without png support.\n");
|
|
#endif
|
|
}
|
|
else if (!strncmp ("ppm", pformat, 3))
|
|
{
|
|
type = OUT_PPM;
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, " ERROR: Unknown output type, defaulting to ppm\n");
|
|
type = OUT_PPM;
|
|
}
|
|
|
|
sd = plu_connect ();
|
|
|
|
if (sd < 0)
|
|
goto error;
|
|
|
|
if (dlp_ReadUserInfo (sd, &User) < 0)
|
|
goto error_close;
|
|
|
|
if (dlp_OpenDB (sd, 0, dlpOpenRead, "ScreenShotDB", &db) < 0)
|
|
{
|
|
fprintf (stderr," ERROR: Unable to open Screen Shot database on Palm.\n");
|
|
dlp_AddSyncLogEntry (sd, "Unable to open Screen Shot database.\n");
|
|
goto error_close;
|
|
}
|
|
|
|
WritePictures (sd, db, type );
|
|
|
|
if (sd)
|
|
{
|
|
/* Close the database */
|
|
dlp_CloseDB (sd, db);
|
|
}
|
|
|
|
if (sd)
|
|
{
|
|
dlp_AddSyncLogEntry (sd,
|
|
"Successfully read screenshots from Palm.\n"
|
|
"Thank you for using pilot-link.");
|
|
dlp_EndOfSync (sd, 0);
|
|
pi_close (sd);
|
|
}
|
|
|
|
if (!plu_quiet) {
|
|
printf ("\nList complete. %d files found.\n", dbcount);
|
|
}
|
|
|
|
return 0;
|
|
|
|
error_close:
|
|
pi_close (sd);
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
|
|
/* ex: set tabstop=4 expandtab: */
|
|
/* Local Variables: */
|
|
/* indent-tabs-mode: t */
|
|
/* c-basic-offset: 8 */
|
|
/* End: */
|