Example #1
0
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);
}
Example #2
0
//--------------------------------------------------------------------------
// 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;
}
Example #3
0
//--------------------------------------------------------------------------
// 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;
}
Example #4
0
//--------------------------------------------------------------------------
// 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;
}
Example #5
0
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;
}
Example #6
0
//--------------------------------------------------------------------------
// 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;
}
Example #7
0
//--------------------------------------------------------------------------
// 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;
}
Example #8
0
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;

}