JPEGTranslator - written by Shard

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2715 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Matthew Wilber 2003-02-15 15:06:44 +00:00
parent 1ed64d8a1f
commit 1d97f2e234
7 changed files with 2456 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,632 @@
/*
Copyright (c) 2002-2003, Marcin 'Shard' Konicki
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Name "Marcin Konicki", "Shard" or any combination of them,
must not be used to endorse or promote products derived from this
software without specific prior written permission from Marcin Konicki.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _JPEGTRANSLATOR_H_
#define _JPEGTRANSLATOR_H_
//----------------------------------------------------------------------------
//
// Include
//
//----------------------------------------------------------------------------
#include <Alert.h>
#include <Application.h>
#include <CheckBox.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Slider.h>
#include <StringView.h>
#include <TranslationKit.h>
#include <TranslatorAddOn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jpeglib.h>
//----------------------------------------------------------------------------
//
// Define & Global variables declaration
//
//----------------------------------------------------------------------------
// Settings
#define SETTINGS_FILE "OpenJPEGTranslator"
#define SETTINGS_PATH "/boot/home/config/settings"
// View messages
#define VIEW_MSG_SET_QUALITY 'JSCQ'
#define VIEW_MSG_SET_SMOOTHING 'JSCS'
#define VIEW_MSG_SET_PROGRESSIVE 'JSCP'
#define VIEW_MSG_SET_OPTIMIZECOLORS 'JSBQ'
#define VIEW_MSG_SET_SMALLERFILE 'JSSF'
#define VIEW_MSG_SET_GRAY1ASRGB24 'JSGR'
#define VIEW_MSG_SET_ALWAYSRGB32 'JSAC'
#define VIEW_MSG_SET_PHOTOSHOPCMYK 'JSPC'
#define VIEW_MSG_SET_SHOWREADERRORBOX 'JSEB'
// View labels
#define VIEW_LABEL_QUALITY "Output quality"
#define VIEW_LABEL_SMOOTHING "Output smoothing strength"
#define VIEW_LABEL_PROGRESSIVE "Use progressive compression"
#define VIEW_LABEL_OPTIMIZECOLORS "Prevent colors 'washing out'"
#define VIEW_LABEL_SMALLERFILE "Make file smaller (sligthtly worse quality)"
#define VIEW_LABEL_GRAY1ASRGB24 "Write Black&White images as RGB24"
#define VIEW_LABEL_ALWAYSRGB32 "Read Greyscale images as RGB32"
#define VIEW_LABEL_PHOTOSHOPCMYK "Use CMYK code with 0 for 100% ink coverage"
#define VIEW_LABEL_SHOWREADERRORBOX "Show warning messages"
// This will be used true if Settings are running, else false
extern bool AreSettingsRunning;
//----------------------------------------------------------------------------
//
// Classes
//
//----------------------------------------------------------------------------
//---------------------------------------------------
// Settings storage structure
//---------------------------------------------------
struct SETTINGS
{
// compression
uchar Smoothing; // default: 0
uchar Quality; // default: 95
bool Progressive; // default: true
bool OptimizeColors; // default: true
bool SmallerFile; // default: false only used if (OptimizeColors == true)
bool B_GRAY1_as_B_RGB24; // default: false if false gray1 converted to gray8, else to rgb24
// decompression
bool Always_B_RGB32; // default: true
bool PhotoshopCMYK; // default: true
bool ShowReadWarningBox; // default: true
};
//---------------------------------------------------
// Slider used in TranslatorView
// With status showing actual value
//---------------------------------------------------
class SSlider : public BSlider
{
public:
SSlider(BRect frame, const char *name, const char *label, BMessage *message, int32 minValue, int32 maxValue, orientation posture = B_HORIZONTAL, thumb_style thumbType = B_BLOCK_THUMB, uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, uint32 flags = B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS);
char* UpdateText() const;
void ResizeToPreferred();
private:
char statusLabel[12];
};
//---------------------------------------------------
// Basic view class with resizing to needed size
//---------------------------------------------------
class SView : public BView
{
public:
SView(const char *name, float x = 0, float y = 0)
:BView( BRect(x,y,x,y), name, B_FOLLOW_NONE, B_WILL_DRAW)
{
preferredWidth = 0;
preferredHeight = 0;
SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR));
SetFont(be_plain_font);
};
void GetPreferredSize(float *width, float *height)
{
*width = preferredWidth;
*height = preferredHeight;
}
inline float GetPreferredWidth() { return preferredWidth; };
inline float GetPreferredHeight() { return preferredHeight; };
inline void ResizePreferredBy(float width, float height) { preferredWidth += width; preferredHeight += height; };
inline void ResizeToPreferred() { ResizeTo(preferredWidth, preferredHeight); };
void AddChild(BView *child, BView *before = NULL)
{
BView::AddChild(child, before);
child->ResizeToPreferred();
BRect frame = child->Frame();
if (frame.right > preferredWidth)
preferredWidth = frame.right;
if (frame.bottom > preferredHeight)
preferredHeight = frame.bottom;
}
private:
float preferredWidth;
float preferredHeight;
};
//---------------------------------------------------
// Configuration view for reading settings
//---------------------------------------------------
class TranslatorReadView : public SView
{
public:
TranslatorReadView(const char *name, SETTINGS *settings, float x = 0, float y = 0);
void AttachedToWindow();
void MessageReceived(BMessage *message);
private:
SETTINGS *Settings;
BCheckBox *alwaysrgb32;
BCheckBox *photoshopCMYK;
BCheckBox *showerrorbox;
};
//---------------------------------------------------
// Configuration view for writing settings
//---------------------------------------------------
class TranslatorWriteView : public SView
{
public:
TranslatorWriteView(const char *name, SETTINGS *settings, float x = 0, float y = 0);
void AttachedToWindow();
void MessageReceived(BMessage *message);
private:
SETTINGS *Settings;
SSlider *quality;
SSlider *smoothing;
BCheckBox *progress;
BCheckBox *optimizecolors;
BCheckBox *smallerfile;
BCheckBox *gray1asrgb24;
};
//---------------------------------------------------
// About view
//---------------------------------------------------
class TranslatorAboutView : public SView
{
public:
TranslatorAboutView(const char *name, float x = 0, float y = 0);
};
//---------------------------------------------------
// Configuration view
//---------------------------------------------------
class TranslatorView : public SView
{
public:
TranslatorView(const char *name);
~TranslatorView() { AreSettingsRunning = false; };
void AttachedToWindow();
void Draw(BRect updateRect);
void MouseDown(BPoint where);
private:
SETTINGS Settings;
int32 tabWidth;
int32 tabHeight;
int32 activeChild;
};
//---------------------------------------------------
// Window used for configuration
//---------------------------------------------------
class TranslatorWindow : public BWindow
{
public:
TranslatorWindow(bool quit_on_close = true);
};
//----------------------------------------------------------------------------
//
// Functions :: Settings
//
//----------------------------------------------------------------------------
//---------------------------------------------------
// Make Settings to defaults
//---------------------------------------------------
inline void
LoadDefaultSettings(SETTINGS *Settings)
{
Settings->Smoothing = 0;
Settings->Quality = 95;
Settings->Progressive = true;
Settings->OptimizeColors = true;
Settings->SmallerFile = false;
Settings->B_GRAY1_as_B_RGB24 = false;
Settings->Always_B_RGB32 = true;
Settings->PhotoshopCMYK = true;
Settings->ShowReadWarningBox = true;
}
//---------------------------------------------------
// Save Settings to config file
//---------------------------------------------------
inline void
SaveSettings(SETTINGS *Settings)
{
// Make path to settings file
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) {
path.SetTo(SETTINGS_PATH);
path.Append(SETTINGS_FILE);
} else
path.Append(SETTINGS_FILE);
// Open settings file (create it if there's no file) and write settings
FILE *file = NULL;
if ((file = fopen( path.Path(), "wb+"))) {
fwrite(Settings, sizeof(SETTINGS), 1, file);
fclose(file);
}
}
//---------------------------------------------------
// Return true if Settings were run, false if not
//---------------------------------------------------
inline bool
SettingsChangedAlert()
{
// If settings view wasn't already initialized (settings not running)
// and user wants to run settings
if (!AreSettingsRunning && (new BAlert("Different settings file", "JPEG settings were set to default because of incompatible settings file.", "Configure settings", "OK", NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go() == 0) {
// Create settings window (with no quit on close!), launch it and wait until it's closed
status_t err;
TranslatorWindow *window = new TranslatorWindow(false);
window->Show();
wait_for_thread(window->Thread(), &err);
return true;
}
return false;
}
//---------------------------------------------------
// Load settings from config file
// If can't find it make them default and try to save
//---------------------------------------------------
inline void
LoadSettings(SETTINGS *Settings)
{
// Make path to settings file
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) {
path.SetTo(SETTINGS_PATH);
path.Append(SETTINGS_FILE);
} else
path.Append(SETTINGS_FILE);
// Open settings file (create it if there's no file) and write settings
FILE *file = NULL;
if ((file = fopen( path.Path(), "rb"))) {
if ( !fread(Settings, sizeof(SETTINGS), 1, file)) {
// Settings struct has changed size
// Load default settings, and Save them
fclose(file);
LoadDefaultSettings(Settings);
SaveSettings(Settings);
// Tell user settings were changed to default, and ask to run settings panel or not
if (SettingsChangedAlert())
// User configured settings, load them again
LoadSettings(Settings);
} else
fclose(file);
} else if ((file = fopen( path.Path(), "wb+"))) {
LoadDefaultSettings(Settings);
fwrite(Settings, sizeof(SETTINGS), 1, file);
fclose(file);
// Tell user settings were changed to default, and ask to run settings panel or not
if (SettingsChangedAlert())
// User configured settings, load them again
LoadSettings(Settings);
}
}
//----------------------------------------------------------------------------
//
// Functions
//
//----------------------------------------------------------------------------
//---------------------------------------------------
// "Initializers" for jpeglib
// based on default ones,
// modified to work on BPositionIO instead of FILE
//---------------------------------------------------
EXTERN(void) be_jpeg_stdio_src(j_decompress_ptr cinfo, BPositionIO *infile); // from "be_jdatasrc.cpp"
EXTERN(void) be_jpeg_stdio_dest(j_compress_ptr cinfo, BPositionIO *outfile); // from "be_jdatadst.cpp"
//---------------------------------------------------
// Error output functions
// based on the one from jerror.c
// modified to use settings
// (so user can decide to show dialog-boxes or not)
//---------------------------------------------------
EXTERN(struct jpeg_error_mgr *) be_jpeg_std_error (struct jpeg_error_mgr * err, SETTINGS * settings); // from "be_jerror.cpp"
//---------------------------------------------------
// Main functions of translator :)
//---------------------------------------------------
status_t Copy(BPositionIO *in, BPositionIO *out);
status_t Compress(BPositionIO *in, BPositionIO *out);
status_t Decompress(BPositionIO *in, BPositionIO *out);
status_t Error(j_common_ptr cinfo, status_t error = B_ERROR);
//---------------------------------------------------
// GRAY1 to GRAY8
//---------------------------------------------------
inline void
convert_from_gray1_to_gray8(uchar *in, uchar *out, int in_bytes)
{
const color_map * map = system_colors();
int32 index = 0;
int32 index2 = 0;
while (index < in_bytes) {
unsigned char c = in[index++];
for (int b = 128; b; b = b>>1) {
unsigned char color;
if (c & b)
color = 0;
else
color = 255;
out[index2++] = color;
}
}
}
//---------------------------------------------------
// GRAY1 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_gray1_to_24(uchar *in, uchar *out, int in_bytes)
{
const color_map * map = system_colors();
int32 index = 0;
int32 index2 = 0;
while (index < in_bytes) {
unsigned char c = in[index++];
for (int b = 128; b; b = b>>1) {
unsigned char color;
if (c & b)
color = 0;
else
color = 255;
out[index2++] = color;
out[index2++] = color;
out[index2++] = color;
}
}
}
//---------------------------------------------------
// CMAP8 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_cmap8_to_24(uchar *in, uchar *out, int in_bytes)
{
const color_map * map = system_colors();
int32 index = 0;
int32 index2 = 0;
while (index < in_bytes) {
rgb_color color = map->color_list[in[index++]];
out[index2++] = color.red;
out[index2++] = color.green;
out[index2++] = color.blue;
}
}
//---------------------------------------------------
// BGR 1:5:5:5 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_15_to_24(uchar *in, uchar *out, int in_bytes)
{
int32 index = 0;
int32 index2 = 0;
int16 in_pixel;
while (index < in_bytes) {
in_pixel = in[index] | (in[index+1] << 8);
index += 2;
out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12);
out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7);
out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
}
}
//---------------------------------------------------
// RGB 1:5:5:5 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_15b_to_24(uchar *in, uchar *out, int in_bytes)
{
int32 index = 0;
int32 index2 = 0;
int16 in_pixel;
while (index < in_bytes) {
in_pixel = in[index+1] | (in[index] << 8);
index += 2;
out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12);
out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7);
out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
}
}
//---------------------------------------------------
// BGR 5:6:5 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_16_to_24(uchar *in, uchar *out, int in_bytes)
{
int32 index = 0;
int32 index2 = 0;
int16 in_pixel;
while (index < in_bytes) {
in_pixel = in[index] | (in[index+1] << 8);
index += 2;
out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13);
out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9);
out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
}
}
//---------------------------------------------------
// RGB 5:6:5 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_16b_to_24(uchar *in, uchar *out, int in_bytes)
{
int32 index = 0;
int32 index2 = 0;
int16 in_pixel;
while (index < in_bytes) {
in_pixel = in[index+1] | (in[index] << 8);
index += 2;
out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13);
out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9);
out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
}
}
//---------------------------------------------------
// BGR 8:8:8 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_24_to_24(uchar *in, uchar *out, int in_bytes)
{
int32 index = 0;
int32 index2 = 0;
while (index < in_bytes) {
out[index2++] = in[index+2];
out[index2++] = in[index+1];
out[index2++] = in[index];
index+=3;
}
}
//---------------------------------------------------
// BGRx 8:8:8:8 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_32_to_24(uchar *in, uchar *out, int in_bytes)
{
int32 index = 0;
int32 index2 = 0;
while (index < in_bytes) {
out[index2++] = in[index+2];
out[index2++] = in[index+1];
out[index2++] = in[index];
index+=4;
}
}
//---------------------------------------------------
// xRGB 8:8:8:8 to RGB 8:8:8
//---------------------------------------------------
inline void
convert_from_32b_to_24(uchar *in, uchar *out, int in_bytes)
{
int32 index = 0;
int32 index2 = 0;
while (index < in_bytes) {
index++;
out[index2++] = in[index++];
out[index2++] = in[index++];
out[index2++] = in[index++];
}
}
//---------------------------------------------------
// CMYK 8:8:8:8 to RGB32 8:8:8:8
// Version for Adobe Photoshop files (0 for 100% ink)
//---------------------------------------------------
inline void
convert_from_CMYK_to_32_photoshop (uchar *in, uchar *out, int out_bytes)
{
int32 index = 0;
int32 index2 = 0;
int32 black = 0;
while (index < out_bytes) {
black = in[index2+3];
out[index++] = in[index2+2]*black/255;
out[index++] = in[index2+1]*black/255;
out[index++] = in[index2]*black/255;
out[index++] = 255;
index2 += 4;
}
}
//---------------------------------------------------
// CMYK 8:8:8:8 to RGB32 8:8:8:8
// !!! UNTESTED !!!
//---------------------------------------------------
inline void
convert_from_CMYK_to_32 (uchar *in, uchar *out, int out_bytes)
{
int32 index = 0;
int32 index2 = 0;
int32 black = 0;
while (index < out_bytes) {
black = 255 - in[index2+3];
out[index++] = ((255-in[index2+2])*black)/255;
out[index++] = ((255-in[index2+1])*black)/255;
out[index++] = ((255-in[index2])*black)/255;
out[index++] = 255;
index2 += 4;
}
}
//---------------------------------------------------
// RGB24 8:8:8 to xRGB 8:8:8:8
//---------------------------------------------------
inline void
convert_from_24_to_32(uchar *in, uchar *out, int out_bytes)
{
int32 index = 0;
int32 index2 = 0;
while (index < out_bytes) {
out[index++] = in[index2+2];
out[index++] = in[index2+1];
out[index++] = in[index2];
out[index++] = 255;
index2 += 3;
}
}
#endif // _JPEGTRANSLATOR_H_

View File

@ -0,0 +1,78 @@
SubDir OBOS_TOP src add-ons translators jpegtranslator ;
# Let Jam know where to find some of our source files
SEARCH_SOURCE += [ FDirName $(SUBDIR) libjpeg ] ;
Translator JPEGTranslator :
# JPEGTranslator
be_jdatadst.cpp
be_jdatasrc.cpp
be_jerror.cpp
JPEGTranslator.cpp
# libjpeg
jcapimin.c
jcapistd.c
jccoefct.c
jccolor.c
jcdctmgr.c
jcdiffct.c
jchuff.c
jcinit.c
jclhuff.c
jclossls.c
jclossy.c
jcmainct.c
jcmarker.c
jcmaster.c
jcodec.c
jcomapi.c
jcparam.c
jcphuff.c
jcpred.c
jcprepct.c
jcsample.c
jcscale.c
jcshuff.c
jctrans.c
jdapimin.c
jdapistd.c
jdatadst.c
jdatasrc.c
jdcoefct.c
jdcolor.c
jddctmgr.c
jddiffct.c
jdhuff.c
jdinput.c
jdlhuff.c
jdlossls.c
jdlossy.c
jdmainct.c
jdmarker.c
jdmaster.c
jdmerge.c
jdphuff.c
jdpostct.c
jdpred.c
jdsample.c
jdscale.c
jdshuff.c
jdtrans.c
jerror.c
jfdctflt.c
jfdctfst.c
jfdctint.c
jidctflt.c
jidctfst.c
jidctint.c
jidctred.c
jmemmgr.c
jmemnobs.c
jquant1.c
jquant2.c
jutils.c
;
LinkSharedOSLibs JPEGTranslator : be translation ;

View File

@ -0,0 +1,49 @@
JPEG Translator v1.1.1
©2002-2003 by Marcin 'Shard' Konicki
shard@beosjournal.org
http://shard.beosjournal.org
TranslationKit add-on for JPEG files. Has more options and can write jpg files with far much better quality than default one in BeOS r5.
It's based on libjpeg by IJG (http://www.ijg.org/files/), with patch to support "lossless" (really bad and misinformative name) encoded images by Ken Murchison (http://www.oceana.com/ftp/ljpeg/). I also used some color space conversion routines by Magnus Hellman found in TestBMPTranslator (http://www.bebits.com/app/802).
A little explanation ("what is what"):
To install translator drag & drop "JPEGTranslator" file onto "Drag JPEGTranslator here" folder.
When You run DataTranslations application and go to JPEG Translator settings, You'll see 3 tabs:
- Write
- Read
- About
Write tab shows settings used for writing jpeg files:
Output quality let's You chose how much output image will be similar to original image. Less quality means worse output image. There is a scale from 0% to 100% but in reality 95% is maximum quality, more percent only will make output file bigger without any noticable image quality changes.
Output smoothing strength let's You chose how much blurred output image will be. It sometimes helps to make it 3-5% smoothed when You use smaller quality. Depends on what that image will be used for of course.
Use progressive compression will make output file to be loaded progressively on webpage, ie: first client will see very big pixels, than after each "rescan" of image it will get better and better up to full image. This option usually makes output file smaller.
Prevent colors 'washing out' makes output file bigger but with full colors from original file. If You made some jpg files on BeOS before, You've probably noticed colors were "washed out". This option prevents that :)
Make file smaller (slightly worse quality) is available only with previous option set on. It will make outout file smaller but with a little worse quality (from what i've seen it's like difference between quality of 95% and 93% - but it's highly subjective opinion. Some people who have seen images generated with this option said they're the same as 95%, others said they're mych worse :)
Write Black&White images as RGB24 tells translator to write B_GRAY1 images as rgb jpeg. If it's turned off, translator will write them as greyscale.
Read tab shows settings used for reading jpeg files:
Read Greyscale images as RGB32 makes translator to read greyscale images as they have been color. Most applications on BeOS can't "understand" greyscale images from translation properly (i've tried ShowImage, ViewImage, Gobe Productive 2, NetPositive, and ArtPaint - only NetPositive can understand them).
Use CMYK code with 0 for 100% ink coverage is to let You read properly CMYK color space jpeg images generated by Photoshop.
Note: CMYK support is only basic - just to give You idea how image can look. Exact translation will be available someday in the future maybe.
Show warning messages lets You turn off read warnings. There are damaged/wrongly written jpg files which can be rendered ok, or almost ok. With this option checked You'll not be bugged about missing few bytes in some image anymore ;]
About tab shows info about this translator.
Shard

View File

@ -0,0 +1,172 @@
/*
Copyright (c) 2002-2003, Marcin 'Shard' Konicki
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Name "Marcin Konicki", "Shard" or any combination of them,
must not be used to endorse or promote products derived from this
software without specific prior written permission from Marcin Konicki.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Modified jdatadst.c from libjpeg
to use BPoistionIO instead of FILE
*/
// Be Headers
#include <DataIO.h>
#include <stdio.h>
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include <jpeglib.h>
#include <jerror.h>
// instead of including jinclude - thx to it translator can be compiled
// without sources to jpeglib
#define SIZEOF(object) ((size_t) sizeof(object))
/* Expanded data destination object for stdio output */
typedef struct {
struct jpeg_destination_mgr pub; /* public fields */
BPositionIO * outfile; /* target stream */
JOCTET * buffer; /* start of buffer */
} be_destination_mgr;
typedef be_destination_mgr * be_dest_ptr;
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
/*
* Initialize destination --- called by jpeg_start_compress
* before any data is actually written.
*/
METHODDEF(void)
be_init_destination (j_compress_ptr cinfo)
{
be_dest_ptr dest = (be_dest_ptr) cinfo->dest;
/* Allocate the output buffer --- it will be released when done with image */
dest->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (OUTPUT_BUF_SIZE * SIZEOF(JOCTET)));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
/*
* Empty the output buffer --- called whenever buffer fills up.
*
* In typical applications, this should write the entire output buffer
* (ignoring the current state of next_output_byte & free_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been dumped.
*
* In applications that need to be able to suspend compression due to output
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
* In this situation, the compressor will return to its caller (possibly with
* an indication that it has not accepted all the supplied scanlines). The
* application should resume compression after it has made more room in the
* output buffer. Note that there are substantial restrictions on the use of
* suspension --- see the documentation.
*
* When suspending, the compressor will back up to a convenient restart point
* (typically the start of the current MCU). next_output_byte & free_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point will be regenerated after resumption, so do not
* write it out when emptying the buffer externally.
*/
METHODDEF(boolean)
be_empty_output_buffer (j_compress_ptr cinfo)
{
be_dest_ptr dest = (be_dest_ptr) cinfo->dest;
if (dest->outfile->Write(dest->buffer, OUTPUT_BUF_SIZE) != (ssize_t) OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
return TRUE;
}
/*
* Terminate destination --- called by jpeg_finish_compress
* after all data has been written. Usually needs to flush buffer.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF(void)
be_term_destination (j_compress_ptr cinfo)
{
be_dest_ptr dest = (be_dest_ptr) cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
if (datacount > 0) {
if (dest->outfile->Write(dest->buffer, datacount) != (ssize_t) datacount)
ERREXIT(cinfo, JERR_FILE_WRITE);
}
}
/*
* Prepare for output to a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing compression.
*/
GLOBAL(void)
be_jpeg_stdio_dest (j_compress_ptr cinfo, BPositionIO * outfile)
{
be_dest_ptr dest;
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(be_destination_mgr));
}
dest = (be_dest_ptr) cinfo->dest;
dest->pub.init_destination = be_init_destination;
dest->pub.empty_output_buffer = be_empty_output_buffer;
dest->pub.term_destination = be_term_destination;
dest->outfile = outfile;
}

