studio android rotation jpeg

studio - android camera2



Girar jpeg usando ExifInterface no funciona a veces (0)

Hola, así es como giro la imagen JPEG:

private static boolean rotateJpg(String filepath, int degrees) { // get current rotation degree int iCurRotation = getExifOrientation(filepath); // create exif ExifInterface exif = null; try { exif = new ExifInterface(filepath); } catch (IOException ex) { return false; } // Calculate new rotation degree int iNewRotation = iCurRotation + degrees; try { iNewRotation %= 360; if (iNewRotation < 0) iNewRotation += 360; int orientation = ExifInterface.ORIENTATION_NORMAL; switch (iNewRotation) { case 0: orientation = ExifInterface.ORIENTATION_NORMAL; break; case 90: orientation = ExifInterface.ORIENTATION_ROTATE_90; break; case 180: orientation = ExifInterface.ORIENTATION_ROTATE_180; break; case 270: orientation = ExifInterface.ORIENTATION_ROTATE_270; break; } // save new rotation degree if (exif != null) { exif.setAttribute(ExifInterface.TAG_ORIENTATION, Integer.toString(orientation)); exif.saveAttributes(); } } catch (Exception ex) { return false; } return true; }

El código anterior funciona. Sin embargo, a veces tengo:

06-29 18:28:35.780: E/JHEAD(28163): Can''t write back - didn''t read all

Lo busqué y descubrí que es el / jhead / jpgfile.c externo quien está arrojando el error:

// Command line parsing code static const char * progname; // program name for error messages //-------------------------------------------------------------------------- // Parse the marker stream until SOS or EOI is seen; //-------------------------------------------------------------------------- static 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(;SectionsRead < MAX_SECTIONS-1;){ int itemlen; int marker = 0; int ll,lh, got; uchar * Data; 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. ErrExit("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){ ErrExit("invalid marker"); } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end. if (Data == NULL){ ErrExit("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){ ErrExit("reading from file"); } SectionsRead += 1; //printf("Marker ''%x'' size %d/n",marker, itemlen); 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){ ErrExit("could not allocate data for entire image"); } got = fread(Data, 1, size, infile); if (got != size){ ErrExit("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. free(Sections[--SectionsRead].Data); break; case M_EXIF: if (SectionsRead <= 2){ // Seen files from some ''U-lead'' software with Vivitar scanner // that uses marker 31 later in the file (no clue what for!) process_EXIF((char *)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 unknown sections. if (ShowTags){ printf("Unknown Jpeg section marker 0x%02x size %d/n",marker, itemlen); } break; } } return TRUE; } //-------------------------------------------------------------------------- // Discard read data. //-------------------------------------------------------------------------- void DiscardData(void) { int a; for (a=0;a<SectionsRead;a++){ free(Sections[a].Data); } memset(&ImageInfo, 0, sizeof(ImageInfo)); SectionsRead = 0; HaveAll = 0; } //-------------------------------------------------------------------------- // Read image data. //-------------------------------------------------------------------------- int ReadJpegFile(const char * FileName, ReadMode_t ReadMode) { FILE * infile; int ret; infile = fopen(FileName, "rb"); // Unix ignores ''b'', windows needs it. if (infile == NULL) { fprintf(stderr, "%s: can''t open ''%s''/n", progname, FileName); return FALSE; } // Scan the JPEG headers. ret = ReadJpegSections(infile, ReadMode); if (!ret){ printf("Not JPEG: %s/n",FileName); } fclose(infile); if (ret == FALSE){ DiscardData(); } return ret; } //-------------------------------------------------------------------------- // Write image data back to disk. //-------------------------------------------------------------------------- void WriteJpegFile(const char * FileName) { FILE * outfile; int a; if (!HaveAll){ ErrExit("Can''t write back - didn''t read all"); } outfile = fopen(FileName,"wb"); if (outfile == NULL){ ErrExit("Could not open file for write"); } // Initial static jpeg marker. fputc(0xff,outfile); fputc(0xd8,outfile); if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF){ // The image must start with an exif or jfif marker. If we threw those away, create one. static uchar JfifHead[18] = { 0xff, M_JFIF, 0x00, 0x10, ''J'' , ''F'' , ''I'' , ''F'' , 0x00, 0x01, 0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00 }; fwrite(JfifHead, 18, 1, outfile); } // Write all the misc sections for (a=0;a<SectionsRead-1;a++){ fputc(0xff,outfile); fputc(Sections[a].Type, outfile); fwrite(Sections[a].Data, Sections[a].Size, 1, outfile); } // Write the remaining image data. fwrite(Sections[a].Data, Sections[a].Size, 1, outfile); fclose(outfile); }

Me sale el error de arriba en la línea:

exif.saveAttributes();

Es muy inconsistente obtener este error. Además, ni siquiera es detectable en try / catch (Excepción). ¿Cómo puedo arreglarlo?

Gracias por adelantado.