1998.06.29 17:19 "Does anyone have an old-style JPEG codec?", by Gerben Vos

1998.06.29 20:08 "Re: Does anyone have an old-style JPEG codec?", by Rex Jolliff

Does anyone have an old-style JPEG decoder, i.e., one using the deprecated TIFF/JPEG encoding in the TIFF 6.0 spec? I only need it to read such TIFFs.

I have a program that extracts a JPEG from a V6 TIFF generated by Pixel translations OCX controls. I believe these are different than the Wang imaging controls though. It turns out in the case of the Pixel Translation controls, that the data from two tags can be extracted and concatenated to create a complete JPEG. Perhaps this is the case with the wang stuff also?

The code is below, though you should use the TIFF library routines to extract the data insted of what I did.

Rex.

-----
char *V6JETGetJPEG(const char *Filename, uint32 *JPEGLength) {
  BOOL    BigEndian;
  char    *OutData;
  uint16  IFDCount, CurIdx, CurTag, CurType;
  uint32  IFDOffset, CurCount, CurValue;
  uint32  JFIFOffset, JFIFLength, StripOffset, StripLength;
  MAP     InData;

  DBGDebug(2, ">> GetJPEGData");

    /*  Open file  */
  if ((InData = MAPOpen(Filename)) == NULL) {
    DBGError("%s: could not open input file", Filename);
    return NULL;
  }
  DBGDebug(2, "File opened");

    /*  Read endian flag/Magic number  */
  if (InData[0] == 'I' && InData[1] == 'I') {
    BigEndian = FALSE;
  } else if (InData[0] == 'M' && InData[1] == 'M') {
    BigEndian = TRUE;
  } else {
    DBGError("%s: Invalid endian flag", Filename);
    MAPClose(InData);
    return NULL;
  }
  DBGDebug(2, "BigEndian: %s", BigEndian ? "TRUE" : "FALSE");
  if (GetWord(BigEndian, InData + 2) != 42) {
    DBGError("%s: Bad magic number", Filename);
    MAPClose(InData);
    return NULL;
  }
  DBGDebug(2, "Magic number is good");

    /*  Get directory pointer  */
  IFDOffset = GetDWord(BigEndian, InData + 4);
  if (IFDOffset > MAPSize(InData)) {
    DBGError("%s: invalid IFD pointer %08lx %08lx", Filename, IFDOffset,
        MAPSize(InData));
    MAPClose(InData);
    return NULL;
  }
  DBGDebug(2, "IFD Offset at %08lx", IFDOffset);

    /*  Get directory count  */
  IFDCount = GetWord(BigEndian, InData + IFDOffset);
  IFDOffset += 2;
  DBGDebug(2, "IFDCount is %d", IFDCount);

  for (CurIdx = 0; CurIdx < IFDCount; CurIdx++) {
      /*  Get directory entry  */
    CurTag = GetWord(BigEndian, InData + IFDOffset + CurIdx * 12);
    CurType = GetWord(BigEndian, InData + IFDOffset + CurIdx * 12 + 2);
    CurCount = GetDWord(BigEndian, InData + IFDOffset + CurIdx * 12 + 4);
    CurValue = GetDWord(BigEndian, InData + IFDOffset + CurIdx * 12 + 8);
    DBGDebug(2, "Entry #%d  Tag: %04x  Type: %d  Count: %d  Value: %08lx",
        CurIdx, CurTag, CurType, CurCount, CurValue);

      /*  If entry is Compression, make sure old style jpeg  */
    if (CurTag == TIFFTAG_COMPRESSION && CurValue != COMPRESSION_OJPEG) {
      DBGError("%s: File in not stored in old style JPEG compression",
          Filename);
      MAPClose(InData);
      return NULL;
    } else if (CurTag == TIFFTAG_JPEGIFOFFSET) {
      JFIFOffset = CurValue;
      DBGDebug(2, "JPEG IF Offset %08lx", JFIFOffset);
    } else if (CurTag == TIFFTAG_JPEGIFBYTECOUNT) {
      JFIFLength = CurValue;
      DBGDebug(2, "JPEG IF Length %08lx", JFIFLength);
    } else if (CurTag == TIFFTAG_STRIPOFFSETS) {
      if (CurCount > 1) {
        DBGError("multiple strips not handled yet");
        MAPClose(InData);
        return NULL;
      }
      StripOffset = CurValue;
      DBGDebug(2, "Strip Offset %08lx", StripOffset);
    } else if (CurTag == TIFFTAG_STRIPBYTECOUNTS) {
      StripLength = CurValue;
      DBGDebug(2, "Strip Length %08lx", StripLength);
    }
  }
  DBGDebug(2, "Read IFD");

    /*  Allocate memory for JPEG  */
  if ((OutData = (char *)malloc(JFIFLength + StripLength)) == NULL) {
    DBGError("%s: Could not allocate memory for JPEG data", Filename);
    MAPClose(InData);
    return NULL;
  }
  DBGDebug(2, "Allocated %d bytes for jpeg data at %08lx",
      JFIFLength + StripLength, OutData);

    /*  Copy JPEG Data  */
  memcpy(OutData, InData + JFIFOffset, JFIFLength);
  memcpy(OutData + JFIFLength, InData + StripOffset, StripLength);
  *JPEGLength = JFIFLength + StripLength;
  DBGDebug(2, "Copied data");

    /*  Close file  */
  MAPClose(InData);
  DBGDebug(2, "Closed file");

  DBGDebug(2, "<< GetJPEGData");
  return OutData;
}