static void sReadImageData(const ZStreamR& iStream, bool iInterlaced, const ZRect& iBounds, ZRef<ZDCPixmapRaster> ioRaster) { uint8 initialCodeSize = iStream.ReadUInt8(); StreamR_Chunk theSIC(iStream); ZStreamR_LZWDecode theSILZW(initialCodeSize, theSIC); ZDCPixmapNS::PixvalDesc sourcePixvalDesc(8, true); void* destBaseAddress = ioRaster->GetBaseAddress(); ZDCPixmapNS::RasterDesc destRasterDesc = ioRaster->GetRasterDesc(); vector<uint8> theRowBufferVector(iBounds.Width()); void* theRowBuffer = &theRowBufferVector[0]; if (iInterlaced) { for (int pass = 0; pass < 4; ++pass) { for (ZCoord currentY = iBounds.top + sInterlaceStart[pass]; currentY < iBounds.bottom; currentY += sInterlaceIncrement[pass]) { theSILZW.Read(theRowBuffer, iBounds.Width()); void* destRowAddress = destRasterDesc.CalcRowAddress(destBaseAddress, currentY); ZDCPixmapNS::sBlitRowPixvals(theRowBuffer, sourcePixvalDesc, 0, destRowAddress, destRasterDesc.fPixvalDesc, iBounds.left, iBounds.Width()); } } } else { for (ZCoord currentY = iBounds.top; currentY < iBounds.bottom; ++currentY) { theSILZW.Read(theRowBuffer, iBounds.Width()); void* destRowAddress = destRasterDesc.CalcRowAddress(destBaseAddress, currentY); ZDCPixmapNS::sBlitRowPixvals(theRowBuffer, sourcePixvalDesc, 0, destRowAddress, destRasterDesc.fPixvalDesc, iBounds.left, iBounds.Width()); } } }
void ZDCPixmapEncoder_GIF::Imp_Write(const ZStreamW& iStream, const void* iBaseAddress, const ZDCPixmapNS::RasterDesc& iRasterDesc, const ZDCPixmapNS::PixelDesc& iPixelDesc, const ZRect& iBounds) { ZRef<ZDCPixmapNS::PixelDescRep_Indexed> thePixelDescRep_Indexed = ZRefDynamicCast<ZDCPixmapNS::PixelDescRep_Indexed>(iPixelDesc.GetRep()); ZAssertStop(2, thePixelDescRep_Indexed); if (fTransparent) iStream.WriteString("GIF89a"); else iStream.WriteString("GIF87a"); iStream.WriteUInt16LE(iBounds.Width()); iStream.WriteUInt16LE(iBounds.Height()); uint8 globalStrmFlags = 0; globalStrmFlags |= 0x80; // hasGlobalColorTable globalStrmFlags |= 0x70; // colorResolution (8 bits per component) // globalStrmFlags |= 0x08; // set this if the color table is sorted in priority order ZAssertStop(2, iRasterDesc.fPixvalDesc.fDepth > 0 && iRasterDesc.fPixvalDesc.fDepth <= 8); globalStrmFlags |= iRasterDesc.fPixvalDesc.fDepth - 1; // globalColorTableSize & depth iStream.WriteUInt8(globalStrmFlags); iStream.WriteUInt8(0); // backgroundColorIndex iStream.WriteUInt8(0); // Pixel aspect ratio -- 0 == none specified. const ZRGBColorPOD* theColors; size_t theColorsCount; thePixelDescRep_Indexed->GetColors(theColors, theColorsCount); sWriteColorTable(iStream, theColors, theColorsCount, 1 << iRasterDesc.fPixvalDesc.fDepth); if (fTransparent) { iStream.WriteUInt8('!'); // Extension block iStream.WriteUInt8(0xF9); // Graphic Control Extension iStream.WriteUInt8(4); // Block size // The next byte encodes four fields: // 3 bits, Reserved == 0 // 3 bits, Disposal Method == none (0), // 1 bit, User Input Flag == none (0) // 1 bit, Transparent Color Flag = yes (1) iStream.WriteUInt8(1); iStream.WriteUInt16LE(0); // Delay time iStream.WriteUInt8(fTransparentPixval); iStream.WriteUInt8(0); // Block terminator } iStream.WriteUInt8(','); // Start of image iStream.WriteUInt16LE(0); // Origin h iStream.WriteUInt16LE(0); // Origin v iStream.WriteUInt16LE(iBounds.Width()); iStream.WriteUInt16LE(iBounds.Height()); uint8 localStrmFlags = 0; // localStrmFlags |= 0x80; // hasLocalColorTable if (fInterlace) localStrmFlags |= 0x40; // interlaced // localStrmFlags |= 0x20; // sorted // localStrmFlags |= 0x70; // localColorTableSize iStream.WriteUInt8(localStrmFlags); iStream.WriteUInt8(iRasterDesc.fPixvalDesc.fDepth); // Initial code size. { // Scope theSC. StreamW_Chunk theSC(iStream); ZStreamW_LZWEncode* theSLZW = nil; ZStreamW_LZWEncodeNoPatent* theSLZWNP = nil; ZStreamW* theStream; if (fNoPatent) { theSLZWNP = new ZStreamW_LZWEncodeNoPatent(iRasterDesc.fPixvalDesc.fDepth, theSC); theStream = theSLZWNP; } else { theSLZW = new ZStreamW_LZWEncode(iRasterDesc.fPixvalDesc.fDepth, theSC); theStream = theSLZW; } ZDCPixmapNS::PixvalDesc destPixvalDesc(8, true); vector<uint8> theRowBufferVector(iBounds.Width()); void* theRowBuffer = &theRowBufferVector[0]; try { if (fInterlace) { for (int pass = 0; pass < 4; ++pass) { for (ZCoord currentY = iBounds.top + sInterlaceStart[pass]; currentY < iBounds.bottom; currentY += sInterlaceIncrement[pass]) { const void* sourceRowAddress = iRasterDesc.CalcRowAddress(iBaseAddress, currentY); ZDCPixmapNS::sBlitRowPixvals( sourceRowAddress, iRasterDesc.fPixvalDesc, iBounds.left, theRowBuffer, destPixvalDesc, 0, iBounds.Width()); theStream->Write(theRowBuffer, iBounds.Width()); } } } else { for (ZCoord currentY = iBounds.top; currentY < iBounds.bottom; ++currentY) { const void* sourceRowAddress = iRasterDesc.CalcRowAddress(iBaseAddress, currentY); ZDCPixmapNS::sBlitRowPixvals( sourceRowAddress, iRasterDesc.fPixvalDesc, iBounds.left, theRowBuffer, destPixvalDesc, 0, iBounds.Width()); theStream->Write(theRowBuffer, iBounds.Width()); } } } catch (...) { delete theSLZW; delete theSLZWNP; throw; } delete theSLZW; delete theSLZWNP; } iStream.WriteUInt8(';'); // Trailer. }
void ZDCPixmapEncoder_JPEGLib::Imp_Write(const ZStreamW& iStream, const void* iBaseAddress, const ZDCPixmapNS::RasterDesc& iRasterDesc, const ZDCPixmapNS::PixelDesc& iPixelDesc, const ZRect& iBounds) { jpeg_compress_struct theJCS; JPEGErrorMgr theEM; theJCS.err = &theEM; ::jpeg_create_compress(&theJCS); theJCS.image_width = iBounds.Width(); theJCS.image_height = iBounds.Height(); JPEGWriter theJW(iStream); theJCS.dest = &theJW; vector<uint8> rowBufferVector; try { ZDCPixmapNS::PixvalDesc destPixvalDesc; ZDCPixmapNS::PixelDesc destPixelDesc; ZRef<ZDCPixmapNS::PixelDescRep> thePixelDescRep = iPixelDesc.GetRep(); if (ZDCPixmapNS::PixelDescRep_Gray* thePixelDescRep_Gray = ZRefDynamicCast<ZDCPixmapNS::PixelDescRep_Gray>(thePixelDescRep)) { theJCS.input_components = 1; theJCS.in_color_space = JCS_GRAYSCALE; rowBufferVector.resize(iBounds.Width()); destPixelDesc = ZDCPixmapNS::PixelDesc(ZDCPixmapNS::eFormatStandard_Gray_8); destPixvalDesc.fDepth = 8; destPixvalDesc.fBigEndian = true; } else { theJCS.input_components = 3; theJCS.in_color_space = JCS_RGB; rowBufferVector.resize(3 * iBounds.Width()); destPixelDesc = ZDCPixmapNS::PixelDesc(ZDCPixmapNS::eFormatStandard_RGB_24); destPixvalDesc.fDepth = 24; destPixvalDesc.fBigEndian = true; } ::jpeg_set_defaults(&theJCS); ::jpeg_set_quality(&theJCS, fQuality, TRUE); theJCS.dct_method = JDCT_FASTEST; ::jpeg_start_compress(&theJCS, TRUE); JSAMPROW rowPtr[1]; rowPtr[0] = &rowBufferVector[0]; for (size_t y = iBounds.top; y < iBounds.bottom; ++y) { const void* sourceRowAddress = iRasterDesc.CalcRowAddress(iBaseAddress, y); ZDCPixmapNS::sBlitRow( sourceRowAddress, iRasterDesc.fPixvalDesc, iPixelDesc, iBounds.left, rowPtr[0], destPixvalDesc, destPixelDesc, 0, iBounds.Width()); ::jpeg_write_scanlines(&theJCS, rowPtr, 1); } ::jpeg_finish_compress(&theJCS); } catch (...) { ::jpeg_destroy(reinterpret_cast<j_common_ptr>(&theJCS)); throw; } ::jpeg_destroy(reinterpret_cast<j_common_ptr>(&theJCS)); }
void ZDCPixmapDecoder_JPEGLib::Imp_Read(const ZStreamR& iStream, ZDCPixmap& oPixmap) { struct jpeg_decompress_struct theJDS; JPEGErrorMgr theEM; theJDS.err = &theEM; ::jpeg_create_decompress(&theJDS); JPEGReader theJR(iStream); theJDS.src = &theJR; try { ::jpeg_read_header(&theJDS, TRUE); ::jpeg_start_decompress(&theJDS); ZDCPixmapNS::PixelDesc sourcePixelDesc; ZDCPixmapNS::PixvalDesc sourcePixvalDesc; vector<uint8> rowBufferVector; if (theJDS.out_color_space == JCS_GRAYSCALE) { sourcePixelDesc = ZDCPixmapNS::PixelDesc(ZDCPixmapNS::eFormatStandard_Gray_8); rowBufferVector.resize(theJDS.image_width); sourcePixvalDesc.fDepth = 8; sourcePixvalDesc.fBigEndian = true; oPixmap = ZDCPixmap(ZPoint(theJDS.image_width, theJDS.image_height), ZDCPixmapNS::eFormatEfficient_Gray_8); } else if (theJDS.out_color_space == JCS_RGB) { sourcePixelDesc = ZDCPixmapNS::PixelDesc(ZDCPixmapNS::eFormatStandard_RGB_24); rowBufferVector.resize(3 * theJDS.image_width); sourcePixvalDesc.fDepth = 24; sourcePixvalDesc.fBigEndian = true; oPixmap = ZDCPixmap(ZPoint(theJDS.image_width, theJDS.image_height), ZDCPixmapNS::eFormatEfficient_Color_24); } else { // TODO. What about other color spaces? ZUnimplemented(); } ZDCPixmapNS::PixelDesc destPixelDesc = oPixmap.GetPixelDesc(); ZDCPixmapNS::RasterDesc destRasterDesc = oPixmap.GetRasterDesc(); void* destBaseAddress = oPixmap.GetBaseAddress(); JSAMPROW rowPtr[1]; rowPtr[0] = &rowBufferVector[0]; while (theJDS.output_scanline < theJDS.output_height) { int scanlinesRead = ::jpeg_read_scanlines(&theJDS, rowPtr, 1); ZAssertStop(1, scanlinesRead == 1); void* destRowAddress = destRasterDesc.CalcRowAddress(destBaseAddress, theJDS.output_scanline - 1); ZDCPixmapNS::sBlitRow( rowPtr[0], sourcePixvalDesc, sourcePixelDesc, 0, destRowAddress, destRasterDesc.fPixvalDesc, destPixelDesc, 0, theJDS.image_width); } ::jpeg_finish_decompress(&theJDS); } catch (...) { ::jpeg_destroy_decompress(&theJDS); throw; } ::jpeg_destroy_decompress(&theJDS); }
static void sUnpackFromStream(const ZStreamR& inStream, ZCoord inSourceWidth, ZCoord inSourceHeight, unsigned short inSourceRowBytes, short inSourcePixelSize, const ZRGBColorPOD* inSourceColors, size_t inSourceColorTableSize, void* inDestBaseAddress, const ZDCPixmapNS::RasterDesc& inDestRasterDesc, const ZDCPixmapNS::PixelDesc& inDestPixelDesc) { // We're only supporting indexed pixels right now ZAssert(inSourcePixelSize == 1 || inSourcePixelSize == 2 || inSourcePixelSize == 4 || inSourcePixelSize == 8); ZDCPixmapNS::PixelDesc sourcePixelDesc(inSourceColors, inSourceColorTableSize); ZDCPixmapNS::PixvalDesc sourcePixvalDesc(inSourcePixelSize, true); if (inSourceRowBytes < 8) { // ah-ha! The bits aren't actually packed. This will be easy. uint8 lineBuffer[8]; for (ZCoord theScanLine = 0; theScanLine < inSourceHeight; ++theScanLine) { inStream.Read(lineBuffer, inSourceRowBytes); void* destRowAddress = inDestRasterDesc.CalcRowAddress(inDestBaseAddress, theScanLine); ZDCPixmapNS::sBlitRow(lineBuffer, sourcePixvalDesc, sourcePixelDesc, 0, destRowAddress, inDestRasterDesc.fPixvalDesc, inDestPixelDesc, 0, inSourceWidth); } } else { // Sometimes we get rows with length > rowBytes. Allocate some extra for slop. // Also note that the data is stored as multiples of rowBytes, which may represent more // pixels than inSourceWidth (if inSourceWidth % 4 != 0). So we have to check for // destinationH < inSourceWidth before we actually blit to the destination. vector<uint8> lineBufferVector(inSourceRowBytes + 80); uint8* lineBuffer = &lineBufferVector[0]; ZDCPixmapNS::PixvalAccessor destAccessor(inDestRasterDesc.fPixvalDesc); for (ZCoord theScanLine = 0; theScanLine < inSourceHeight; ++theScanLine) { void* destRowAddress = inDestRasterDesc.CalcRowAddress(inDestBaseAddress, theScanLine); size_t lineLen; if (inSourceRowBytes > 250 || inSourcePixelSize > 8) lineLen = inStream.ReadUInt16(); else lineLen = inStream.ReadUInt8(); if (lineLen > inSourceRowBytes + 80) ::sThrowBadFormat(); inStream.Read(lineBuffer, lineLen); ZCoord destinationH = 0; for (size_t j = 0; j < lineLen; /*no increment*/) { if (lineBuffer[j] & 0x80) { size_t repeatCount = (lineBuffer[j++] ^ 0xFF) + 2; ZRGBColorPOD theRGBColor; sourcePixelDesc.AsRGBColor(lineBuffer[j++], theRGBColor); uint32 destPixval = inDestPixelDesc.AsPixval(theRGBColor); for (size_t k = 0; k < repeatCount; ++k) { if (destinationH < inSourceWidth) destAccessor.SetPixval(destRowAddress, destinationH, destPixval); destinationH += 1; } } else { size_t realLength = lineBuffer[j] + 1; if (inSourceWidth > destinationH) { size_t countToCopy = min(realLength, size_t(inSourceWidth - destinationH)); ZDCPixmapNS::sBlitRow(lineBuffer, sourcePixvalDesc, sourcePixelDesc, j + 1, destRowAddress, inDestRasterDesc.fPixvalDesc, inDestPixelDesc, destinationH, countToCopy); destinationH += countToCopy; } j += realLength + 1; } } } } }