static void print_exif_info(struct jpeg_marker_struct const marker) { /*---------------------------------------------------------------------------- Dump as informational messages the contents of the Jpeg miscellaneous marker 'marker', assuming it is an Exif header. -----------------------------------------------------------------------------*/ ImageInfo_t imageInfo; const char * error; assert(marker.data_length >= 6); process_EXIF(marker.data+6, marker.data_length-6, &imageInfo, FALSE, &error); if (error) { pm_message("EXIF header is invalid. %s", error); strfree(error); } else ShowImageInfo(&imageInfo); }
//-------------------------------------------------------------------------- // Parse the marker buffer until SOS or EOI is seen; //-------------------------------------------------------------------------- int ReadJpegSectionsFromBuffer (unsigned char* buffer, unsigned int buffer_size, ReadMode_t ReadMode) { int a; unsigned int pos = 0; int HaveCom = FALSE; if (!buffer) { return FALSE; } if (buffer_size < 1) { return FALSE; } a = (int) buffer[pos++]; if (a != 0xff || buffer[pos++] != M_SOI){ return FALSE; } for(;;){ int itemlen; int marker = 0; int ll,lh, got; uchar * Data; CheckSectionsAllocated(); for (a=0;a<=16;a++){ marker = buffer[pos++]; if (marker != 0xff) break; if (a >= 16){ fprintf(stderr,"too many padding bytes\n"); return FALSE; } } Sections[SectionsRead].Type = marker; Sections[SectionsRead].Offset = pos; // Read the length of the section. lh = buffer[pos++]; ll = buffer[pos++]; itemlen = (lh << 8) | ll; if (itemlen < 2) { ALOGE("invalid marker"); return FALSE; } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen); if (Data == NULL) { ALOGE("Could not allocate memory"); return 0; } Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (uchar)lh; Data[1] = (uchar)ll; if (pos+itemlen-2 > buffer_size) { ALOGE("Premature end of file?"); return FALSE; } memcpy(Data+2, buffer+pos, itemlen-2); // Read the whole section. pos += itemlen-2; SectionsRead += 1; printf("reading marker %d", marker); switch(marker){ case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. if (ReadMode & READ_IMAGE){ int size; // Determine how much file is left. size = buffer_size - pos; if (size < 1) { ALOGE("could not read the rest of the image"); return FALSE; } Data = (uchar *)malloc(size); if (Data == NULL) { ALOGE("%d: could not allocate data for entire image size: %d", __LINE__, size); return FALSE; } memcpy(Data, buffer+pos, size); CheckSectionsAllocated(); Sections[SectionsRead].Data = Data; Sections[SectionsRead].Offset = pos; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; HaveAll = 1; } return TRUE; case M_EOI: // in case it's a tables-only JPEG stream ALOGE("No image in jpeg!\n"); return FALSE; case M_COM: // Comment section if (HaveCom || ((ReadMode & READ_METADATA) == 0)){ // Discard this section. free(Sections[--SectionsRead].Data); }else{ process_COM(Data, itemlen); HaveCom = TRUE; } break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. free(Sections[--SectionsRead].Data); break; case M_EXIF: // There can be different section using the same marker. if (ReadMode & READ_METADATA){ if (memcmp(Data+2, "Exif", 4) == 0){ process_EXIF(Data, itemlen); break; }else if (memcmp(Data+2, "http:", 5) == 0){ Sections[SectionsRead-1].Type = M_XMP; // Change tag for internal purposes. if (ShowTags){ ALOGD("Image cotains XMP section, %d bytes long\n", itemlen); if (ShowTags){ ShowXmp(Sections[SectionsRead-1]); } } break; } } // Oterwise, discard this section. free(Sections[--SectionsRead].Data); break; case M_IPTC: if (ReadMode & READ_METADATA){ if (ShowTags){ ALOGD("Image cotains IPTC section, %d bytes long\n", itemlen); } // Note: We just store the IPTC section. Its relatively straightforward // and we don't act on any part of it, so just display it at parse time. }else{ free(Sections[--SectionsRead].Data); } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); break; default: // Skip any other sections. if (ShowTags){ ALOGD("Jpeg section marker 0x%02x size %d\n",marker, itemlen); } break; } } return TRUE; }
//-------------------------------------------------------------------------- // Parse the marker stream until SOS or EOI is seen; //-------------------------------------------------------------------------- int ReadJpegSections (FILE * infile, ReadMode_t ReadMode) { int a; int HaveCom = FALSE; a = fgetc(infile); if (a != 0xff || fgetc(infile) != M_SOI){ return FALSE; } ImageInfo.JfifHeader.XDensity = ImageInfo.JfifHeader.YDensity = 300; ImageInfo.JfifHeader.ResolutionUnits = 1; for(;;){ int itemlen; int prev; int marker = 0; int ll,lh, got; uchar * Data; CheckSectionsAllocated(); prev = 0; for (a=0;;a++){ marker = fgetc(infile); if (marker != 0xff && prev == 0xff) break; prev = marker; } if (a > 10){ ErrNonfatal("Extraneous %d padding bytes before section %02X",a-1,marker); } Sections[SectionsRead].Type = marker; // Read the length of the section. lh = fgetc(infile); ll = fgetc(infile); itemlen = (lh << 8) | ll; if (itemlen < 2){ ErrFatal("invalid marker"); } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen); if (Data == NULL){ ErrFatal("Could not allocate memory"); } Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (uchar)lh; Data[1] = (uchar)ll; got = fread(Data+2, 1, itemlen-2, infile); // Read the whole section. if (got != itemlen-2){ ErrFatal("Premature end of file?"); } SectionsRead += 1; switch(marker){ case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. if (ReadMode & READ_IMAGE){ int cp, ep, size; // Determine how much file is left. cp = ftell(infile); fseek(infile, 0, SEEK_END); ep = ftell(infile); fseek(infile, cp, SEEK_SET); size = ep-cp; Data = (uchar *)malloc(size); if (Data == NULL){ ErrFatal("could not allocate data for entire image"); } got = fread(Data, 1, size, infile); if (got != size){ ErrFatal("could not read the rest of the image"); } CheckSectionsAllocated(); Sections[SectionsRead].Data = Data; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; HaveAll = 1; } return TRUE; case M_EOI: // in case it's a tables-only JPEG stream fprintf(stderr,"No image in jpeg!\n"); return FALSE; case M_COM: // Comment section if (HaveCom || ((ReadMode & READ_METADATA) == 0)){ // Discard this section. free(Sections[--SectionsRead].Data); }else{ process_COM(Data, itemlen); HaveCom = TRUE; } break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. if (memcmp(Data+2, "JFIF\0",5)){ fprintf(stderr,"Header missing JFIF marker\n"); } if (itemlen < 16){ fprintf(stderr,"Jfif header too short\n"); goto ignore; } ImageInfo.JfifHeader.Present = TRUE; ImageInfo.JfifHeader.ResolutionUnits = Data[9]; ImageInfo.JfifHeader.XDensity = (Data[10]<<8) | Data[11]; ImageInfo.JfifHeader.YDensity = (Data[12]<<8) | Data[13]; if (ShowTags){ printf("JFIF SOI marker: Units: %d ",ImageInfo.JfifHeader.ResolutionUnits); switch(ImageInfo.JfifHeader.ResolutionUnits){ case 0: printf("(aspect ratio)"); break; case 1: printf("(dots per inch)"); break; case 2: printf("(dots per cm)"); break; default: printf("(unknown)"); break; } printf(" X-density=%d Y-density=%d\n",ImageInfo.JfifHeader.XDensity, ImageInfo.JfifHeader.YDensity); if (Data[14] || Data[15]){ fprintf(stderr,"Ignoring jfif header thumbnail\n"); } } ignore: free(Sections[--SectionsRead].Data); break; case M_EXIF: // There can be different section using the same marker. if (ReadMode & READ_METADATA){ if (memcmp(Data+2, "Exif", 4) == 0){ process_EXIF(Data, itemlen); break; }else if (memcmp(Data+2, "http:", 5) == 0){ Sections[SectionsRead-1].Type = M_XMP; // Change tag for internal purposes. if (ShowTags){ printf("Image cotains XMP section, %d bytes long\n", itemlen); if (ShowTags){ ShowXmp(Sections[SectionsRead-1]); } } break; } } // Oterwise, discard this section. free(Sections[--SectionsRead].Data); break; case M_IPTC: if (ReadMode & READ_METADATA){ if (ShowTags){ printf("Image cotains IPTC section, %d bytes long\n", itemlen); } // Note: We just store the IPTC section. Its relatively straightforward // and we don't act on any part of it, so just display it at parse time. }else{ free(Sections[--SectionsRead].Data); } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); break; default: // Skip any other sections. if (ShowTags){ printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen); } break; } } return TRUE; }
//-------------------------------------------------------------------------- // Parse the marker stream until SOS or EOI is seen; //-------------------------------------------------------------------------- int ReadJpegSections (FILE * infile, ReadMode_t ReadMode) { int a; int HaveCom = FALSE; a = fgetc(infile); if (a != 0xff || fgetc(infile) != M_SOI){ return FALSE; } for(;;){ int itemlen; int marker = 0; int ll,lh, got; uchar * Data; if (SectionsRead >= MAX_SECTIONS){ ErrFatal("Too many sections in jpg file"); } for (a=0;a<7;a++){ marker = fgetc(infile); if (marker != 0xff) break; if (a >= 6){ printf("too many padding bytes\n"); return FALSE; } } if (marker == 0xff){ // 0xff is legal padding, but if we get that many, something's wrong. ErrFatal("too many padding bytes!"); } Sections[SectionsRead].Type = marker; // Read the length of the section. lh = fgetc(infile); ll = fgetc(infile); itemlen = (lh << 8) | ll; if (itemlen < 2){ ErrFatal("invalid marker"); } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen); if (Data == NULL){ ErrFatal("Could not allocate memory"); } Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (uchar)lh; Data[1] = (uchar)ll; got = fread(Data+2, 1, itemlen-2, infile); // Read the whole section. if (got != itemlen-2){ ErrFatal("Premature end of file?"); } SectionsRead += 1; switch(marker){ case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. if (ReadMode & READ_IMAGE){ int cp, ep, size; // Determine how much file is left. cp = ftell(infile); fseek(infile, 0, SEEK_END); ep = ftell(infile); fseek(infile, cp, SEEK_SET); size = ep-cp; Data = (uchar *)malloc(size); if (Data == NULL){ ErrFatal("could not allocate data for entire image"); } got = fread(Data, 1, size, infile); if (got != size){ ErrFatal("could not read the rest of the image"); } Sections[SectionsRead].Data = Data; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; HaveAll = 1; } return TRUE; case M_EOI: // in case it's a tables-only JPEG stream printf("No image in jpeg!\n"); return FALSE; case M_COM: // Comment section if (HaveCom || ((ReadMode & READ_EXIF) == 0)){ // Discard this section. free(Sections[--SectionsRead].Data); }else{ process_COM(Data, itemlen); HaveCom = TRUE; } break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. free(Sections[--SectionsRead].Data); break; case M_EXIF: // Seen files from some 'U-lead' software with Vivitar scanner // that uses marker 31 for non exif stuff. Thus make sure // it says 'Exif' in the section before treating it as exif. if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){ process_EXIF(Data, itemlen); }else{ // Discard this section. free(Sections[--SectionsRead].Data); } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); break; default: // Skip any other sections. if (ShowTags){ printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen); } break; } } return TRUE; }
bool Cexif::DecodeExif(const char *filename, int Thumb) { FileWrapper wrapper(filename, "r"); FILE * hFile = wrapper.handle; if(!hFile) return false; m_exifinfo = new EXIFINFO; memset(m_exifinfo,0,sizeof(EXIFINFO)); freeinfo = true; m_exifinfo->Thumnailstate = Thumb; m_szLastError[0]='\0'; ExifImageWidth = MotorolaOrder = SectionsRead=0; memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t)); int HaveCom = 0; int a = fgetc(hFile); strcpy(m_szLastError,"EXIF-Data not found"); if (a != 0xff || fgetc(hFile) != M_SOI) return false; for(;;) { int marker = 0; int ll,lh, got, itemlen; unsigned char * Data; if (SectionsRead >= MAX_SECTIONS) { strcpy(m_szLastError,"Too many sections in jpg file"); return false; } for (a=0;a<7;a++) { marker = fgetc(hFile); if (marker != 0xff) break; if (a >= 6) { strcpy(m_szLastError,"too many padding unsigned chars\n"); return false; } } if (marker == 0xff) { strcpy(m_szLastError,"too many padding unsigned chars!"); return false; } Sections[SectionsRead].Type = marker; lh = fgetc(hFile); ll = fgetc(hFile); itemlen = (lh << 8) | ll; if (itemlen < 2) { strcpy(m_szLastError,"invalid marker"); return false; } Sections[SectionsRead].Size = itemlen; Data = (unsigned char *)malloc(itemlen); if (Data == NULL) { strcpy(m_szLastError,"Could not allocate memory"); return false; } Sections[SectionsRead].Data = Data; Data[0] = (unsigned char)lh; Data[1] = (unsigned char)ll; got = fread(Data+2, 1, itemlen-2,hFile); if (got != itemlen-2) { strcpy(m_szLastError,"Premature end of file?"); return false; } SectionsRead += 1; switch(marker) { case M_SOS: return true; case M_EOI: printf("No image in jpeg!\n"); return false; case M_COM: if (HaveCom) { free(Sections[--SectionsRead].Data); Sections[SectionsRead].Data=0; } else { process_COM(Data, itemlen); HaveCom = 1; } break; case M_JFIF: free(Sections[--SectionsRead].Data); Sections[SectionsRead].Data=0; break; case M_EXIF: if (memcmp(Data+2, "Exif", 4) == 0) { m_exifinfo->IsExif = process_EXIF((unsigned char *)Data+2, itemlen); } else { free(Sections[--SectionsRead].Data); Sections[SectionsRead].Data=0; } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); break; default: break; } } return true; }
//-------------------------------------------------------------------------- // Parse the marker stream until SOS or EOI is seen; //-------------------------------------------------------------------------- int ExifData::ReadJpegSections (QFile & infile, ReadMode_t ReadMode) { int a; a = infile.getch(); if (a != 0xff || infile.getch() != M_SOI) { SectionsRead = 0; return false; } for(SectionsRead = 0; SectionsRead < MAX_SECTIONS-1; ) { int marker = 0; int got; unsigned int ll,lh; unsigned int itemlen; uchar * Data; for (a=0; a<7; a++) { marker = infile.getch(); if (marker != 0xff) break; if (a >= 6) { kdDebug(7034) << "too many padding bytes\n"; return false; } } if (marker == 0xff) { // 0xff is legal padding, but if we get that many, something's wrong. throw FatalError("too many padding bytes!"); } Sections[SectionsRead].Type = marker; // Read the length of the section. lh = (uchar) infile.getch(); ll = (uchar) infile.getch(); itemlen = (lh << 8) | ll; if (itemlen < 2) { throw FatalError("invalid marker"); } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end. Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (uchar)lh; Data[1] = (uchar)ll; got = infile.readBlock((char*)Data+2, itemlen-2); // Read the whole section. if (( unsigned ) got != itemlen-2) { throw FatalError("reading from file"); } SectionsRead++; switch(marker) { case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. if (ReadMode & READ_IMAGE) { unsigned long size; size = kMax( 0ul, infile.size()-infile.at() ); Data = (uchar *)malloc(size); if (Data == NULL) { throw FatalError("could not allocate data for entire image"); } got = infile.readBlock((char*)Data, size); if (( unsigned ) got != size) { throw FatalError("could not read the rest of the image"); } Sections[SectionsRead].Data = Data; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; //HaveAll = 1; } return true; case M_EOI: // in case it's a tables-only JPEG stream kdDebug(7034) << "No image in jpeg!\n"; return false; case M_COM: // Comment section // pieczy 2002-02-12 // now the User comment goes to UserComment // so we can store a Comment section also in READ_EXIF mode process_COM(Data, itemlen); break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. free(Sections[--SectionsRead].Data); break; case M_EXIF: // Seen files from some 'U-lead' software with Vivitar scanner // that uses marker 31 for non exif stuff. Thus make sure // it says 'Exif' in the section before treating it as exif. if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0) { process_EXIF((uchar *)Data, itemlen); // FIXME: This call // requires Data to be array of at least 8 bytes. Code // above only checks for itemlen < 2. } else { // Discard this section. free(Sections[--SectionsRead].Data); } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); //FIXME: This call requires Data to // be array of at least 8 bytes. Code above only checks for // itemlen < 2. break; default: break; } } return true; }
//-------------------------------------------------------------------------- // Parse the marker stream until SOS or EOI is seen; //-------------------------------------------------------------------------- int ExifData::ReadJpegSections ( QFile & infile, ReadMode_t ReadMode ) { int a; int SectionsRead; a = getch ( infile ); if ( a != 0xff || getch ( infile ) != M_SOI ) { SectionsRead = 0; return false; } for ( SectionsRead = 0; SectionsRead < MAX_SECTIONS-1; SectionsRead++ ) { int marker = 0; int got; unsigned int ll,lh; unsigned int itemlen; uchar * Data; for ( a=0;a<7;a++ ) { marker = getch ( infile ); if ( marker != 0xff ) break; if ( a >= 6 ) return false; } if ( marker == 0xff ) return false; // Read the length of the section. lh = ( uchar ) getch ( infile ); ll = ( uchar ) getch ( infile ); itemlen = ( lh << 8 ) | ll; if ( itemlen < 2 ) return false; Data = ( uchar * ) malloc ( itemlen+1 ); // Add 1 to allow sticking a 0 at the end. // Store first two pre-read bytes. Data[0] = ( uchar ) lh; Data[1] = ( uchar ) ll; got = infile.read ( ( char* ) Data+2, itemlen-2 ); // Read the whole section. if ( ( unsigned ) got != itemlen-2 ) { free(Data); return false; } switch ( marker ) { case M_SOS: // stop before hitting compressed data free(Data); return true; case M_EOI: // in case it's a tables-only JPEG stream free(Data); return false; case M_COM: // Comment section // pieczy 2002-02-12 // now the User comment goes to UserComment // so we can store a Comment section also in READ_EXIF mode process_COM ( Data, itemlen ); break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. break; case M_EXIF: // Seen files from some 'U-lead' software with Vivitar scanner // that uses marker 31 for non exif stuff. Thus make sure // it says 'Exif' in the section before treating it as exif. if ( ( ReadMode & READ_EXIF ) && memcmp ( Data+2, "Exif", 4 ) == 0 ) { process_EXIF ( ( uchar * ) Data, itemlen ); // FIXME: This call // requires Data to be array of at least 8 bytes. Code // above only checks for itemlen < 2. exifDataValid = true; } // else // { // // Discard this section. // free ( Sections[--SectionsRead].Data ); // return false; // } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn ( Data, marker ); //FIXME: This call requires Data to // be array of at least 8 bytes. Code above only checks for // itemlen < 2. break; default: break; } free(Data); } return true; }
static int ReadJpegStreamSections (ReadMode_t ReadMode, CALLBACK_js_getc js_getc, CALLBACK_js_read js_read) { int a; int HaveCom = FALSE; a = js_getc(); if (a != 0xff || js_getc() != M_SOI){ ALOGE("a = %d",a); return FALSE; } for(;;){ int itemlen; int prev; int marker = 0; int ll,lh, got; uchar * Data; CheckSectionsAllocated(); prev = 0; for (a=0;;a++){ marker = js_getc(); if (marker != 0xff && prev == 0xff) break; prev = marker; if(marker == EOF){ ALOGE("hit file end!!\n"); return FALSE; } } if (a >= 4096){ ALOGD("get marker %x, prv %x, after (%d), L:%d!!\n", marker, prev, a, __LINE__); } Sections[SectionsRead].Type = marker; // Read the length of the section. lh = js_getc(); ll = js_getc(); itemlen = (lh << 8) | ll; if (itemlen < 2){ // ErrFatal("invalid marker"); ALOGE("invalid marker"); return FALSE; } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen); if (Data == NULL){ // ErrFatal("Could not allocate memory"); ALOGE("Could not allocate memory"); return 0; } Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (uchar)lh; Data[1] = (uchar)ll; got = js_read(Data+2, 1, itemlen-2); // Read the whole section. if (got != itemlen-2){ // ErrFatal("Premature end of file?"); ALOGE("Premature end of file?"); return FALSE; } SectionsRead += 1; printf("reading marker %d", marker); switch(marker){ case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. /* if (ReadMode & READ_IMAGE){ int cp, ep, size; // Determine how much file is left. cp = ftell(infile); fseek(infile, 0, SEEK_END); ep = ftell(infile); fseek(infile, cp, SEEK_SET); size = ep-cp; Data = (uchar *)malloc(size); if (Data == NULL){ // ErrFatal("could not allocate data for entire image"); ALOGE("could not allocate data for entire image"); return FALSE; } got = fread(Data, 1, size, infile); if (got != size){ // ErrFatal("could not read the rest of the image"); ALOGE("could not read the rest of the image"); return FALSE; } CheckSectionsAllocated(); Sections[SectionsRead].Data = Data; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; HaveAll = 1; }*/ return TRUE; case M_EOI: // in case it's a tables-only JPEG stream ALOGE("No image in jpeg!\n"); fprintf(stderr,"No image in jpeg!\n"); return FALSE; case M_COM: // Comment section if (HaveCom || ((ReadMode & READ_METADATA) == 0)){ // Discard this section. free(Sections[--SectionsRead].Data); }else{ process_COM(Data, itemlen); HaveCom = TRUE; } break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. free(Sections[--SectionsRead].Data); break; case M_EXIF: // There can be different section using the same marker. if (ReadMode & READ_METADATA){ if (memcmp(Data+2, "Exif", 4) == 0){ process_EXIF(Data, itemlen); break; }else if (memcmp(Data+2, "http:", 5) == 0){ Sections[SectionsRead-1].Type = M_XMP; // Change tag for internal purposes. if (ShowTags){ printf("Image cotains XMP section, %d bytes long\n", itemlen); if (ShowTags){ ShowXmp(Sections[SectionsRead-1]); } } break; } } // Oterwise, discard this section. free(Sections[--SectionsRead].Data); break; case M_IPTC: if (ReadMode & READ_METADATA){ if (ShowTags){ printf("Image cotains IPTC section, %d bytes long\n", itemlen); } // Note: We just store the IPTC section. Its relatively straightforward // and we don't act on any part of it, so just display it at parse time. }else{ free(Sections[--SectionsRead].Data); } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); break; default: // Skip any other sections. if (ShowTags){ printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen); } break; } } return TRUE; }