Skip to content

Commit

Permalink
add jpeg_rescue.c and jpeg_truncate.c and Makefile
Browse files Browse the repository at this point in the history
  • Loading branch information
KOMURA Takaaki committed Mar 9, 2010
1 parent abb2cef commit 439f48a
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 0 deletions.
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ALLTARGETS=jpeg_rescue jpeg_truncate

all: $(ALLTARGETS)

jpeg_rescue: jpeg_rescue.o
$(CC) -o $@ $>

jpeg_truncate: jpeg_truncate.o
$(CC) -o $@ $>


clean:
rm *.o $(ALLTARGETS)

26 changes: 26 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
These tools rescue JPEG files from broken SD/USB memory cards

* jpeg_rescue

'jpeg_rescue' rescues JPEG files from broken SD/USB memory cards.
This tool expects JPEG files are wrote sequentially in memory device.

This tool searches JPEG Start Of Image (0xff 0xd8) from top of
each cluster (4KB block) and pick up data (to just before next SOI).

usage:

1. insert broekn SD/USB memory into slot of your PC.
2. when your memory device appears in /dev/da0
# dd if=/dev/da0 of=hogehoge bs=1m
# jpeg_rescue hogehoge
or
# jpeg_rescue /dev/da0


* jpeg_truncate
'jpeg_truncate' truncates unnecessary end of data
This tool trancate garbage after JPEG End Of Image (0xff 0xd9)

usage:
% jpeg_truncate *.jpg
86 changes: 86 additions & 0 deletions jpeg_rescue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MAXBUF 4096
#define BLOCKSIZE 4096
#define MAXJPEGSIZE (1024*1024*10)

int is_jpeg_startofimage(unsigned char *buf)
{
if(buf[0] == 0xff &&
buf[1] == 0xd8){
return 1;
} else {
return 0;
}
}


int main(int argc, char** argv)
{
FILE *ifp;
char *ifname;

FILE *ofp = NULL;
char ofname[8+1+3+1];
size_t oflen;

unsigned char buf[MAXBUF];
int cl = 0;

int i = 0;

if(argc != 2){
fprintf(stderr, "please specify filename\n");
return -1;
}
ifname = argv[1];

if((ifp=fopen(ifname, "r"))==NULL){
fprintf(stderr, "can not open file: '%s'\n", ifname);
return -1;
}

while(!feof(ifp)){
int err;

cl++;
if((err=fread(buf, BLOCKSIZE, 1, ifp))!=1){
fprintf(stderr, "fread: error=%d, skip cl=%ld\n", err, cl);
continue;
}
if(oflen > MAXJPEGSIZE){
fprintf(stderr, ", cut [%ld]\n", oflen);
fclose(ofp);
ofp = NULL;
oflen = 0;
}
if(is_jpeg_startofimage(buf)){
if(ofp!=NULL){
fprintf(stderr, ", done [%ld]\n", oflen);
fclose(ofp);
ofp = NULL;
oflen = 0;
}
snprintf(ofname, sizeof(ofname), "%08ld.jpg", i++);
fprintf(stderr, "writing: %s", ofname);
oflen = 0;
if((ofp = fopen(ofname, "w"))==NULL){
fprintf(stderr, ": faile\n");
continue;
}

}
if(ofp == NULL){
fprintf(stderr, "skip: cl=%d because ofp=NULL\n", cl);
continue;
}
if((err=fwrite(buf, BLOCKSIZE, 1, ofp))!=1){
fprintf(stderr, "fwrite: error=%d, skip cl=%ld\n", err, cl);
continue;
}
oflen += BLOCKSIZE;
}
return 0;
}
91 changes: 91 additions & 0 deletions jpeg_truncate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#define BUFMAX 4096

long where_jpeg_endofimage(unsigned char *buf, long size)
{
long p;
int stage = 0;

for(p = size-1; p>0l; p--){
switch(stage){
case 0:
if(buf[p] == 0xd9){
stage++;
}
break;
case 1:
if(buf[p] == 0xff){
stage++;
} else {
stage--;
}
break;
case 2:
return p + 3;
break;
default:
fprintf(stderr, "unsupported stage: %d\n", stage);
break;
}
}
return 0;
}


size_t getfilesize(int fd)
{
struct stat sb;

assert(fstat(fd, &sb) >= 0);
return sb.st_size;
}


int jpeg_trancate(char *ifname)
{
int ifd;
void *ifmap;
long ifsize;
long offset;

ifd = open(ifname, O_RDWR);
assert(ifd != -1);
ifsize = getfilesize(ifd); /* get file size */

fprintf(stderr, "open %s [%ld]", ifname, ifsize);

ifmap = mmap(NULL, ifsize, PROT_READ, MAP_PRIVATE, ifd, 0);
assert(ifmap != MAP_FAILED);

offset = where_jpeg_endofimage(ifmap, ifsize);

fprintf(stderr, " -> [%ld = 0x%x] (%ld)\n", offset, offset, offset-ifsize);

ftruncate(ifd, offset);
fprintf(stderr, "truncated\n");
return offset;
}


int main(int argc, char **argv)
{
int i;

if(argc < 2){
fprintf(stderr, "please specify file name\n");
return -1;
}

for(i = 1; i < argc; i++){
jpeg_trancate(argv[i]);
}
return 0;
}

0 comments on commit 439f48a

Please sign in to comment.