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)); }