View File

@ -0,0 +1,240 @@
/*
Copyright (c) 2002-2003, Marcin 'Shard' Konicki
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Name "Marcin Konicki", "Shard" or any combination of them,
must not be used to endorse or promote products derived from this
software without specific prior written permission from Marcin Konicki.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Modified jdatasrc.c from libjpeg
to use BPoistionIO instead of FILE
*/
//Be headers
#include <DataIO.h>
#include <stdio.h>
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include <jpeglib.h>
#include <jerror.h>
// instead of including jinclude - thx to it translator can be compiled
// without sources to jpeglib
#define SIZEOF(object) ((size_t) sizeof(object))
/* Expanded data source object for stdio input */
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
BPositionIO * infile; /* source stream */
JOCTET * buffer; /* start of buffer */
boolean start_of_file; /* have we gotten any data yet? */
} be_source_mgr;
typedef be_source_mgr * be_src_ptr;
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
METHODDEF(void)
be_init_source (j_decompress_ptr cinfo)
{
be_src_ptr src = (be_src_ptr) cinfo->src;
/* We reset the empty-input-file flag for each image,
* but we don't clear the input buffer.
* This is correct behavior for reading a series of images from one source.
*/
src->start_of_file = TRUE;
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*
* In typical applications, this should read fresh data into the buffer
* (ignoring the current state of next_input_byte & bytes_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been reloaded. It is not necessary to
* fill the buffer entirely, only to obtain at least one more byte.
*
* There is no such thing as an EOF return. If the end of the file has been
* reached, the routine has a choice of ERREXIT() or inserting fake data into
* the buffer. In most cases, generating a warning message and inserting a
* fake EOI marker is the best course of action --- this will allow the
* decompressor to output however much of the image is there. However,
* the resulting error message is misleading if the real problem is an empty
* input file, so we handle that case specially.
*
* In applications that need to be able to suspend compression due to input
* not being available yet, a FALSE return indicates that no more data can be
* obtained right now, but more may be forthcoming later. In this situation,
* the decompressor will return to its caller (with an indication of the
* number of scanlines it has read, if any). The application should resume
* decompression after it has loaded more data into the input buffer. Note
* that there are substantial restrictions on the use of suspension --- see
* the documentation.
*
* When suspending, the decompressor will back up to a convenient restart point
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point must be rescanned after resumption, so move it to
* the front of the buffer rather than discarding it.
*/
METHODDEF(boolean)
be_fill_input_buffer (j_decompress_ptr cinfo)
{
be_src_ptr src = (be_src_ptr) cinfo->src;
size_t nbytes;
nbytes = src->infile->Read(src->buffer, INPUT_BUF_SIZE);
if (nbytes <= 0) {
if (src->start_of_file) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
src->buffer[0] = (JOCTET) 0xFF;
src->buffer[1] = (JOCTET) JPEG_EOI;
nbytes = 2;
}
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = nbytes;
src->start_of_file = FALSE;
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* Writers of suspendable-input applications must note that skip_input_data
* is not granted the right to give a suspension return. If the skip extends
* beyond the data currently in the buffer, the buffer can be marked empty so
* that the next read will cause a fill_input_buffer call that can suspend.
* Arranging for additional bytes to be discarded before reloading the input
* buffer is the application writer's problem.
*/
METHODDEF(void)
be_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
be_src_ptr src = (be_src_ptr) cinfo->src;
/* Just a dumb implementation for now. Could use fseek() except
* it doesn't work on pipes. Not clear that being smart is worth
* any trouble anyway --- large skips are infrequent.
*/
if (num_bytes > 0) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) be_fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* An additional method that can be provided by data source modules is the
* resync_to_restart method for error recovery in the presence of RST markers.
* For the moment, this source module just uses the default resync method
* provided by the JPEG library. That method assumes that no backtracking
* is possible.
*/
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF(void)
be_term_source (j_decompress_ptr cinfo)
{
/* no work necessary here */
}
/*
* Prepare for input from a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing decompression.
*/
GLOBAL(void)
be_jpeg_stdio_src (j_decompress_ptr cinfo, BPositionIO * infile)
{
be_src_ptr src;
/* The source object and input buffer are made permanent so that a series
* of JPEG images can be read from the same file by calling jpeg_stdio_src
* only before the first one. (If we discarded the buffer at the end of
* one image, we'd likely lose the start of the next one.)
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(be_source_mgr));
src = (be_src_ptr) cinfo->src;
src->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
INPUT_BUF_SIZE * SIZEOF(JOCTET));
}
src = (be_src_ptr) cinfo->src;
src->pub.init_source = be_init_source;
src->pub.fill_input_buffer = be_fill_input_buffer;
src->pub.skip_input_data = be_skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = be_term_source;
src->infile = infile;
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
}

View File

@ -0,0 +1,116 @@
/*
Copyright (c) 2002-2003, Marcin 'Shard' Konicki
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Name "Marcin Konicki", "Shard" or any combination of them,
must not be used to endorse or promote products derived from this
software without specific prior written permission from Marcin Konicki.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Modified jerror.c from libjpeg
to make it possible to turn on/off error dialog-box
only two functions modified, rest is used from original error handling code
*/
// Be headers
#include <Alert.h>
#include <stdio.h>
// JPEG headers
#include <jpeglib.h>
#include <jconfig.h>
#include <jerror.h>
// JPEGTtanslator settings header to get SETTINGS struct
#include "JPEGTranslator.h"
// Since Translator doesn't use it's own error table, we can use error_mgr's
// variables to store some usefull data.
// last_addon_message (as ShowReadWarnings) is used for storing SETTINGS->ShowReadWarningBox value
#define ShowReadWarnings last_addon_message
/*
* Error exit handler: must not return to caller.
*/
GLOBAL(void)
be_error_exit (j_common_ptr cinfo)
{
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
/* show error message */
(new BAlert("JPEG Library Error", buffer, "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
/* Let the memory manager delete any temp files before we die */
jpeg_destroy(cinfo);
exit(B_ERROR);
}
/*
* Actual output of an error or trace message.
*/
GLOBAL(void)
be_output_message (j_common_ptr cinfo)
{
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
/* If it's compressing or decompressing and user turned messages on */
if (!cinfo->is_decompressor || cinfo->err->ShowReadWarnings)
/* show warning message */
(new BAlert("JPEG Library Warning", buffer, "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
}
/*
* Fill in the standard error-handling methods in a jpeg_error_mgr object.
* Since Translator doesn't use it's own error table, we can use error_mgr's
* variables to store some usefull data.
* last_addon_message (as ShowReadWarnings) is used for storing SETTINGS->ShowReadWarningBox value
*/
GLOBAL(struct jpeg_error_mgr *)
be_jpeg_std_error (struct jpeg_error_mgr * err, SETTINGS *settings)
{
jpeg_std_error(err);
err->error_exit = be_error_exit;
err->output_message = be_output_message;
err->ShowReadWarnings = settings->ShowReadWarningBox;
return err;
}