Tag Archives: PNG

Alfresco Share Support for SketchUp Files

I’m a huge fan of Alfresco, the Java-based open source ECM. Having spent the better part of a year migrating a proprietary customization and asset management platform into Alfresco, I developed a deep appreciation for the extensibility of the platform. Because it’s open source, I was able to make use of it at home for managing household documents – both electronic and scanned originals.

As an amateur woodworker and SketchUp user, I’ve also built up a small library of design documents used for past projects. Naturally, I decided to store these in the new Alfresco repository. However, I found the lack of native support for the SketchUp file format frustrating. I was accustomed to seeing thumbnail previews of my other documents and really wanted a preview for SketchUp as well.

Turns out that SketchUp files contain bitmap previews in PNG format, and one need only locate and extract the bits from the SKP file in order to make them available to Alfresco.

The heart of the AbstractContentTransformer2 extension class’s transformInternal method…

		// Write out the PNG
		InputStream in = reader.getContentInputStream();
		OutputStream out = writer.getContentOutputStream();
		try {
			BitmapExtractor extractor = extractors.get(sourceMimetype);
			if (extractor == null) {
				throw new IllegalArgumentException("No extractor configured " +
						"for source mimetype [" + sourceMimetype + "]");
			}
			extractor.extractBitmap(index, in, out);
		}
		finally {
			IOUtils.closeQuietly(in);
			IOUtils.closeQuietly(out);
		}

…calls on a custom PngExtractor to do the actual work (from the superclass AbstractDelimitedBitmapExtractor

	public boolean extractBitmap(int n, InputStream in, OutputStream out) throws IOException {
		byte[] header = getHeaderSequence();
		byte[] footer = getFooterSequence();

		in = buffer(in);
		int count = 0;
		while (nextMatch(header, in)) {
			if (++count == n) {
				// This is the one we're after. Read in the PNG until the PNG_FOOTER...
				out.write(header);
				int b = 0;
				while((b = in.read()) != -1) {
					if (matches(footer, in, b)) {
						// Matched footer. Stream not reset so
						// write footer and exit.
						out.write(footer);
						return true;
					}
					out.write(b);
				}

			}
		}
		return false;
	}

The full set of classes is available on google code under the alfresco-extra-mimetypes project. I hope to extend support to CorelDraw and InDesign documents, among others where possible. Enjoy.