From c9794bddd78b1bad1496da3f2367a430fd36ce91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sat, 16 Feb 2008 13:02:03 +0000 Subject: [PATCH] added a PCX translator with some supported formats git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23963 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/translators/Jamfile | 1 + src/add-ons/translators/pcx/ConfigView.cpp | 57 ++++ src/add-ons/translators/pcx/ConfigView.h | 19 ++ src/add-ons/translators/pcx/Jamfile | 27 ++ src/add-ons/translators/pcx/PCX.cpp | 257 ++++++++++++++++++ src/add-ons/translators/pcx/PCX.h | 58 ++++ src/add-ons/translators/pcx/PCXTranslator.cpp | 174 ++++++++++++ src/add-ons/translators/pcx/PCXTranslator.h | 59 ++++ src/add-ons/translators/pcx/main.cpp | 28 ++ 9 files changed, 680 insertions(+) create mode 100644 src/add-ons/translators/pcx/ConfigView.cpp create mode 100644 src/add-ons/translators/pcx/ConfigView.h create mode 100644 src/add-ons/translators/pcx/Jamfile create mode 100644 src/add-ons/translators/pcx/PCX.cpp create mode 100644 src/add-ons/translators/pcx/PCX.h create mode 100644 src/add-ons/translators/pcx/PCXTranslator.cpp create mode 100644 src/add-ons/translators/pcx/PCXTranslator.h create mode 100644 src/add-ons/translators/pcx/main.cpp diff --git a/src/add-ons/translators/Jamfile b/src/add-ons/translators/Jamfile index 81903f2974..8881d577fe 100644 --- a/src/add-ons/translators/Jamfile +++ b/src/add-ons/translators/Jamfile @@ -8,6 +8,7 @@ SubInclude HAIKU_TOP src add-ons translators ico ; SubInclude HAIKU_TOP src add-ons translators jpeg ; SubInclude HAIKU_TOP src add-ons translators jpeg2000 ; SubInclude HAIKU_TOP src add-ons translators libtiff ; +SubInclude HAIKU_TOP src add-ons translators pcx ; SubInclude HAIKU_TOP src add-ons translators png ; SubInclude HAIKU_TOP src add-ons translators ppm ; SubInclude HAIKU_TOP src add-ons translators raw ; diff --git a/src/add-ons/translators/pcx/ConfigView.cpp b/src/add-ons/translators/pcx/ConfigView.cpp new file mode 100644 index 0000000000..bfee818bb8 --- /dev/null +++ b/src/add-ons/translators/pcx/ConfigView.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2008, Jérôme Duval, korli@users.berlios.de. All rights reserved. + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "ConfigView.h" +#include "PCXTranslator.h" + +#include +#include + +#include +#include + + +ConfigView::ConfigView(const BRect &frame, uint32 resize, uint32 flags) + : BView(frame, "PCXTranslator Settings", resize, flags) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + font_height fontHeight; + be_bold_font->GetHeight(&fontHeight); + float height = fontHeight.descent + fontHeight.ascent + fontHeight.leading; + + BRect rect(10, 10, 200, 10 + height); + BStringView *stringView = new BStringView(rect, "title", "PCX Images"); + stringView->SetFont(be_bold_font); + stringView->ResizeToPreferred(); + AddChild(stringView); + + rect.OffsetBy(0, height + 10); + char version[256]; + sprintf(version, "Version %d.%d.%d, %s", + int(B_TRANSLATION_MAJOR_VERSION(PCX_TRANSLATOR_VERSION)), + int(B_TRANSLATION_MINOR_VERSION(PCX_TRANSLATOR_VERSION)), + int(B_TRANSLATION_REVISION_VERSION(PCX_TRANSLATOR_VERSION)), + __DATE__); + stringView = new BStringView(rect, "version", version); + stringView->ResizeToPreferred(); + AddChild(stringView); + + GetFontHeight(&fontHeight); + height = fontHeight.descent + fontHeight.ascent + fontHeight.leading; + + rect.OffsetBy(0, height + 5); + stringView = new BStringView(rect, "copyright", B_UTF8_COPYRIGHT "2008 Haiku Inc."); + stringView->ResizeToPreferred(); + AddChild(stringView); +} + + +ConfigView::~ConfigView() +{ +} + diff --git a/src/add-ons/translators/pcx/ConfigView.h b/src/add-ons/translators/pcx/ConfigView.h new file mode 100644 index 0000000000..8be5d04f18 --- /dev/null +++ b/src/add-ons/translators/pcx/ConfigView.h @@ -0,0 +1,19 @@ +/* + * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef CONFIG_VIEW_H +#define CONFIG_VIEW_H + + +#include + + +class ConfigView : public BView { + public: + ConfigView(const BRect &frame, uint32 resize = B_FOLLOW_ALL, + uint32 flags = B_WILL_DRAW); + virtual ~ConfigView(); +}; + +#endif /* CONFIG_VIEW_H */ diff --git a/src/add-ons/translators/pcx/Jamfile b/src/add-ons/translators/pcx/Jamfile new file mode 100644 index 0000000000..ede992989e --- /dev/null +++ b/src/add-ons/translators/pcx/Jamfile @@ -0,0 +1,27 @@ +SubDir HAIKU_TOP src add-ons translators pcx ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +# Include code from shared translator directory +SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons translators shared ] ; + +Translator PCXTranslator : + # PCXTranslator classes + main.cpp + PCXTranslator.cpp + ConfigView.cpp + PCX.cpp + + # shared classes + BaseTranslator.cpp + TranslatorSettings.cpp + TranslatorWindow.cpp + + : be translation + : true +; + +Package haiku-translationkit-cvs : + PCXTranslator + : boot home config add-ons Translators + ; diff --git a/src/add-ons/translators/pcx/PCX.cpp b/src/add-ons/translators/pcx/PCX.cpp new file mode 100644 index 0000000000..383aeb0b1b --- /dev/null +++ b/src/add-ons/translators/pcx/PCX.cpp @@ -0,0 +1,257 @@ +/* + * Copyright 2008, Jérôme Duval, korli@users.berlios.de. All rights reserved. + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "PCX.h" +#include "PCXTranslator.h" + +#include + +#include +#include +#include + + +//#define TRACE_PCX +#ifdef TRACE_PCX +# define TRACE(x...) printf(x) +#else +# define TRACE(x...) ; +#endif + + +using namespace PCX; + + +class TempAllocator { + public: + TempAllocator() : fMemory(NULL) {} + ~TempAllocator() { free(fMemory); } + + void *Allocate(size_t size) { return fMemory = malloc(size); } + + private: + void *fMemory; +}; + + +bool +pcx_header::IsValid() const +{ + TRACE("manufacturer:%u version:%u encoding:%u bitsPerPixel:%u nPlanes:%u bytesPerLine:%u\n", manufacturer, version, encoding, bitsPerPixel, nPlanes, bytesPerLine); + return manufacturer == 10 + && version == 5 + && encoding == 1 + && (bitsPerPixel == 1 || bitsPerPixel == 4 || bitsPerPixel == 8) + && (nPlanes == 1 || nPlanes == 3) + && (bitsPerPixel == 8 || nPlanes == 1) + && (bytesPerLine & 1) == 0; +} + + +void +pcx_header::SwapToHost() +{ + swap_data(B_UINT16_TYPE, this, sizeof(pcx_header), B_SWAP_LENDIAN_TO_HOST); +} + + +void +pcx_header::SwapFromHost() +{ + swap_data(B_UINT16_TYPE, this, sizeof(pcx_header), B_SWAP_HOST_TO_LENDIAN); +} + + +// #pragma mark - + + +static status_t +convert_data_to_bits(pcx_header &header, BPositionIO &source, + BPositionIO &target) +{ + uint16 bitsPerPixel = header.bitsPerPixel; + uint16 bytesPerLine = header.bytesPerLine; + uint16 width = header.xMax - header.xMin + 1; + uint16 height = header.yMax - header.yMin + 1; + uint16 nPlanes = header.nPlanes; + uint32 scanLineLength = nPlanes * bytesPerLine; + + // allocate buffers + TempAllocator scanLineAllocator; + TempAllocator paletteAllocator; + uint8 *scanLineData[height]; + uint8 *palette = (uint8 *)paletteAllocator.Allocate(3 * 256); + + for (uint32 row = 0; row < height; row++) { + TRACE("scanline %ld\n", row); + scanLineData[row] = (uint8 *)scanLineAllocator.Allocate(scanLineLength); + if (scanLineData[row] == NULL) + return B_NO_MEMORY; + uint8 *line = scanLineData[row]; + uint32 index = 0; + uint8 x; + do { + if (source.Read(&x, 1) != 1) + return B_IO_ERROR; + if ((x & 0xc0) == 0xc0) { + uint32 count = x & 0x3f; + if (index + count - 1 > scanLineLength) + return B_IO_ERROR; + if (source.Read(&x, 1) != 1) + return B_IO_ERROR; + for (uint32 i = 0; i < count; i++) + line[index++] = x; + } else { + line[index++] = x; + } + } while (index < scanLineLength); + } + + + if (bitsPerPixel == 8 && nPlanes == 1) { + TRACE("palette reading %p 8\n", palette); + uint8 x; + if (source.Read(&x, 1) != 1) + return B_IO_ERROR; + if (x != 12) + return B_IO_ERROR; + if (source.Read(palette, 256 * 3) != 256 * 3) + return B_IO_ERROR; + } else { + TRACE("palette reading %p palette\n", palette); + memcpy(palette, &header.paletteInfo, 48); + } + + uint8 alpha = 255; + if (bitsPerPixel == 1 && nPlanes == 1) { + TRACE("target writing 1\n"); + palette[0] = palette[1] = palette[2] = 0; + palette[3] = palette[4] = palette[5] = 0xff; + for (uint32 row = 0; row < height; row++) { + uint8 *line = scanLineData[row]; + uint8 mask[] = { 128, 64, 32, 16, 8, 4, 2, 1 }; + for (int i = 0; i < width; i++) { + bool isBit = ((line[i >> 3] & mask[i & 7]) != 0) ? true : false; + target.Write(&palette[!isBit ? 2 : 5], 1); + target.Write(&palette[!isBit ? 1 : 4], 1); + target.Write(&palette[!isBit ? 0 : 3], 1); + target.Write(&alpha, 1); + } + } + } else if (bitsPerPixel == 4 && nPlanes == 1) { + TRACE("target writing 4\n"); + for (uint32 row = 0; row < height; row++) { + uint8 *line = scanLineData[row]; + for (int i = 0; i < width; i++) { + uint16 index; + if ((i & 1) == 0) + index = (line[i >> 1] >> 4) & 15; + else + index = line[i >> 1] & 15; + TRACE("target writing 4 i %d index %d\n", i, index); + index += (index + index); + target.Write(&palette[index+2], 1); + target.Write(&palette[index+1], 1); + target.Write(&palette[index], 1); + target.Write(&alpha, 1); + } + } + } else if (bitsPerPixel == 8 && nPlanes == 1) { + TRACE("target writing 8\n"); + for (uint32 row = 0; row < height; row++) { + TRACE("target writing 8 row %ld\n", row); + uint8 *line = scanLineData[row]; + for (int i = 0; i < width; i++) { + uint16 index = line[i]; + index += (index + index); + target.Write(&palette[index+2], 1); + target.Write(&palette[index+1], 1); + target.Write(&palette[index], 1); + target.Write(&alpha, 1); + } + + } + } else { + TRACE("target writing raw\n"); + for (uint32 row = 0; row < height; row++) { + uint8 *line = scanLineData[row]; + for (int i = 0; i < width; i++) { + target.Write(&line[i + 2 * bytesPerLine], 1); + target.Write(&line[i + bytesPerLine], 1); + target.Write(&line[i], 1); + target.Write(&alpha, 1); + } + } + } + + return B_OK; +} + + +// #pragma mark - + + +status_t +PCX::identify(BMessage *settings, BPositionIO &stream, uint8 &type, int32 &bitsPerPixel) +{ + // read in the header + + pcx_header header; + if (stream.Read(&header, sizeof(pcx_header)) != (ssize_t)sizeof(pcx_header)) + return B_BAD_VALUE; + + header.SwapToHost(); + + // check header + + if (!header.IsValid()) + return B_BAD_VALUE; + + bitsPerPixel = header.bitsPerPixel; + + TRACE("PCX::identify OK\n"); + + return B_OK; +} + + +/** Converts an PCX image of any type into a B_RGBA32 B_TRANSLATOR_BITMAP. + */ + +status_t +PCX::convert_pcx_to_bits(BMessage *settings, BPositionIO &source, BPositionIO &target) +{ + pcx_header header; + if (source.Read(&header, sizeof(pcx_header)) != (ssize_t)sizeof(pcx_header)) + return B_BAD_VALUE; + + header.SwapToHost(); + + // check header + + if (!header.IsValid()) + return B_BAD_VALUE; + + uint16 width = header.xMax - header.xMin + 1; + uint16 height = header.yMax - header.yMin + 1; + + TranslatorBitmap bitsHeader; + bitsHeader.magic = B_TRANSLATOR_BITMAP; + bitsHeader.bounds.left = 0; + bitsHeader.bounds.top = 0; + bitsHeader.bounds.right = width - 1; + bitsHeader.bounds.bottom = height - 1; + bitsHeader.bounds.Set(0, 0, width - 1, height - 1); + bitsHeader.rowBytes = width * 4; + bitsHeader.colors = B_RGB32; + bitsHeader.dataSize = bitsHeader.rowBytes * height; + + // write out Be's Bitmap header + swap_data(B_UINT32_TYPE, &bitsHeader, sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN); + target.Write(&bitsHeader, sizeof(TranslatorBitmap)); + + return convert_data_to_bits(header, source, target); +} diff --git a/src/add-ons/translators/pcx/PCX.h b/src/add-ons/translators/pcx/PCX.h new file mode 100644 index 0000000000..9bc909045d --- /dev/null +++ b/src/add-ons/translators/pcx/PCX.h @@ -0,0 +1,58 @@ +/* + * Copyright 2008, Jérôme Duval, korli@users.berlios.de. All rights reserved. + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef PCX_H +#define PCX_H + + +#include +#include +#include + +class BMessage; + + +namespace PCX { + +struct pcx_header { + uint8 manufacturer; + uint8 version; + uint8 encoding; + uint8 bitsPerPixel; + uint16 xMin, yMin, xMax, yMax; + uint16 hDpi, vDpi; + uint8 colormap[48]; + uint8 reserved; + uint8 nPlanes; + uint16 bytesPerLine; + uint16 paletteInfo; + uint16 hScreenSize, vScreenSize; + uint8 filler[54]; + bool IsValid() const; + void SwapToHost(); + void SwapFromHost(); +} _PACKED; + + +struct rgba32_color { + uint8 blue; + uint8 green; + uint8 red; + uint8 alpha; + + inline bool + operator==(const rgba32_color& other) const + { + return red == other.red && green == other.green && blue == other.blue; + } +}; + + +extern status_t identify(BMessage *settings, BPositionIO &stream, uint8 &type, int32 &bitsPerPixel); +extern status_t convert_pcx_to_bits(BMessage *settings, BPositionIO &source, BPositionIO &target); + +} // namespace PCX + +#endif /* PCX_H */ diff --git a/src/add-ons/translators/pcx/PCXTranslator.cpp b/src/add-ons/translators/pcx/PCXTranslator.cpp new file mode 100644 index 0000000000..c2c60e56b7 --- /dev/null +++ b/src/add-ons/translators/pcx/PCXTranslator.cpp @@ -0,0 +1,174 @@ +/* + * Copyright 2008, Jérôme Duval, korli@users.berlios.de. All rights reserved. + * Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "PCXTranslator.h" +#include "ConfigView.h" +#include "PCX.h" + +#include +#include +#include + + +#define kPCXMimeType "image/x-pcx" + + +// The input formats that this translator supports. +translation_format sInputFormats[] = { + { + PCX_IMAGE_FORMAT, + B_TRANSLATOR_BITMAP, + PCX_IN_QUALITY, + PCX_IN_CAPABILITY, + kPCXMimeType, + "PCX image" + }/*, + { + B_TRANSLATOR_BITMAP, + B_TRANSLATOR_BITMAP, + BITS_IN_QUALITY, + BITS_IN_CAPABILITY, + "x-be-bitmap", + "Be Bitmap image" + },*/ +}; + +// The output formats that this translator supports. +translation_format sOutputFormats[] = { + /*{ + PCX_IMAGE_FORMAT, + B_TRANSLATOR_BITMAP, + PCX_OUT_QUALITY, + PCX_OUT_CAPABILITY, + kPCXMimeType, + "PCX image" + },*/ + { + B_TRANSLATOR_BITMAP, + B_TRANSLATOR_BITMAP, + BITS_OUT_QUALITY, + BITS_OUT_CAPABILITY, + "x-be-bitmap", + "Be Bitmap image" + }, +}; + +// Default settings for the Translator +static TranSetting sDefaultSettings[] = { + {B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false}, + {B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false} +}; + +const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format); +const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format); +const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting); + + +PCXTranslator::PCXTranslator() + : BaseTranslator("PCX Images", "PCX Translator", + PCX_TRANSLATOR_VERSION, + sInputFormats, kNumInputFormats, + sOutputFormats, kNumOutputFormats, + "PCXTranslator_Settings", + sDefaultSettings, kNumDefaultSettings, + B_TRANSLATOR_BITMAP, PCX_IMAGE_FORMAT) +{ +} + + +PCXTranslator::~PCXTranslator() +{ +} + + +status_t +PCXTranslator::DerivedIdentify(BPositionIO *stream, + const translation_format *format, BMessage *ioExtension, + translator_info *info, uint32 outType) +{ + if (!outType) + outType = B_TRANSLATOR_BITMAP; + if (outType != B_TRANSLATOR_BITMAP && outType != PCX_IMAGE_FORMAT) + return B_NO_TRANSLATOR; + + int32 bitsPerPixel; + uint8 type; + if (PCX::identify(ioExtension, *stream, type, bitsPerPixel) != B_OK) + return B_NO_TRANSLATOR; + + info->type = PCX_IMAGE_FORMAT; + info->group = B_TRANSLATOR_BITMAP; + info->quality = PCX_IN_QUALITY; + info->capability = PCX_IN_CAPABILITY; + snprintf(info->name, sizeof(info->name), "PCX %lu bit image", + bitsPerPixel); + strcpy(info->MIME, kPCXMimeType); + + return B_OK; +} + + +status_t +PCXTranslator::DerivedTranslate(BPositionIO *source, + const translator_info *info, BMessage *ioExtension, + uint32 outType, BPositionIO *target, int32 baseType) +{ + /*if (!outType) + outType = B_TRANSLATOR_BITMAP; + if (outType != B_TRANSLATOR_BITMAP && outType != PCX_IMAGE_FORMAT) + return B_NO_TRANSLATOR;*/ + + switch (baseType) { + /*case 1: + { + if (outType != PCX_IMAGE_FORMAT) + return B_NO_TRANSLATOR; + + // Source is in bits format - this has to be done here, because + // identify_bits_header() is a member of the BaseTranslator class... + TranslatorBitmap bitsHeader; + status_t status = identify_bits_header(source, NULL, &bitsHeader); + if (status != B_OK) + return status; + + return PCX::convert_bits_to_pcx(ioExtension, *source, bitsHeader, *target); + }*/ + + case 0: + { + // source is NOT in bits format + if (outType != B_TRANSLATOR_BITMAP) + return B_NO_TRANSLATOR; + + return PCX::convert_pcx_to_bits(ioExtension, *source, *target); + } + + default: + return B_NO_TRANSLATOR; + } +} + + +BView * +PCXTranslator::NewConfigView(TranslatorSettings *settings) +{ + return new ConfigView(BRect(0, 0, 225, 175)); +} + + +// #pragma mark - + + +BTranslator * +make_nth_translator(int32 n, image_id you, uint32 flags, ...) +{ + if (n != 0) + return NULL; + + return new PCXTranslator(); +} + diff --git a/src/add-ons/translators/pcx/PCXTranslator.h b/src/add-ons/translators/pcx/PCXTranslator.h new file mode 100644 index 0000000000..91fba4b882 --- /dev/null +++ b/src/add-ons/translators/pcx/PCXTranslator.h @@ -0,0 +1,59 @@ +/* + * Copyright 2008, Jérôme Duval, korli@users.berlios.de. All rights reserved. + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef PCX_TRANSLATOR_H +#define PCX_TRANSLATOR_H + + +#include "BaseTranslator.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PCX_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(0, 3, 0) +#define PCX_IMAGE_FORMAT 'PCX ' + +#define PCX_IN_QUALITY 0.5 +#define PCX_IN_CAPABILITY 0.5 +#define BITS_IN_QUALITY 1 +#define BITS_IN_CAPABILITY 1 + +#define PCX_OUT_QUALITY 0.8 +#define PCX_OUT_CAPABILITY 0.8 +#define BITS_OUT_QUALITY 1 +#define BITS_OUT_CAPABILITY 0.9 + + +class PCXTranslator : public BaseTranslator { + public: + PCXTranslator(); + + virtual status_t DerivedIdentify(BPositionIO *inSource, + const translation_format *inFormat, BMessage *ioExtension, + translator_info *outInfo, uint32 outType); + + virtual status_t DerivedTranslate(BPositionIO *inSource, + const translator_info *inInfo, BMessage *ioExtension, + uint32 outType, BPositionIO *outDestination, int32 baseType); + + virtual BView *NewConfigView(TranslatorSettings *settings); + + protected: + virtual ~PCXTranslator(); + // this is protected because the object is deleted by the + // Release() function instead of being deleted directly by + // the user + + private: +}; + +#endif /* PCX_TRANSLATOR_H */ diff --git a/src/add-ons/translators/pcx/main.cpp b/src/add-ons/translators/pcx/main.cpp new file mode 100644 index 0000000000..18d39d90e8 --- /dev/null +++ b/src/add-ons/translators/pcx/main.cpp @@ -0,0 +1,28 @@ +/* + * Copyright 2008, Jérôme Duval, korli@users.berlios.de. All rights reserved. + * Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "PCXTranslator.h" +#include "PCX.h" + +#include "TranslatorWindow.h" +#include + + +int +main(int /*argc*/, char **/*argv*/) +{ + BApplication app("application/x-vnd.haiku-pcx-translator"); + + status_t result; + result = LaunchTranslatorWindow(new PCXTranslator, "PCX Settings", BRect(0, 0, 225, 175)); + if (result != B_OK) + return 1; + + app.Run(); + return 0; +} +