int DetectBySignature(const void *pHeader, sint32 nHeaderSize, const void *pFooter, sint32 nFooterSize, sint64 nFileSize) { if (nHeaderSize >= 32) { const uint8 *buf = (const uint8 *)pHeader; const uint8 kPNGSignature[8]={137,80,78,71,13,10,26,10}; // Check for PNG if (!memcmp(buf, kPNGSignature, 8)) return 1; // Check for BMP if (buf[0] == 'B' && buf[1] == 'M') return 1; // Check for MayaIFF (FOR4....CIMG) if (VDIsMayaIFFHeader(pHeader, nHeaderSize)) return 1; if (buf[0] == 0xFF && buf[1] == 0xD8) { if (buf[2] == 0xFF && buf[3] == 0xE0) { // x'FF' SOI x'FF' APP0 // Hmm... might be a JPEG image. Check for JFIF tag. if (buf[6] == 'J' && buf[7] == 'F' && buf[8] == 'I' && buf[9] == 'F') return 1; // Looks like JPEG to me. } // Nope, see if it's an Exif file instead (used by digital cameras). if (buf[2] == 0xFF && buf[3] == 0xE1) { // x'FF' SOI x'FF' APP1 if (buf[6] == 'E' && buf[7] == 'x' && buf[8] == 'i' && buf[9] == 'f') return 1; // Looks like JPEG to me. } // Look for a bare JPEG (start of second marker and x'FF' EOI at the end const uint8 *footer = (const uint8 *)pFooter; if (buf[2] == 0xFF && nFooterSize >= 2 && footer[nFooterSize - 2] == 0xFF && footer[nFooterSize - 1] == 0xD9) return 1; } } if (nFooterSize > 18) { if (!memcmp((const uint8 *)pFooter + nFooterSize - 18, "TRUEVISION-XFILE.", 18)) return 1; } return -1; }
const void *VideoSourceImages::streamGetFrame(const void *inputBuffer, uint32 data_len, bool is_preroll, VDPosition frame_num, VDPosition target_sample) { // We may get a zero-byte frame if we already have the image. if (!data_len) return getFrameBuffer(); int w, h; bool bHasAlpha; bool bIsPNG = false; bool bIsJPG = false; bool bIsBMP = false; bool bIsIFF = false; bool bIsTGA = false; bIsPNG = VDDecodePNGHeader(inputBuffer, data_len, w, h, bHasAlpha); if (!bIsPNG) { bIsJPG = VDIsJPEGHeader(inputBuffer, data_len); if (!bIsJPG) { bIsBMP = DecodeBMPHeader(inputBuffer, data_len, w, h, bHasAlpha); if (!bIsBMP) { bIsIFF = VDIsMayaIFFHeader(inputBuffer, data_len); if (!bIsIFF) bIsTGA = DecodeTGAHeader(inputBuffer, data_len, w, h, bHasAlpha); } } } if (!bIsBMP && !bIsTGA && !bIsJPG && !bIsPNG && !bIsIFF) throw MyError("Image file must be in PNG, Windows BMP, truecolor TARGA format, MayaIFF, or sequential JPEG format."); if (bIsJPG) { if (!mpJPEGDecoder) mpJPEGDecoder = VDCreateJPEGDecoder(); mpJPEGDecoder->Begin(inputBuffer, data_len); mpJPEGDecoder->DecodeHeader(w, h); } VDPixmap pxIFF; if (bIsIFF) { if (!mpIFFDecoder) mpIFFDecoder = VDCreateImageDecoderIFF(); pxIFF = mpIFFDecoder->Decode(inputBuffer, data_len); w = pxIFF.w; h = pxIFF.h; } // Check image header. VDAVIBitmapInfoHeader *pFormat = getImageFormat(); if (getFrameBuffer()) { if (w != pFormat->biWidth || h != pFormat->biHeight) { vdfastvector<wchar_t> errBuf; throw MyError("Image \"%ls\" (%dx%d) doesn't match the image dimensions of the first image (%dx%d)." , mpParent->ComputeFilename(errBuf, frame_num), w, h, pFormat->biWidth, pFormat->biHeight); } } else { if (!AllocFrameBuffer(w * h * 4)) throw MyMemoryError(); pFormat->biSize = sizeof(BITMAPINFOHEADER); pFormat->biWidth = w; pFormat->biHeight = h; pFormat->biPlanes = 1; pFormat->biCompression = 0xFFFFFFFFUL; pFormat->biBitCount = 0; pFormat->biSizeImage = 0; pFormat->biXPelsPerMeter = 0; pFormat->biYPelsPerMeter = 0; pFormat->biClrUsed = 0; pFormat->biClrImportant = 0; // special case for initial read in constructor return NULL; } if (bIsJPG) { int format; switch(mvbFrameBuffer.depth) { case 16: format = IVDJPEGDecoder::kFormatXRGB1555; break; case 24: format = IVDJPEGDecoder::kFormatRGB888; break; case 32: format = IVDJPEGDecoder::kFormatXRGB8888; break; } mpJPEGDecoder->DecodeImage((char *)mvbFrameBuffer.data + mvbFrameBuffer.pitch * (mvbFrameBuffer.h - 1), -mvbFrameBuffer.pitch, format); mpJPEGDecoder->End(); } if (bIsIFF) VDPixmapBlt(getTargetFormat(), pxIFF); if (bIsBMP) DecodeBMP(inputBuffer, data_len, mvbFrameBuffer); if (bIsTGA) DecodeTGA(inputBuffer, data_len, mvbFrameBuffer); if (bIsPNG) { if (!mpPNGDecoder) mpPNGDecoder = VDCreateImageDecoderPNG(); PNGDecodeError err = mpPNGDecoder->Decode(inputBuffer, data_len); if (err) { if (err == kPNGDecodeOutOfMemory) throw MyMemoryError(); vdfastvector<wchar_t> errBuf; throw MyError("Error decoding \"%ls\": %ls\n", mpParent->ComputeFilename(errBuf, frame_num), VDLoadString(0, kVDST_PNGDecodeErrors, err)); } VDPixmapBlt(VDAsPixmap(mvbFrameBuffer), mpPNGDecoder->GetFrameBuffer()); } mCachedFrame = frame_num; return mpFrameBuffer; }