void NPainter_FromPICT(const ZStreamR& inStream, ZDCPixmap& outPixmap) { inStream.ReadInt16(); // picSize. This field has been obsolete since 1987. inStream.ReadInt16(); // picFrame.top inStream.ReadInt16(); // picFrame.left inStream.ReadInt16(); // picFrame.bottom inStream.ReadInt16(); // picFrame.right uint8 ch; // skip any empty bytes while ((ch = inStream.ReadUInt8()) == 0) {} if (ch != 0x11) throw runtime_error("NPainter_FromPICT, expected version opcode"); if ((ch = inStream.ReadUInt8()) != 0x02) throw runtime_error("NPainter_FromPICT, expected version number 2"); if ((ch = inStream.ReadUInt8()) != 0xFF) throw runtime_error("NPainter_FromPICT, expected subcode 0xFF"); // The order of remaining opcodes is not always the same, hence we use a loop to consume them. uint16 opcode; while (true) { opcode = inStream.ReadUInt16(); if (opcode == 0x0C00) // Header, followed by 24 bytes of data we don't need inStream.Skip(24); else if (opcode == 0x01) // Clip rgn { unsigned short clipBytes = inStream.ReadUInt16() - sizeof(short); inStream.Skip(clipBytes); } else if (opcode != 0x1E) // Hilite break; } if (opcode != 0x98) throw runtime_error("NPainter_FromPICT, expected packbits opcode"); // Do the actual read ::sReadPixmap(inStream, outPixmap); // Suck up remaining data while ((ch = inStream.ReadUInt8()) == 0x00) {} if (ch != 0xFF) throw runtime_error("NPainter_FromPICT, expected end of picture opcode"); }
static void sReadPixmap(const ZStreamR& inStream, ZDCPixmap& outPixmap) { uint16 rowBytes = inStream.ReadUInt16(); if (!(rowBytes & 0x8000)) ::sThrowBadFormat(); rowBytes &= 0x7FFF; ZRect bounds; bounds.top = inStream.ReadInt16(); bounds.left = inStream.ReadInt16(); bounds.bottom = inStream.ReadInt16(); bounds.right = inStream.ReadInt16(); inStream.ReadInt16(); // version inStream.ReadInt16(); // packType inStream.ReadInt32(); // packSize inStream.ReadInt32(); // hRes inStream.ReadInt32(); //vRes short pixelType = inStream.ReadInt16(); // pixelType short pixelSize = inStream.ReadInt16(); // pixelSize short cmpCount = inStream.ReadInt16(); // cmpCount short cmpSize = inStream.ReadInt16(); // cmpSize inStream.ReadInt32(); // planeBytes inStream.ReadInt32(); // pmTable inStream.ReadInt32(); // pmReserved // We only deal with pixel type of 0 (indexed pixels) if (pixelType != 0) ::sThrowUnsupportedFormat(); // indexed pixels have a cmpCount of 1 if (cmpCount != 1) ::sThrowBadFormat(); // pixelSize and cmpSize should be equal for indexed pixels if (pixelSize != cmpSize) ::sThrowBadFormat(); // Next on the stream is the color table vector<ZRGBColor> theColorTable; inStream.ReadInt32(); // ctSeed inStream.ReadInt16(); // ctFlags short ctSize = inStream.ReadInt16(); for (int i = 0; i <= ctSize; ++i) { inStream.ReadInt16(); // colorSpecIndex ZRGBColor theColor; theColor.red = inStream.ReadUInt16(); theColor.green = inStream.ReadUInt16(); theColor.blue = inStream.ReadUInt16(); theColorTable.push_back(theColor); } // Now we have the source rect inStream.Skip(8); // and the destination rect inStream.Skip(8); // Penultimately we have the mode inStream.ReadUInt16(); // The remaining data is the packed pixels. Allocate our ZDCPixmap // using the size we read in, but with no initialized data. ZDCPixmap thePixmap(bounds.Size(), ZDCPixmapNS::eFormatEfficient_Color_32); void* baseAddress = thePixmap.GetBaseAddress(); ZDCPixmapNS::RasterDesc theRasterDesc = thePixmap.GetRasterDesc(); ZDCPixmapNS::PixelDesc thePixelDesc = thePixmap.GetPixelDesc(); ::sUnpackFromStream(inStream, bounds.Width(), bounds.Height(), rowBytes, pixelSize, &theColorTable[0], theColorTable.size(), baseAddress, theRasterDesc, thePixelDesc); outPixmap = thePixmap; }