bool InternalGenerator::writeText (const Byte *string) { #ifdef DEBUG_INTERNALGENERATOR // m_device->debug ("!!!! InternalGenerator: writeText> ", (const char *) string); #endif DWord length = DWord (strlen ((const char *) string)); if (!m_device->writeInternal (string, length)) return false; return true; }
bool Image::writeToDevice (void) { CHECK_DEVICE; #ifdef DEBUG_IMAGE m_device->debug ("\n>>>> Image::writeToDevice <<<<\n"); #endif #ifdef DEBUG_IMAGE Dump (mappingMode); //Dump (MFP_width); // will change below //Dump (MFP_height); Dump (MFP_unknown); Dump (indent); //Dump (width); //Dump (height); Dump (zero); Dump (numHeaderBytes); //Dump (numDataBytes); //Dump (horizontalScalingRel1000); //Dump (verticalScalingRel1000); #endif // sanity checking if (!m_externalImage || m_externalImageSize <= 0 || m_originalWidth <= 0 || m_originalHeight <= 0 || m_displayedWidth <= 0 || m_displayedHeight <= 0) { ErrorAndQuit (Error::InternalError, "uninitialised or invalid Image\n"); } // // write data // // if (getIsWMF ()) { // Header check WMFHeader wmfHeader; m_device->setCache (m_externalImage); wmfHeader.setDevice (m_device); if (!wmfHeader.readFromDevice ()) return false; // TODO: fix this incorrect check (see wmf.cpp) //if (wmfHeader.getFileSize () * sizeof (Word) != m_externalImageSize) // m_device->error (Error::Warn, "wmfHeader.fileSize != externalImageSize\n"); m_device->setCache (NULL); // // set image dimensions // // entire BitmapHeader is unused with WMFs m_bmh->setWidth (0); m_bmh->setHeight (0); m_bmh->setWidthBytes (0); m_bmh->setNumPlanes (0); m_bmh->setBitsPerPixel (0); m_MFP_width = Word (Twip2Milli (m_originalWidth * 0.75) * 100.0); m_MFP_height = Word (Twip2Milli (m_originalHeight * 0.75) * 100.0); m_width = Word (m_displayedWidth); m_height = Word (m_displayedHeight); // not used by WMFs m_horizontalScalingRel1000 = m_verticalScalingRel1000 = 1000; // write header setNumDataBytes (m_externalImageSize); if (!ImageGenerated::writeToDevice ()) return false; // external=internal with WMF (i.e. we really do write a WMF) if (!m_device->writeInternal (m_externalImage, m_externalImageSize)) return false; } else // if (getIsBMP ()) { m_device->setCache (m_externalImage); BMP_BitmapFileHeader fileHeader; fileHeader.setDevice (m_device); if (!fileHeader.readFromDevice ()) return false; /*Word colorTableSize = (1 << m_bmh->getNumPlanes ()) * BMP_BitmapColorIndex::s_size; // fileHeader DWord fileSize = BMP_BitmapFileHeader::s_size + BMP_BitmapInfoHeader::s_size + colorTableSize + (m_bmh->getHeight () * getBytesPerScanLine (m_bmh->getWidth (), m_bmh->getBitsPerPixel (), 4)); fileHeader.setTotalBytes (fileSize); fileHeader.setActualImageOffset (BMP_BitmapFileHeader::s_size + BMP_BitmapInfoHeader::s_size + colorTableSize);*/ // infoHeader BMP_BitmapInfoHeader infoHeader; infoHeader.setDevice (m_device); if (!infoHeader.readFromDevice ()) return false; // write out each scanline // to .WRI (padded to 2) vs input BMP (padded to 4 Word scanLineWRILength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 2); Word scanLineBMPLength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 4); if (infoHeader.getWidth () <= 0 || infoHeader.getHeight () <= 0) ErrorAndQuit (Error::InvalidFormat, "infoHeader invalid dimensions\n"); // did the user lie about the dimensions of the BMP? if (infoHeader.getWidth () != Word (Twip2Point (m_originalWidth))) m_device->error (Error::Warn, "infoHeader width != m_originalWidth\n"); if (infoHeader.getHeight () != Word (Twip2Point (m_originalHeight))) m_device->error (Error::Warn, "infoHeader.height != m_originalHeight\n"); m_bmh->setWidth (infoHeader.getWidth ()); m_bmh->setHeight (infoHeader.getHeight ()); m_bmh->setWidthBytes (scanLineWRILength); if (infoHeader.getNumPlanes () != 1) ErrorAndQuit (Error::InvalidFormat, "infoHeader.getNumPlanes() != 1\n"); m_bmh->setNumPlanes (infoHeader.getNumPlanes ()); m_bmh->setBitsPerPixel (infoHeader.getBitsPerPixel ()); if (infoHeader.getCompression () != 0) // BI_RGB (uncompressed) ErrorAndQuit (Error::Unsupported, "compressed bitmaps unsupported\n"); //infoHeader.setSizeImage (0); // lazy //infoHeader.setXPixelsPerMeter (0), infoHeader.setYPixelsPerMeter (0); infoHeader.setColorsUsed (1 << infoHeader.getBitsPerPixel ()); // make life easier //infoHeader.setColorsImportant (infoHeader.getColorsUsed ()); if (infoHeader.getColorsUsed () != 2) ErrorAndQuit (Error::Unsupported, "can't save color BMPs, use WMFs for that purpose\n"); // colorTable BMP_BitmapColorIndex *colorIndex = new BMP_BitmapColorIndex [infoHeader.getColorsUsed ()]; if (!colorIndex) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for colorIndex[]\n"); colorIndex [0].setDevice (m_device); if (!colorIndex [0].readFromDevice ()) return false; if (colorIndex [0].getRed () != 0 || colorIndex [0].getGreen () != 0 || colorIndex [0].getBlue () != 0) m_device->error (Error::Warn, "black not black\n"); colorIndex [1].setDevice (m_device); if (!colorIndex [1].readFromDevice ()) return false; if (colorIndex [1].getRed () != 0xFF || colorIndex [1].getGreen () != 0xFF || colorIndex [1].getBlue () != 0xFF) m_device->error (Error::Warn, "white not white\n"); // finish reading from m_externalImage m_device->setCache (NULL); // // set image dimensions // m_MFP_width = Word (Twip2Point (m_originalWidth) * 2.64); m_MFP_height = Word (Twip2Point (m_originalHeight) * 2.64); // BMPs don't use m_width = 0, m_height = 0; m_horizontalScalingRel1000 = Word (m_displayedWidth * 1.38889 * 1000.0 / m_originalWidth); m_verticalScalingRel1000 = Word (m_displayedHeight * 1.38889 * 1000.0 / m_originalHeight); // write header setNumDataBytes (infoHeader.getHeight () * scanLineWRILength); if (!ImageGenerated::writeToDevice ()) return false; // sanity check DWord expectedSize = DWord (infoHeader.getHeight ()) * DWord (scanLineBMPLength); DWord imageSize = m_externalImageSize - fileHeader.getActualImageOffset (); if (expectedSize != imageSize) { if (expectedSize > imageSize) { // better quit instead of reading past end of m_externalImage[] ErrorAndQuit (Error::InvalidFormat, "infoHeader.getHeight () * scanLineBMPLength > imageSize\n"); } else m_device->error (Error::Warn, "infoHeader.getHeight () * scanLineBMPLength != imageSize\n"); } // the DIB is upside-down... Byte *bmpData = m_externalImage + fileHeader.getActualImageOffset () + (infoHeader.getHeight () - 1) * scanLineBMPLength; for (int i = (int) infoHeader.getHeight () - 1; i >= 0; i--) { // write bitmap scanline (padded to 2) //if (!m_device->writeInternal (m_externalImage + fileHeader.getActualImageOffset () + i * scanLineBMPLength, scanLineWRILength)) if (!m_device->writeInternal (bmpData, scanLineWRILength)) return false; bmpData -= scanLineBMPLength; } delete [] colorIndex; } return true; }
bool Image::readFromDevice (void) { CHECK_DEVICE; #ifdef DEBUG_IMAGE m_device->debug ("\n<<<< Image::readFromDevice >>>>\n"); #endif if (!ImageGenerated::readFromDevice ()) return false; #ifdef DEBUG_IMAGE Dump (mappingMode); Dump (MFP_width); Dump (MFP_height); Dump (MFP_unknown); Dump (indent); Dump (width); Dump (height); Dump (zero); Dump (numHeaderBytes); Dump (numDataBytes); Dump (horizontalScalingRel1000); Dump (verticalScalingRel1000); #endif if (getIsWMF ()) { // // get image dimensions // if (m_bmh->getWidth () || m_bmh->getHeight ()) m_device->error (Error::Warn, "m_bmh structure should be 0 for WMFs\n"); m_originalWidth = Milli2Twip (double (m_MFP_width) / 100.0) * 4.0/3.0; m_originalHeight = Milli2Twip (double (m_MFP_height) / 100.0) * 4.0/3.0; m_displayedWidth = double (m_width); m_displayedHeight = double (m_height); if (m_horizontalScalingRel1000 != 1000) m_device->error (Error::Warn, "horizontal scaling should not be set for WMFs\n"); if (m_verticalScalingRel1000 != 1000) m_device->error (Error::Warn, "vertical scaling should not be set for WMFs\n"); // // read image // m_externalImage = new Byte [m_externalImageSize = getNumDataBytes ()]; if (!m_externalImage) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for external WMF image\n"); if (!m_device->readInternal (m_externalImage, m_externalImageSize)) ErrorAndQuit (Error::FileError, "could not read internal WMF\n"); // Header check WMFHeader wmfHeader; m_device->setCache (m_externalImage); wmfHeader.setDevice (m_device); if (!wmfHeader.readFromDevice ()) return false; // TODO: fix this incorrect check (see wmf.cpp) //if (wmfHeader.getFileSize () * sizeof (Word) != m_numDataBytes) // m_device->error (Error::Warn, "wmfHeader.fileSize != numDataBytes\n"); m_device->setCache (NULL); } else // if (getIsBMP ()) { // // get image dimensions // m_originalWidth = Point2Twip (DWord (m_bmh->getWidth ())); m_originalHeight = Point2Twip (DWord (m_bmh->getHeight ())); m_displayedWidth = m_originalWidth / 1.38889 * m_horizontalScalingRel1000 / 1000; m_displayedHeight = m_originalHeight / 1.38889 * m_verticalScalingRel1000 / 1000; #define MSWrite_fabs(val) (((val)>=0)?(val):(-(val))) if (MSWrite_fabs (m_MFP_width / double (m_bmh->getWidth ()) - 2.64) > .3) m_device->error (Error::Warn, "m_MFP_width != m_bmh->getWidth() * 2.64\n"); if (MSWrite_fabs (m_MFP_height / double (m_bmh->getHeight ()) - 2.64) > .3) m_device->error (Error::Warn, "m_MFP_height != m_bmh->getHeight() * 2.64\n"); #undef MSWrite_fabs if (m_width) m_device->error (Error::Warn, "m_width should not be set for BMPs\n"); if (m_height) m_device->error (Error::Warn, "m_height should not be set for BMPs\n"); // // read image // Byte *internalData = new Byte [getNumDataBytes ()]; if (!internalData) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for internal BMP image\n"); if (!m_device->readInternal (internalData, getNumDataBytes ())) ErrorAndQuit (Error::FileError, "could not read internal BMP\n"); // infoHeader BMP_BitmapInfoHeader infoHeader; infoHeader.setWidth (m_bmh->getWidth ()); infoHeader.setHeight (m_bmh->getHeight ()); if (m_bmh->getNumPlanes () != 1) ErrorAndQuit (Error::InvalidFormat, "bmh.m_numPlanes != 1\n"); infoHeader.setNumPlanes (m_bmh->getNumPlanes ()); infoHeader.setBitsPerPixel (m_bmh->getBitsPerPixel ()); infoHeader.setCompression (0); // BI_RGB (uncompressed) infoHeader.setSizeImage (0); // lazy infoHeader.setXPixelsPerMeter (0), infoHeader.setYPixelsPerMeter (0); infoHeader.setColorsUsed (1 << infoHeader.getBitsPerPixel ()); infoHeader.setColorsImportant (infoHeader.getColorsUsed ()); if (infoHeader.getColorsUsed () != 2) ErrorAndQuit (Error::InternalError, "color bitmap??? Please email this file to <*****@*****.**>\n"); Word colorTableSize = infoHeader.getColorsUsed () * BMP_BitmapColorIndex::s_size; // fileHeader BMP_BitmapFileHeader fileHeader; DWord fileSize = BMP_BitmapFileHeader::s_size + BMP_BitmapInfoHeader::s_size + colorTableSize + (m_bmh->getHeight () * getBytesPerScanLine (m_bmh->getWidth (), m_bmh->getBitsPerPixel (), 4)); fileHeader.setTotalBytes (fileSize); fileHeader.setActualImageOffset (BMP_BitmapFileHeader::s_size + BMP_BitmapInfoHeader::s_size + colorTableSize); // colorTable BMP_BitmapColorIndex *colorIndex = new BMP_BitmapColorIndex [infoHeader.getColorsUsed ()]; if (!colorIndex) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for colorIndex[]\n"); // black and white... colorIndex [0].setRed (0), colorIndex [0].setGreen (0), colorIndex [0].setBlue (0); colorIndex [1].setRed (0xFF), colorIndex [1].setGreen (0xFF), colorIndex [1].setBlue (0xFF); m_externalImage = new Byte [m_externalImageSize = fileSize]; if (!m_externalImage) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for external BMP image\n"); MemoryDevice device; device.setCache (m_externalImage); fileHeader.setDevice (&device); fileHeader.writeToDevice (); infoHeader.setDevice (&device); infoHeader.writeToDevice (); for (int i = 0; i < 2; i++) { colorIndex [i].setDevice (&device); colorIndex [i].writeToDevice (); } // (BMP padded to 4 bytes vs WRI input bitmap which is actually padded to 2) Word scanLineWRILength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 2); if (scanLineWRILength != m_bmh->getWidthBytes ()) ErrorAndQuit (Error::InvalidFormat, "scanLineWRILength != m_bmh->getWidthBytes()\n"); Word scanLineBMPLength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 4); #ifdef DEBUG_IMAGE m_device->debug ("in: scanLineWRILength: ", scanLineWRILength); m_device->debug ("out: scanLineBMPLength: ", scanLineBMPLength); #endif // sanity check DWord expectedSize = DWord (infoHeader.getHeight ()) * DWord (scanLineWRILength); if (expectedSize != getNumDataBytes ()) { if (expectedSize > getNumDataBytes ()) { // better quit instead of reading past end of internalData[] ErrorAndQuit (Error::InvalidFormat, "infoHeader.getHeight () * scanLineWRILength > numDataBytes\n"); } else m_device->error (Error::Warn, "infoHeader.getHeight () * scanLineWRILength != numDataBytes\n"); } Byte *padding = new Byte [scanLineBMPLength - scanLineWRILength]; if (!padding) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for scanline\n"); memset (padding, 0, scanLineBMPLength - scanLineWRILength); // the DIB is upside-down... for (int i = (int) infoHeader.getHeight () - 1; i >= 0; i--) { // write bitmap scanline device.writeInternal (internalData + i * scanLineWRILength, scanLineWRILength * sizeof (Byte)); // write padding for scanline device.writeInternal (padding, (scanLineBMPLength - scanLineWRILength) * sizeof (Byte)); } delete [] padding; device.setCache (NULL); delete [] colorIndex; delete [] internalData; } return true; }