* Made the translator more relaxed wrt to corrupted files - this makes it
loading the GMARBLES.PCX test file just fine. * Automatic whitespace cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34440 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,19 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Jérôme Duval, [email protected]. All rights reserved.
|
* Copyright 2008, Jérôme Duval, [email protected]. All rights reserved.
|
||||||
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2005-2009, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "StreamBuffer.h"
|
|
||||||
#include "PCX.h"
|
|
||||||
#include "PCXTranslator.h"
|
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
#include "PCX.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
|
||||||
|
#include "StreamBuffer.h"
|
||||||
|
#include "PCXTranslator.h"
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_PCX
|
//#define TRACE_PCX
|
||||||
#ifdef TRACE_PCX
|
#ifdef TRACE_PCX
|
||||||
@@ -38,16 +40,16 @@ class TempAllocator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pcx_header::IsValid() const
|
pcx_header::IsValid() const
|
||||||
{
|
{
|
||||||
TRACE("manufacturer:%u version:%u encoding:%u bitsPerPixel:%u nPlanes:%u bytesPerLine:%u\n", manufacturer, version, encoding, bitsPerPixel, nPlanes, bytesPerLine);
|
TRACE("manufacturer:%u version:%u encoding:%u bitsPerPixel:%u numPlanes:%u bytesPerLine:%u\n", manufacturer, version, encoding, bitsPerPixel, numPlanes, bytesPerLine);
|
||||||
return manufacturer == 10
|
return manufacturer == 10
|
||||||
&& version == 5
|
&& version == 5
|
||||||
&& encoding == 1
|
&& encoding == 1
|
||||||
&& (bitsPerPixel == 1 || bitsPerPixel == 4 || bitsPerPixel == 8)
|
&& (bitsPerPixel == 1 || bitsPerPixel == 4 || bitsPerPixel == 8)
|
||||||
&& (nPlanes == 1 || nPlanes == 3)
|
&& (numPlanes == 1 || numPlanes == 3)
|
||||||
&& (bitsPerPixel == 8 || nPlanes == 1)
|
&& (bitsPerPixel == 8 || numPlanes == 1)
|
||||||
&& (bytesPerLine & 1) == 0;
|
&& (bytesPerLine & 1) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,16 +77,17 @@ convert_data_to_bits(pcx_header &header, StreamBuffer &source,
|
|||||||
{
|
{
|
||||||
uint16 bitsPerPixel = header.bitsPerPixel;
|
uint16 bitsPerPixel = header.bitsPerPixel;
|
||||||
uint16 bytesPerLine = header.bytesPerLine;
|
uint16 bytesPerLine = header.bytesPerLine;
|
||||||
uint16 width = header.xMax - header.xMin + 1;
|
uint32 width = header.xMax - header.xMin + 1;
|
||||||
uint16 height = header.yMax - header.yMin + 1;
|
uint32 height = header.yMax - header.yMin + 1;
|
||||||
uint16 nPlanes = header.nPlanes;
|
uint16 numPlanes = header.numPlanes;
|
||||||
uint32 scanLineLength = nPlanes * bytesPerLine;
|
uint32 scanLineLength = numPlanes * bytesPerLine;
|
||||||
|
|
||||||
// allocate buffers
|
// allocate buffers
|
||||||
TempAllocator scanLineAllocator;
|
TempAllocator scanLineAllocator;
|
||||||
TempAllocator paletteAllocator;
|
TempAllocator paletteAllocator;
|
||||||
uint8 *scanLineData[height];
|
uint8 *scanLineData[height];
|
||||||
uint8 *palette = (uint8 *)paletteAllocator.Allocate(3 * 256);
|
uint8 *palette = (uint8 *)paletteAllocator.Allocate(3 * 256);
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
for (uint32 row = 0; row < height; row++) {
|
for (uint32 row = 0; row < height; row++) {
|
||||||
TRACE("scanline %ld\n", row);
|
TRACE("scanline %ld\n", row);
|
||||||
@@ -95,46 +98,68 @@ convert_data_to_bits(pcx_header &header, StreamBuffer &source,
|
|||||||
uint32 index = 0;
|
uint32 index = 0;
|
||||||
uint8 x;
|
uint8 x;
|
||||||
do {
|
do {
|
||||||
if (source.Read(&x, 1) != 1)
|
if (source.Read(&x, 1) != 1) {
|
||||||
return B_IO_ERROR;
|
status = B_IO_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if ((x & 0xc0) == 0xc0) {
|
if ((x & 0xc0) == 0xc0) {
|
||||||
uint32 count = x & 0x3f;
|
uint32 count = x & 0x3f;
|
||||||
if (index + count - 1 > scanLineLength)
|
if (index + count - 1 > scanLineLength) {
|
||||||
return B_IO_ERROR;
|
status = B_BAD_DATA;
|
||||||
if (source.Read(&x, 1) != 1)
|
break;
|
||||||
return B_IO_ERROR;
|
}
|
||||||
|
if (source.Read(&x, 1) != 1) {
|
||||||
|
status = B_IO_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
for (uint32 i = 0; i < count; i++)
|
for (uint32 i = 0; i < count; i++)
|
||||||
line[index++] = x;
|
line[index++] = x;
|
||||||
} else {
|
} else {
|
||||||
line[index++] = x;
|
line[index++] = x;
|
||||||
}
|
}
|
||||||
} while (index < scanLineLength);
|
} while (index < scanLineLength);
|
||||||
|
|
||||||
|
if (status != B_OK) {
|
||||||
|
// If we've already read more than a third of the file, display
|
||||||
|
// what we have, ie. ignore the error.
|
||||||
|
if (row < height / 3)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
memset(scanLineData + row, 0, sizeof(uint8*) * (height - row));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitsPerPixel == 8 && numPlanes == 1) {
|
||||||
if (bitsPerPixel == 8 && nPlanes == 1) {
|
|
||||||
TRACE("palette reading %p 8\n", palette);
|
TRACE("palette reading %p 8\n", palette);
|
||||||
uint8 x;
|
uint8 x;
|
||||||
if (source.Read(&x, 1) != 1)
|
if (status != B_OK || source.Read(&x, 1) != 1 || x != 12) {
|
||||||
|
// Try again by repositioning the file stream
|
||||||
|
if (source.Seek(-3 * 256 - 1, SEEK_END) < 0)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
if (source.Read(&x, 1) != 1)
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
if (x != 12)
|
if (x != 12)
|
||||||
return B_IO_ERROR;
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
if (source.Read(palette, 256 * 3) != 256 * 3)
|
if (source.Read(palette, 256 * 3) != 256 * 3)
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
} else {
|
} else {
|
||||||
TRACE("palette reading %p palette\n", palette);
|
TRACE("palette reading %p palette\n", palette);
|
||||||
memcpy(palette, &header.paletteInfo, 48);
|
memcpy(palette, &header.paletteInfo, 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 alpha = 255;
|
uint8 alpha = 255;
|
||||||
if (bitsPerPixel == 1 && nPlanes == 1) {
|
if (bitsPerPixel == 1 && numPlanes == 1) {
|
||||||
TRACE("target writing 1\n");
|
TRACE("target writing 1\n");
|
||||||
palette[0] = palette[1] = palette[2] = 0;
|
palette[0] = palette[1] = palette[2] = 0;
|
||||||
palette[3] = palette[4] = palette[5] = 0xff;
|
palette[3] = palette[4] = palette[5] = 0xff;
|
||||||
for (uint32 row = 0; row < height; row++) {
|
for (uint32 row = 0; row < height; row++) {
|
||||||
uint8 *line = scanLineData[row];
|
uint8 *line = scanLineData[row];
|
||||||
|
if (line == NULL)
|
||||||
|
break;
|
||||||
uint8 mask[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
uint8 mask[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
||||||
for (int i = 0; i < width; i++) {
|
for (uint32 i = 0; i < width; i++) {
|
||||||
bool isBit = ((line[i >> 3] & mask[i & 7]) != 0) ? true : false;
|
bool isBit = ((line[i >> 3] & mask[i & 7]) != 0) ? true : false;
|
||||||
target.Write(&palette[!isBit ? 2 : 5], 1);
|
target.Write(&palette[!isBit ? 2 : 5], 1);
|
||||||
target.Write(&palette[!isBit ? 1 : 4], 1);
|
target.Write(&palette[!isBit ? 1 : 4], 1);
|
||||||
@@ -142,11 +167,13 @@ convert_data_to_bits(pcx_header &header, StreamBuffer &source,
|
|||||||
target.Write(&alpha, 1);
|
target.Write(&alpha, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (bitsPerPixel == 4 && nPlanes == 1) {
|
} else if (bitsPerPixel == 4 && numPlanes == 1) {
|
||||||
TRACE("target writing 4\n");
|
TRACE("target writing 4\n");
|
||||||
for (uint32 row = 0; row < height; row++) {
|
for (uint32 row = 0; row < height; row++) {
|
||||||
uint8 *line = scanLineData[row];
|
uint8 *line = scanLineData[row];
|
||||||
for (int i = 0; i < width; i++) {
|
if (line == NULL)
|
||||||
|
break;
|
||||||
|
for (uint32 i = 0; i < width; i++) {
|
||||||
uint16 index;
|
uint16 index;
|
||||||
if ((i & 1) == 0)
|
if ((i & 1) == 0)
|
||||||
index = (line[i >> 1] >> 4) & 15;
|
index = (line[i >> 1] >> 4) & 15;
|
||||||
@@ -160,12 +187,14 @@ convert_data_to_bits(pcx_header &header, StreamBuffer &source,
|
|||||||
target.Write(&alpha, 1);
|
target.Write(&alpha, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (bitsPerPixel == 8 && nPlanes == 1) {
|
} else if (bitsPerPixel == 8 && numPlanes == 1) {
|
||||||
TRACE("target writing 8\n");
|
TRACE("target writing 8\n");
|
||||||
for (uint32 row = 0; row < height; row++) {
|
for (uint32 row = 0; row < height; row++) {
|
||||||
TRACE("target writing 8 row %ld\n", row);
|
TRACE("target writing 8 row %ld\n", row);
|
||||||
uint8 *line = scanLineData[row];
|
uint8 *line = scanLineData[row];
|
||||||
for (int i = 0; i < width; i++) {
|
if (line == NULL)
|
||||||
|
break;
|
||||||
|
for (uint32 i = 0; i < width; i++) {
|
||||||
uint16 index = line[i];
|
uint16 index = line[i];
|
||||||
index += (index + index);
|
index += (index + index);
|
||||||
target.Write(&palette[index+2], 1);
|
target.Write(&palette[index+2], 1);
|
||||||
@@ -173,13 +202,15 @@ convert_data_to_bits(pcx_header &header, StreamBuffer &source,
|
|||||||
target.Write(&palette[index], 1);
|
target.Write(&palette[index], 1);
|
||||||
target.Write(&alpha, 1);
|
target.Write(&alpha, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TRACE("target writing raw\n");
|
TRACE("target writing raw\n");
|
||||||
for (uint32 row = 0; row < height; row++) {
|
for (uint32 row = 0; row < height; row++) {
|
||||||
uint8 *line = scanLineData[row];
|
uint8 *line = scanLineData[row];
|
||||||
for (int i = 0; i < width; i++) {
|
if (line == NULL)
|
||||||
|
break;
|
||||||
|
for (uint32 i = 0; i < width; i++) {
|
||||||
target.Write(&line[i + 2 * bytesPerLine], 1);
|
target.Write(&line[i + 2 * bytesPerLine], 1);
|
||||||
target.Write(&line[i + bytesPerLine], 1);
|
target.Write(&line[i + bytesPerLine], 1);
|
||||||
target.Write(&line[i], 1);
|
target.Write(&line[i], 1);
|
||||||
@@ -187,7 +218,7 @@ convert_data_to_bits(pcx_header &header, StreamBuffer &source,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,9 +241,9 @@ PCX::identify(BMessage *settings, BPositionIO &stream, uint8 &type, int32 &bitsP
|
|||||||
|
|
||||||
if (!header.IsValid())
|
if (!header.IsValid())
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
bitsPerPixel = header.bitsPerPixel;
|
bitsPerPixel = header.bitsPerPixel;
|
||||||
|
|
||||||
TRACE("PCX::identify OK\n");
|
TRACE("PCX::identify OK\n");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -228,7 +259,7 @@ PCX::convert_pcx_to_bits(BMessage *settings, BPositionIO &source, BPositionIO &t
|
|||||||
StreamBuffer sourceBuf(&source, 2048);
|
StreamBuffer sourceBuf(&source, 2048);
|
||||||
if (sourceBuf.InitCheck() != B_OK)
|
if (sourceBuf.InitCheck() != B_OK)
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
|
|
||||||
pcx_header header;
|
pcx_header header;
|
||||||
if (sourceBuf.Read(&header, sizeof(pcx_header)) != (ssize_t)sizeof(pcx_header))
|
if (sourceBuf.Read(&header, sizeof(pcx_header)) != (ssize_t)sizeof(pcx_header))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -239,10 +270,10 @@ PCX::convert_pcx_to_bits(BMessage *settings, BPositionIO &source, BPositionIO &t
|
|||||||
|
|
||||||
if (!header.IsValid())
|
if (!header.IsValid())
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
uint16 width = header.xMax - header.xMin + 1;
|
uint16 width = header.xMax - header.xMin + 1;
|
||||||
uint16 height = header.yMax - header.yMin + 1;
|
uint16 height = header.yMax - header.yMin + 1;
|
||||||
|
|
||||||
TranslatorBitmap bitsHeader;
|
TranslatorBitmap bitsHeader;
|
||||||
bitsHeader.magic = B_TRANSLATOR_BITMAP;
|
bitsHeader.magic = B_TRANSLATOR_BITMAP;
|
||||||
bitsHeader.bounds.left = 0;
|
bitsHeader.bounds.left = 0;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ struct pcx_header {
|
|||||||
uint16 hDpi, vDpi;
|
uint16 hDpi, vDpi;
|
||||||
uint8 colormap[48];
|
uint8 colormap[48];
|
||||||
uint8 reserved;
|
uint8 reserved;
|
||||||
uint8 nPlanes;
|
uint8 numPlanes;
|
||||||
uint16 bytesPerLine;
|
uint16 bytesPerLine;
|
||||||
uint16 paletteInfo;
|
uint16 paletteInfo;
|
||||||
uint16 hScreenSize, vScreenSize;
|
uint16 hScreenSize, vScreenSize;
|
||||||
|
|||||||
Reference in New Issue
Block a user