From 9fe1a5533f99ee55973be6058647826e43bbc998 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Thu, 8 Nov 2012 11:21:35 +0100 Subject: [PATCH 1/9] Fix typo in zlib symlink. Should resolve #9126. --- build/jam/HaikuImage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index c9cc3fc6f5..81fddaefd8 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -363,7 +363,7 @@ AddSymlinkToHaikuHybridImage system lib : $(HAIKU_JPEG_CURRENT_LINK) AddSymlinkToHaikuHybridImage system lib : $(HAIKU_ZLIB_CURRENT_LIB:BS) : $(HAIKU_ZLIB_CURRENT_LINK) : : true ; AddSymlinkToHaikuHybridImage system lib : $(HAIKU_ZLIB_CURRENT_LINK) - : libzlib.so : : true ; + : libz.so : : true ; # servers AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ; From 122e78a5b92a5abfad8bef23c2bb859a0ab5eb6f Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Thu, 8 Nov 2012 10:08:37 +0000 Subject: [PATCH 2/9] Added translator for Apple icons (icns) * Read/Write up to 1024x1024 icon sizes. * All build-in icon sizes available as pages in ShowImage. * Support only 32-bit icon colors (rgb32 and rgba32) now. --- src/add-ons/translators/Jamfile | 1 + src/add-ons/translators/icns/ConfigView.cpp | 103 + src/add-ons/translators/icns/ConfigView.h | 27 + src/add-ons/translators/icns/ICNSLoader.cpp | 307 ++ src/add-ons/translators/icns/ICNSLoader.h | 68 + .../translators/icns/ICNSTranslator.cpp | 234 ++ src/add-ons/translators/icns/ICNSTranslator.h | 64 + .../translators/icns/ICNSTranslator.rdef | 15 + src/add-ons/translators/icns/Jamfile | 90 + .../translators/icns/libicns/COPYING.LGPL-2 | 481 +++ src/add-ons/translators/icns/libicns/README | 118 + src/add-ons/translators/icns/libicns/config.h | 30 + src/add-ons/translators/icns/libicns/icns.h | 212 ++ .../translators/icns/libicns/icns_colormaps.h | 314 ++ .../translators/icns/libicns/icns_debug.c | 61 + .../translators/icns/libicns/icns_element.c | 740 +++++ .../translators/icns/libicns/icns_family.c | 111 + .../translators/icns/libicns/icns_image.c | 794 +++++ .../translators/icns/libicns/icns_internals.h | 207 ++ .../translators/icns/libicns/icns_io.c | 1522 ++++++++++ .../translators/icns/libicns/icns_jp2.c | 961 ++++++ .../translators/icns/libicns/icns_png.c | 201 ++ .../translators/icns/libicns/icns_rle24.c | 411 +++ .../translators/icns/libicns/icns_utils.c | 763 +++++ src/add-ons/translators/icns/main.cpp | 26 + src/add-ons/translators/icns/openjpeg/LICENSE | 31 + src/add-ons/translators/icns/openjpeg/README | 25 + src/add-ons/translators/icns/openjpeg/bio.c | 187 ++ src/add-ons/translators/icns/openjpeg/bio.h | 125 + .../translators/icns/openjpeg/cidx_manager.c | 211 ++ .../translators/icns/openjpeg/cidx_manager.h | 56 + src/add-ons/translators/icns/openjpeg/cio.c | 191 ++ src/add-ons/translators/icns/openjpeg/cio.h | 93 + src/add-ons/translators/icns/openjpeg/dwt.c | 858 ++++++ src/add-ons/translators/icns/openjpeg/dwt.h | 113 + src/add-ons/translators/icns/openjpeg/event.c | 121 + src/add-ons/translators/icns/openjpeg/event.h | 58 + src/add-ons/translators/icns/openjpeg/fix.h | 64 + src/add-ons/translators/icns/openjpeg/image.c | 89 + .../icns/openjpeg/indexbox_manager.h | 118 + src/add-ons/translators/icns/openjpeg/int.h | 119 + src/add-ons/translators/icns/openjpeg/j2k.c | 2616 +++++++++++++++++ src/add-ons/translators/icns/openjpeg/j2k.h | 446 +++ .../translators/icns/openjpeg/j2k_lib.c | 59 + .../translators/icns/openjpeg/j2k_lib.h | 54 + src/add-ons/translators/icns/openjpeg/jp2.c | 1223 ++++++++ src/add-ons/translators/icns/openjpeg/jp2.h | 234 ++ src/add-ons/translators/icns/openjpeg/jpt.c | 155 + src/add-ons/translators/icns/openjpeg/jpt.h | 75 + src/add-ons/translators/icns/openjpeg/mct.c | 190 ++ src/add-ons/translators/icns/openjpeg/mct.h | 98 + src/add-ons/translators/icns/openjpeg/mqc.c | 592 ++++ src/add-ons/translators/icns/openjpeg/mqc.h | 200 ++ .../translators/icns/openjpeg/oj_image.h | 48 + .../translators/icns/openjpeg/openjpeg.c | 343 +++ .../translators/icns/openjpeg/openjpeg.h | 914 ++++++ .../translators/icns/openjpeg/opj_config.h | 117 + .../translators/icns/openjpeg/opj_includes.h | 140 + .../translators/icns/openjpeg/opj_malloc.h | 165 ++ .../translators/icns/openjpeg/phix_manager.c | 170 ++ src/add-ons/translators/icns/openjpeg/pi.c | 963 ++++++ src/add-ons/translators/icns/openjpeg/pi.h | 156 + .../translators/icns/openjpeg/ppix_manager.c | 173 ++ src/add-ons/translators/icns/openjpeg/raw.c | 87 + src/add-ons/translators/icns/openjpeg/raw.h | 100 + src/add-ons/translators/icns/openjpeg/t1.c | 1585 ++++++++++ src/add-ons/translators/icns/openjpeg/t1.h | 147 + .../icns/openjpeg/t1_generate_luts.c | 275 ++ .../translators/icns/openjpeg/t1_luts.h | 143 + src/add-ons/translators/icns/openjpeg/t2.c | 822 ++++++ src/add-ons/translators/icns/openjpeg/t2.h | 105 + src/add-ons/translators/icns/openjpeg/tcd.c | 1574 ++++++++++ src/add-ons/translators/icns/openjpeg/tcd.h | 286 ++ src/add-ons/translators/icns/openjpeg/tgt.c | 213 ++ src/add-ons/translators/icns/openjpeg/tgt.h | 114 + .../translators/icns/openjpeg/thix_manager.c | 120 + .../translators/icns/openjpeg/tpix_manager.c | 153 + 77 files changed, 25175 insertions(+) create mode 100644 src/add-ons/translators/icns/ConfigView.cpp create mode 100644 src/add-ons/translators/icns/ConfigView.h create mode 100644 src/add-ons/translators/icns/ICNSLoader.cpp create mode 100644 src/add-ons/translators/icns/ICNSLoader.h create mode 100644 src/add-ons/translators/icns/ICNSTranslator.cpp create mode 100644 src/add-ons/translators/icns/ICNSTranslator.h create mode 100644 src/add-ons/translators/icns/ICNSTranslator.rdef create mode 100644 src/add-ons/translators/icns/Jamfile create mode 100644 src/add-ons/translators/icns/libicns/COPYING.LGPL-2 create mode 100644 src/add-ons/translators/icns/libicns/README create mode 100644 src/add-ons/translators/icns/libicns/config.h create mode 100644 src/add-ons/translators/icns/libicns/icns.h create mode 100644 src/add-ons/translators/icns/libicns/icns_colormaps.h create mode 100644 src/add-ons/translators/icns/libicns/icns_debug.c create mode 100644 src/add-ons/translators/icns/libicns/icns_element.c create mode 100644 src/add-ons/translators/icns/libicns/icns_family.c create mode 100644 src/add-ons/translators/icns/libicns/icns_image.c create mode 100644 src/add-ons/translators/icns/libicns/icns_internals.h create mode 100644 src/add-ons/translators/icns/libicns/icns_io.c create mode 100644 src/add-ons/translators/icns/libicns/icns_jp2.c create mode 100644 src/add-ons/translators/icns/libicns/icns_png.c create mode 100644 src/add-ons/translators/icns/libicns/icns_rle24.c create mode 100644 src/add-ons/translators/icns/libicns/icns_utils.c create mode 100644 src/add-ons/translators/icns/main.cpp create mode 100644 src/add-ons/translators/icns/openjpeg/LICENSE create mode 100644 src/add-ons/translators/icns/openjpeg/README create mode 100644 src/add-ons/translators/icns/openjpeg/bio.c create mode 100644 src/add-ons/translators/icns/openjpeg/bio.h create mode 100644 src/add-ons/translators/icns/openjpeg/cidx_manager.c create mode 100644 src/add-ons/translators/icns/openjpeg/cidx_manager.h create mode 100644 src/add-ons/translators/icns/openjpeg/cio.c create mode 100644 src/add-ons/translators/icns/openjpeg/cio.h create mode 100644 src/add-ons/translators/icns/openjpeg/dwt.c create mode 100644 src/add-ons/translators/icns/openjpeg/dwt.h create mode 100644 src/add-ons/translators/icns/openjpeg/event.c create mode 100644 src/add-ons/translators/icns/openjpeg/event.h create mode 100644 src/add-ons/translators/icns/openjpeg/fix.h create mode 100644 src/add-ons/translators/icns/openjpeg/image.c create mode 100644 src/add-ons/translators/icns/openjpeg/indexbox_manager.h create mode 100644 src/add-ons/translators/icns/openjpeg/int.h create mode 100644 src/add-ons/translators/icns/openjpeg/j2k.c create mode 100644 src/add-ons/translators/icns/openjpeg/j2k.h create mode 100644 src/add-ons/translators/icns/openjpeg/j2k_lib.c create mode 100644 src/add-ons/translators/icns/openjpeg/j2k_lib.h create mode 100644 src/add-ons/translators/icns/openjpeg/jp2.c create mode 100644 src/add-ons/translators/icns/openjpeg/jp2.h create mode 100644 src/add-ons/translators/icns/openjpeg/jpt.c create mode 100644 src/add-ons/translators/icns/openjpeg/jpt.h create mode 100644 src/add-ons/translators/icns/openjpeg/mct.c create mode 100644 src/add-ons/translators/icns/openjpeg/mct.h create mode 100644 src/add-ons/translators/icns/openjpeg/mqc.c create mode 100644 src/add-ons/translators/icns/openjpeg/mqc.h create mode 100644 src/add-ons/translators/icns/openjpeg/oj_image.h create mode 100644 src/add-ons/translators/icns/openjpeg/openjpeg.c create mode 100644 src/add-ons/translators/icns/openjpeg/openjpeg.h create mode 100644 src/add-ons/translators/icns/openjpeg/opj_config.h create mode 100644 src/add-ons/translators/icns/openjpeg/opj_includes.h create mode 100644 src/add-ons/translators/icns/openjpeg/opj_malloc.h create mode 100644 src/add-ons/translators/icns/openjpeg/phix_manager.c create mode 100644 src/add-ons/translators/icns/openjpeg/pi.c create mode 100644 src/add-ons/translators/icns/openjpeg/pi.h create mode 100644 src/add-ons/translators/icns/openjpeg/ppix_manager.c create mode 100644 src/add-ons/translators/icns/openjpeg/raw.c create mode 100644 src/add-ons/translators/icns/openjpeg/raw.h create mode 100644 src/add-ons/translators/icns/openjpeg/t1.c create mode 100644 src/add-ons/translators/icns/openjpeg/t1.h create mode 100644 src/add-ons/translators/icns/openjpeg/t1_generate_luts.c create mode 100644 src/add-ons/translators/icns/openjpeg/t1_luts.h create mode 100644 src/add-ons/translators/icns/openjpeg/t2.c create mode 100644 src/add-ons/translators/icns/openjpeg/t2.h create mode 100644 src/add-ons/translators/icns/openjpeg/tcd.c create mode 100644 src/add-ons/translators/icns/openjpeg/tcd.h create mode 100644 src/add-ons/translators/icns/openjpeg/tgt.c create mode 100644 src/add-ons/translators/icns/openjpeg/tgt.h create mode 100644 src/add-ons/translators/icns/openjpeg/thix_manager.c create mode 100644 src/add-ons/translators/icns/openjpeg/tpix_manager.c diff --git a/src/add-ons/translators/Jamfile b/src/add-ons/translators/Jamfile index ab861a7fac..b6002cfee0 100644 --- a/src/add-ons/translators/Jamfile +++ b/src/add-ons/translators/Jamfile @@ -20,3 +20,4 @@ SubInclude HAIKU_TOP src add-ons translators tga ; SubInclude HAIKU_TOP src add-ons translators tiff ; SubInclude HAIKU_TOP src add-ons translators webp ; SubInclude HAIKU_TOP src add-ons translators wonderbrush ; +SubInclude HAIKU_TOP src add-ons translators icns ; diff --git a/src/add-ons/translators/icns/ConfigView.cpp b/src/add-ons/translators/icns/ConfigView.cpp new file mode 100644 index 0000000000..69c3f5336a --- /dev/null +++ b/src/add-ons/translators/icns/ConfigView.cpp @@ -0,0 +1,103 @@ +/* + * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "ConfigView.h" +#include "ICNSTranslator.h" + +#include +#include +#include + +#include + +extern "C" { +#include +}; + + +ConfigView::ConfigView(TranslatorSettings *settings) + : BGroupView("ICNSTranslator Settings", B_VERTICAL, 0) +{ + fSettings = settings; + BAlignment leftAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_UNSET); + + BStringView *stringView = new BStringView("title", "Apple icon translator"); + stringView->SetFont(be_bold_font); + stringView->SetExplicitAlignment(leftAlignment); + AddChild(stringView); + + float spacing = be_control_look->DefaultItemSpacing(); + AddChild(BSpaceLayoutItem::CreateVerticalStrut(spacing)); + + char version[256]; + sprintf(version, "Version %d.%d.%d, %s", + int(B_TRANSLATION_MAJOR_VERSION(ICNS_TRANSLATOR_VERSION)), + int(B_TRANSLATION_MINOR_VERSION(ICNS_TRANSLATOR_VERSION)), + int(B_TRANSLATION_REVISION_VERSION(ICNS_TRANSLATOR_VERSION)), + __DATE__); + stringView = new BStringView("version", version); + stringView->SetExplicitAlignment(leftAlignment); + AddChild(stringView); + + stringView = new BStringView("copyright", + B_UTF8_COPYRIGHT "2005-2006 Haiku Inc."); + stringView->SetExplicitAlignment(leftAlignment); + AddChild(stringView); + + stringView = new BStringView("my_copyright", + B_UTF8_COPYRIGHT "2012 Gerasim Troeglazov <3dEyes@gmail.com>."); + stringView->SetExplicitAlignment(leftAlignment); + AddChild(stringView); + + AddChild(BSpaceLayoutItem::CreateVerticalStrut(spacing)); + + stringView = new BStringView("support_sizes", + "Valid sizes: 16, 32, 48, 128, 256, 512, 1024"); + stringView->SetExplicitAlignment(leftAlignment); + AddChild(stringView); + + stringView = new BStringView("support_colors", + "Valid colors: RGB32, RGBA32"); + stringView->SetExplicitAlignment(leftAlignment); + AddChild(stringView); + + AddChild(BSpaceLayoutItem::CreateVerticalStrut(spacing)); + + BString copyrightText; + copyrightText << "libicns v0.8.1\n" + << B_UTF8_COPYRIGHT "2001-2012 Mathew Eis \n\n" + << "OpenJPEG " << opj_version() << "\n" + << B_UTF8_COPYRIGHT "2002-2012, Communications and Remote Sensing " + << "Laboratory, Universite catholique de Louvain (UCL), Belgium"; + + fCopyrightView = new BTextView("CopyrightLibs"); + fCopyrightView->SetExplicitAlignment(leftAlignment); + fCopyrightView->MakeEditable(false); + fCopyrightView->MakeResizable(true); + fCopyrightView->SetWordWrap(true); + fCopyrightView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fCopyrightView->SetText(copyrightText.String()); + fCopyrightView->SetExplicitMinSize(BSize(300,200)); + + BFont font; + font.SetSize(font.Size() * 0.9); + fCopyrightView->SetFontAndColor(&font, B_FONT_SIZE, NULL); + AddChild(fCopyrightView); + + fCopyrightView->SetExplicitAlignment(leftAlignment); + + AddChild(BSpaceLayoutItem::CreateGlue()); + GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, + B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); + + SetExplicitPreferredSize(GroupLayout()->MinSize()); +} + + +ConfigView::~ConfigView() +{ + fSettings->Release(); +} + diff --git a/src/add-ons/translators/icns/ConfigView.h b/src/add-ons/translators/icns/ConfigView.h new file mode 100644 index 0000000000..9fa7cd3a25 --- /dev/null +++ b/src/add-ons/translators/icns/ConfigView.h @@ -0,0 +1,27 @@ +/* + * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef CONFIG_VIEW_H +#define CONFIG_VIEW_H + +#include "TranslatorSettings.h" + +#include +#include +#include +#include + + +class ConfigView : public BGroupView { + public: + ConfigView(TranslatorSettings *settings); + virtual ~ConfigView(); + + private: + BTextView* fCopyrightView; + TranslatorSettings *fSettings; +}; + +#endif // CONFIG_VIEW_H diff --git a/src/add-ons/translators/icns/ICNSLoader.cpp b/src/add-ons/translators/icns/ICNSLoader.cpp new file mode 100644 index 0000000000..c98c34f446 --- /dev/null +++ b/src/add-ons/translators/icns/ICNSLoader.cpp @@ -0,0 +1,307 @@ +/* + * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "ICNSLoader.h" +#include "BaseTranslator.h" + + +static int compareTypes(const void *a, const void *b) +{ + icns_type_t typeItemA = *((icns_type_t*)(*((icns_type_t*)a))); + icns_type_t typeItemB = *((icns_type_t*)(*((icns_type_t*)b))); + + icns_icon_info_t imageInfoA = icns_get_image_info_for_type(typeItemA); + icns_icon_info_t imageInfoB = icns_get_image_info_for_type(typeItemB); + + return imageInfoB.iconWidth - imageInfoA.iconWidth; +} + + +icns_type_t +ICNSFormat(float width, float height, color_space colors) +{ + int imageWidth = (int)ceil(width); + int imageHeight = (int)ceil(height); + + if (imageWidth != imageHeight) + return ICNS_NULL_TYPE; + + //other colors depth not supported now + if (colors != B_RGB32 && colors != B_RGBA32) + return ICNS_NULL_TYPE; + + switch (imageWidth) { + case 16: + return ICNS_16x16_32BIT_DATA; + case 32: + return ICNS_32x32_32BIT_DATA; + case 48: + return ICNS_48x48_32BIT_DATA; + case 128: + return ICNS_128X128_32BIT_DATA; + case 256: + return ICNS_256x256_32BIT_ARGB_DATA; + case 512: + return ICNS_512x512_32BIT_ARGB_DATA; + case 1024: + return ICNS_1024x1024_32BIT_ARGB_DATA; + } + return ICNS_NULL_TYPE; +} + + +ICNSLoader::ICNSLoader(BPositionIO *stream) +{ + fLoaded = false; + fIconsCount = 0; + + stream->Seek(0, SEEK_END); + fStreamSize = stream->Position(); + stream->Seek(0, SEEK_SET); + + uint8* icnsDataBuffer = new uint8[fStreamSize]; + size_t readedBytes = stream->Read(icnsDataBuffer,fStreamSize); + + fIconFamily = NULL; + int status = icns_import_family_data(readedBytes, icnsDataBuffer, + &fIconFamily); + if (status != 0) + return; + + icns_byte_t *dataPtr = (icns_byte_t*)fIconFamily; + off_t dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + while ((dataOffset+8) < fIconFamily->resourceSize) + { + icns_element_t iconElement; + icns_size_t iconDataSize; + + memcpy(&iconElement, (dataPtr + dataOffset), 8); + iconDataSize = iconElement.elementSize - 8; + + if(IS_SPUPPORTED_TYPE(iconElement.elementType)) { + icns_type_t* newTypeItem = new icns_type_t; + *newTypeItem = iconElement.elementType; + fFormatList.AddItem(newTypeItem); + fIconsCount++; + } + dataOffset += iconElement.elementSize; + } + + fFormatList.SortItems(compareTypes); + + delete icnsDataBuffer; + + fLoaded = true; +} + + +ICNSLoader::~ICNSLoader() +{ + if (fIconFamily != NULL) + free(fIconFamily); + + icns_type_t* item; + for (int32 i = 0; (item = (icns_type_t*)fFormatList.ItemAt(i)) != NULL; i++) + delete item; + fFormatList.MakeEmpty(); +} + + +bool +ICNSLoader::IsLoaded(void) +{ + return fLoaded; +} + + +int +ICNSLoader::IconsCount(void) +{ + return fIconsCount; +} + + +int +ICNSLoader::GetIcon(BPositionIO *target, int index) +{ + if (index < 1 || index > fIconsCount || !fLoaded) + return B_NO_TRANSLATOR; + + icns_image_t iconImage; + memset(&iconImage, 0, sizeof(icns_image_t)); + + icns_type_t typeItem = *((icns_type_t*)fFormatList.ItemAt(index - 1)); + int status = icns_get_image32_with_mask_from_family(fIconFamily, + typeItem, &iconImage); + + if (status != 0) + return B_NO_TRANSLATOR; + + TranslatorBitmap bitsHeader; + bitsHeader.magic = B_TRANSLATOR_BITMAP; + bitsHeader.bounds.left = 0; + bitsHeader.bounds.top = 0; + bitsHeader.bounds.right = iconImage.imageWidth - 1; + bitsHeader.bounds.bottom = iconImage.imageHeight - 1; + bitsHeader.rowBytes = sizeof(uint32) * iconImage.imageWidth; + bitsHeader.colors = B_RGBA32; + bitsHeader.dataSize = bitsHeader.rowBytes * iconImage.imageHeight; + if (swap_data(B_UINT32_TYPE, &bitsHeader, + sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) { + icns_free_image(&iconImage); + return B_NO_TRANSLATOR; + } + target->Write(&bitsHeader, sizeof(TranslatorBitmap)); + + uint8 *rowBuff = new uint8[iconImage.imageWidth * sizeof(uint32)]; + for (uint32 i = 0; i < iconImage.imageHeight; i++) { + uint8 *rowData = iconImage.imageData + + (i * iconImage.imageWidth * sizeof(uint32)); + uint8 *rowBuffPtr = rowBuff; + for (uint32 j=0; j < iconImage.imageWidth; j++) { + rowBuffPtr[0] = rowData[2]; + rowBuffPtr[1] = rowData[1]; + rowBuffPtr[2] = rowData[0]; + rowBuffPtr[3] = rowData[3]; + rowBuffPtr += sizeof(uint32); + rowData += sizeof(uint32); + } + target->Write(rowBuff, iconImage.imageWidth * sizeof(uint32)); + } + delete rowBuff; + icns_free_image(&iconImage); + + return B_OK; +} + + +ICNSSaver::ICNSSaver(BPositionIO *stream, uint32 rowBytes, icns_type_t type) +{ + fCreated = false; + + icns_icon_info_t imageTypeInfo = icns_get_image_info_for_type(type); + int iconWidth = imageTypeInfo.iconWidth; + int iconHeight = imageTypeInfo.iconWidth; + int bpp = 32; + + uint8 *bits = new uint8[iconWidth * iconHeight * sizeof(uint32)]; + + uint8 *rowPtr = bits; + for (int i = 0; i < iconHeight; i++) { + stream->Read(rowPtr, rowBytes); + uint8 *bytePtr = rowPtr; + for (int j=0; j < iconWidth; j++) { + uint8 temp = bytePtr[0]; + bytePtr[0] = bytePtr[2]; + bytePtr[2] = temp; + bytePtr += sizeof(uint32); + } + rowPtr += iconWidth * sizeof(uint32); + } + + icns_create_family(&fIconFamily); + + icns_image_t icnsImage; + icnsImage.imageWidth = iconWidth; + icnsImage.imageHeight = iconHeight; + icnsImage.imageChannels = 4; + icnsImage.imagePixelDepth = 8; + icnsImage.imageDataSize = iconWidth * iconHeight * 4; + icnsImage.imageData = bits; + + icns_icon_info_t iconInfo; + iconInfo.isImage = 1; + iconInfo.iconWidth = icnsImage.imageWidth; + iconInfo.iconHeight = icnsImage.imageHeight; + iconInfo.iconBitDepth = bpp; + iconInfo.iconChannels = (bpp == 32 ? 4 : 1); + iconInfo.iconPixelDepth = bpp / iconInfo.iconChannels; + + icns_type_t iconType = icns_get_type_from_image_info(iconInfo); + + if (iconType == ICNS_NULL_TYPE) { + free(fIconFamily); + fIconFamily = NULL; + return; + } + + icns_element_t *iconElement = NULL; + int icnsErr = icns_new_element_from_image(&icnsImage, iconType, + &iconElement); + + if (iconElement != NULL) { + if (icnsErr == ICNS_STATUS_OK) { + icns_set_element_in_family(&fIconFamily, iconElement); + fCreated = true; + } + free(iconElement); + } + + if (iconType != ICNS_1024x1024_32BIT_ARGB_DATA + && iconType != ICNS_512x512_32BIT_ARGB_DATA + && iconType != ICNS_256x256_32BIT_ARGB_DATA) + { + icns_type_t maskType = icns_get_mask_type_for_icon_type(iconType); + + icns_image_t icnsMask; + icns_init_image_for_type(maskType, &icnsMask); + + uint32 iconDataOffset = 0; + uint32 maskDataOffset = 0; + + while (iconDataOffset < icnsImage.imageDataSize + && maskDataOffset < icnsMask.imageDataSize) { + icnsMask.imageData[maskDataOffset] = + icnsImage.imageData[iconDataOffset + 3]; + iconDataOffset += 4; + maskDataOffset += 1; + } + + icns_element_t *maskElement = NULL; + icnsErr = icns_new_element_from_mask(&icnsMask, maskType, + &maskElement); + + if (maskElement != NULL) { + if (icnsErr == ICNS_STATUS_OK) + icns_set_element_in_family(&fIconFamily, maskElement); + else + fCreated = false; + free(maskElement); + } + icns_free_image(&icnsMask); + } + + if(!fCreated) { + free(fIconFamily); + fIconFamily = NULL; + } +} + + +ICNSSaver::~ICNSSaver() +{ + if (fIconFamily != NULL) + free(fIconFamily); +} + + +int +ICNSSaver::SaveData(BPositionIO *target) +{ + icns_size_t dataSize; + icns_byte_t *dataPtrOut; + icns_export_family_data(fIconFamily, &dataSize, &dataPtrOut); + target->Write(dataPtrOut, dataSize); + + return B_OK; +} + + +bool +ICNSSaver::IsCreated(void) +{ + return fCreated; +} diff --git a/src/add-ons/translators/icns/ICNSLoader.h b/src/add-ons/translators/icns/ICNSLoader.h new file mode 100644 index 0000000000..a3edb2cefb --- /dev/null +++ b/src/add-ons/translators/icns/ICNSLoader.h @@ -0,0 +1,68 @@ +/* + * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef ICNS_LOADER_H +#define ICNS_LOADER_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "icns.h" +} + +#define IS_SPUPPORTED_TYPE(type) ((type) == ICNS_1024x1024_32BIT_ARGB_DATA || \ + (type) == ICNS_512x512_32BIT_ARGB_DATA || \ + (type) == ICNS_256x256_32BIT_ARGB_DATA || \ + (type) == ICNS_128X128_32BIT_DATA || \ + (type) == ICNS_48x48_32BIT_DATA || \ + (type) == ICNS_32x32_32BIT_DATA || \ + (type) == ICNS_16x16_32BIT_DATA) + +icns_type_t ICNSFormat(float width, float height, color_space colors); + +class ICNSLoader { +public: + ICNSLoader(BPositionIO *stream); + ~ICNSLoader(); + + int IconsCount(void); + int GetIcon(BPositionIO *target, int index); + bool IsLoaded(void); +private: + icns_family_t* fIconFamily; + int fIconsCount; + size_t fStreamSize; + BList fFormatList; + bool fLoaded; +}; + +class ICNSSaver { +public: + ICNSSaver(BPositionIO *stream, uint32 rowBytes, + icns_type_t type); + ~ICNSSaver(); + + int SaveData(BPositionIO *target); + bool IsCreated(void); +private: + icns_family_t* fIconFamily; + bool fCreated; + +}; + + +#endif /* ICNS_LOADER_H */ diff --git a/src/add-ons/translators/icns/ICNSTranslator.cpp b/src/add-ons/translators/icns/ICNSTranslator.cpp new file mode 100644 index 0000000000..0eca734f9e --- /dev/null +++ b/src/add-ons/translators/icns/ICNSTranslator.cpp @@ -0,0 +1,234 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "ICNSTranslator.h" + +#include +#include +#include + +#include "ConfigView.h" +#include "ICNSLoader.h" + +extern "C" { +#include "icns.h" +} + +const char *kDocumentCount = "/documentCount"; +const char *kDocumentIndex = "/documentIndex"; + +#define kICNSMimeType "image/icns" +#define kICNSName "Apple Icon" + +// The input formats that this translator supports. +static const translation_format sInputFormats[] = { + { + ICNS_IMAGE_FORMAT, + B_TRANSLATOR_BITMAP, + ICNS_IN_QUALITY, + ICNS_IN_CAPABILITY, + kICNSMimeType, + kICNSName + }, + { + B_TRANSLATOR_BITMAP, + B_TRANSLATOR_BITMAP, + BITS_IN_QUALITY, + BITS_IN_CAPABILITY, + "image/x-be-bitmap", + "Be Bitmap Format (ICNSTranslator)" + }, +}; + +// The output formats that this translator supports. +static const translation_format sOutputFormats[] = { + { + ICNS_IMAGE_FORMAT, + B_TRANSLATOR_BITMAP, + ICNS_OUT_QUALITY, + ICNS_OUT_CAPABILITY, + kICNSMimeType, + kICNSName + }, + { + B_TRANSLATOR_BITMAP, + B_TRANSLATOR_BITMAP, + BITS_OUT_QUALITY, + BITS_OUT_CAPABILITY, + "image/x-be-bitmap", + "Be Bitmap Format (ICNSTranslator)" + }, +}; + +// Default settings for the Translator +static const 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); + + +ICNSTranslator::ICNSTranslator() + : BaseTranslator("Apple icons", + "Apple icon translator", + ICNS_TRANSLATOR_VERSION, + sInputFormats, kNumInputFormats, + sOutputFormats, kNumOutputFormats, + "ICNSTranslator", + sDefaultSettings, kNumDefaultSettings, + B_TRANSLATOR_BITMAP, ICNS_IMAGE_FORMAT) +{ +} + + +ICNSTranslator::~ICNSTranslator() +{ +} + + +status_t +ICNSTranslator::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 != ICNS_IMAGE_FORMAT) + return B_NO_TRANSLATOR; + + uint32 signatureData; + ssize_t signatureSize = 4; + if (stream->Read(&signatureData, signatureSize) != signatureSize) + return B_IO_ERROR; + + const uint32 kICNSMagic = B_HOST_TO_BENDIAN_INT32('icns'); + + if (signatureData != kICNSMagic) + return B_ILLEGAL_DATA; + + + ICNSLoader icnsFile(stream); + if(!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0) + return B_ILLEGAL_DATA; + + int32 documentCount = icnsFile.IconsCount(); + int32 documentIndex = 1; + + if (ioExtension) { + if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK) + documentIndex = 1; + if (documentIndex < 1 || documentIndex > documentCount) + return B_NO_TRANSLATOR; + } + + if (ioExtension) { + ioExtension->RemoveName(DOCUMENT_COUNT); + ioExtension->AddInt32(DOCUMENT_COUNT, documentCount); + } + + info->type = ICNS_IMAGE_FORMAT; + info->group = B_TRANSLATOR_BITMAP; + info->quality = ICNS_IN_QUALITY; + info->capability = ICNS_IN_CAPABILITY; + snprintf(info->name, sizeof(info->name), "Apple icon"); + strcpy(info->MIME, kICNSMimeType); + + return B_OK; +} + + +status_t +ICNSTranslator::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 != ICNS_IMAGE_FORMAT) + return B_NO_TRANSLATOR; + + switch (baseType) { + case 1: + { + TranslatorBitmap bitsHeader; + status_t result; + result = identify_bits_header(source, NULL, &bitsHeader); + if (result != B_OK) + return B_NO_TRANSLATOR; + + icns_type_t type = ICNSFormat(bitsHeader.bounds.Width() + 1, + bitsHeader.bounds.Height() + 1, bitsHeader.colors); + if (type == ICNS_NULL_TYPE) + return B_NO_TRANSLATOR; + + if (outType == ICNS_IMAGE_FORMAT) { + ICNSSaver icnsFile(source, bitsHeader.rowBytes, type); + if (icnsFile.IsCreated()) + return icnsFile.SaveData(target); + } + + return B_NO_TRANSLATOR; + } + + case 0: + { + if (outType != B_TRANSLATOR_BITMAP) + return B_NO_TRANSLATOR; + + ICNSLoader icnsFile(source); + if (!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0) + return B_NO_TRANSLATOR; + + int32 documentIndex = 0; + + if (ioExtension) { + if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK) + documentIndex = 1; + } + + return icnsFile.GetIcon(target, documentIndex); + } + + default: + return B_NO_TRANSLATOR; + } +} + + +status_t +ICNSTranslator::DerivedCanHandleImageSize(float width, float height) const +{ + if (ICNSFormat(width, height, B_RGBA32) == ICNS_NULL_TYPE) + return B_NO_TRANSLATOR; + return B_OK; +} + + +BView * +ICNSTranslator::NewConfigView(TranslatorSettings *settings) +{ + return new ConfigView(settings); +} + + +// #pragma mark - + + +BTranslator * +make_nth_translator(int32 n, image_id you, uint32 flags, ...) +{ + if (n != 0) + return NULL; + + return new ICNSTranslator(); +} + diff --git a/src/add-ons/translators/icns/ICNSTranslator.h b/src/add-ons/translators/icns/ICNSTranslator.h new file mode 100644 index 0000000000..0b5982071a --- /dev/null +++ b/src/add-ons/translators/icns/ICNSTranslator.h @@ -0,0 +1,64 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef ICNS_TRANSLATOR_H +#define ICNS_TRANSLATOR_H + + +#include "BaseTranslator.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DOCUMENT_COUNT "/documentCount" +#define DOCUMENT_INDEX "/documentIndex" + +#define ICNS_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 0, 0) +#define ICNS_IMAGE_FORMAT 'ICNS' + +#define ICNS_IN_QUALITY 0.5 +#define ICNS_IN_CAPABILITY 0.5 +#define BITS_IN_QUALITY 1 +#define BITS_IN_CAPABILITY 1 + +#define ICNS_OUT_QUALITY 0.8 +#define ICNS_OUT_CAPABILITY 0.8 +#define BITS_OUT_QUALITY 1 +#define BITS_OUT_CAPABILITY 0.9 + + +class ICNSTranslator : public BaseTranslator { + public: + ICNSTranslator(); + + 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 status_t DerivedCanHandleImageSize(float width, + float height) const; + + virtual BView *NewConfigView(TranslatorSettings *settings); + + protected: + virtual ~ICNSTranslator(); +}; + +// Extensions that ShowImage supports +extern const char *kDocumentCount; +extern const char *kDocumentIndex; + +#endif /* ICNS_TRANSLATOR_H */ diff --git a/src/add-ons/translators/icns/ICNSTranslator.rdef b/src/add-ons/translators/icns/ICNSTranslator.rdef new file mode 100644 index 0000000000..ca4a905581 --- /dev/null +++ b/src/add-ons/translators/icns/ICNSTranslator.rdef @@ -0,0 +1,15 @@ +/* + * ICNSTranslator.rdef + */ + +resource app_signature "application/x-vnd.Haiku-ICNSTranslator"; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + variety = 0, + internal = 0, + short_info = "1.0.0", + long_info = "Haiku ICNSTranslator Add-Ons." +}; diff --git a/src/add-ons/translators/icns/Jamfile b/src/add-ons/translators/icns/Jamfile new file mode 100644 index 0000000000..23b3e44942 --- /dev/null +++ b/src/add-ons/translators/icns/Jamfile @@ -0,0 +1,90 @@ +SubDir HAIKU_TOP src add-ons translators icns ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UseHeaders $(HAIKU_LIBPNG_HEADERS) : true ; + +SubDirSysHdrs [ FDirName $(SUBDIR) openjpeg ] ; +SubDirSysHdrs [ FDirName $(SUBDIR) libicns ] ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) shared ] ; + #for BaseTranslator.h and friends + +# Let Jam know where to find some of our source files +SEARCH_SOURCE += [ FDirName $(SUBDIR) openjpeg ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) libicns ] ; + +SubDirC++Flags [ FDefines BEOS_R5_COMPATIBLE ] ; + +local openjpeg_files = + bio.c + cio.c + dwt.c + event.c + image.c + j2k.c + j2k_lib.c + jp2.c + jpt.c + mct.c + mqc.c + openjpeg.c + pi.c + raw.c + t1.c + t2.c + tcd.c + tgt.c + cidx_manager.c + phix_manager.c + ppix_manager.c + thix_manager.c + tpix_manager.c + ; + +ObjectCcFlags [ FGristFiles $(openjpeg_files:S=$(SUFOBJ)) ] : -w ; + +local libicns_files = + icns_debug.c + icns_element.c + icns_family.c + icns_image.c + icns_io.c + icns_jp2.c + icns_png.c + icns_rle24.c + icns_utils.c + ; + +ObjectCcFlags [ FGristFiles $(libicns_files:S=$(SUFOBJ)) ] : -w ; + +AddResources ICNSTranslator : ICNSTranslator.rdef ; + +Translator ICNSTranslator : + + # ICNSTranslator + ICNSTranslator.cpp + ICNSLoader.cpp + ConfigView.cpp + main.cpp + + $(openjpeg_files) + + $(libicns_files) + + : be translation libtranslatorsutils.a $(TARGET_LIBSUPC++) + $(HAIKU_LIBPNG_LIB) $(HAIKU_LOCALE_LIBS) + : true +; + +DoCatalogs ICNSTranslator : + x-vnd.Haiku-ICNSTranslator + : + ICNSTranslator.h + ICNSTranslator.cpp +; + +Package haiku-translationkit-cvs : + ICNSTranslator : + boot home config add-ons Translators ; + diff --git a/src/add-ons/translators/icns/libicns/COPYING.LGPL-2 b/src/add-ons/translators/icns/libicns/COPYING.LGPL-2 new file mode 100644 index 0000000000..5bc8fb2c8f --- /dev/null +++ b/src/add-ons/translators/icns/libicns/COPYING.LGPL-2 @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/src/add-ons/translators/icns/libicns/README b/src/add-ons/translators/icns/libicns/README new file mode 100644 index 0000000000..40d3394171 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/README @@ -0,0 +1,118 @@ +=============================================================================== +README for libicns 0.8.1 - June 14, 2012 +Copyright (C) 2001-2012 Mathew Eis + +Other individuals have supported the development of libicns; they are credited +in the source files where their respective contibutions have been made. + +=============================================================================== +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +=============================================================================== +This package include the following libraries and utilities: +1) libicns - A library for the translation of the icns format +2) icns2png - A utility for converting icns files into png images +3) icontainer2icns - A utility for extracting icns files from icontainer packs + +You should be able to get the latest version at http://sf.net/projects/icns + +=============================================================================== +libicns is a library for manipulation of the Mac OS icns resource format, also +known as the IconFamily resource type. It can read and write files from the +Mac OS X icns format, as well as read from Mac OS resource files and macbinary +encoded Mac OS resource forks. + +As of release 0.5.9, it can fully manipulate any 128x128 and smaller 32-bit +icons, and has partial support for manipulating 8-bit, 4-bit, and 1-bit icons. + +When linked with Jasper, it also has full support for 256x256 and 512x512 +icon sizes within the icon family. + +As of release 0.8.0, it can read the PNG format introduced with OS X Lion 10.7 + + +Please see DEVNOTES for more information on how to use libicns + +=============================================================================== +Using icns2png + +icns2png -x OmniWeb.icns +Converting OmniWeb.icns to OmniWeb_128x128x32.png... + +This will result in a file OmniWeb_128x128x32.png with a 128x128 icon from OmniWeb.icns. + +Run icns2png --help for more detailed information. + +=============================================================================== +Using icontainer2icns + +icontainer2icns foo.icontainer + +This will end up with a couple of icns files identified by the iContainer ID +and the iContainer name in a (new) folder carrying the icontainer name +(without any suffix) + +=============================================================================== +NOTICE: icontainer2icns is NOT related to www.iconfactory.com - though it +decodes this library type. They are NOT involved, please don't bother them +with bug reports. + +For bug/wishes regarding icontainer2icns mailto: baghira-style@gmx.net + +=============================================================================== +Understanding the Mac OS X Icons + +Mac OS X Icon files come in two formats - icns files, and icns resources +embedded with rsrc files. They may also be stored in a macbinary encoded +rsrc files, or applesingle/appledouble encoded rsrc files + +libicns (and icns2png) can decode all five storage formats + +The .icns files are much easier to deal with, since they are in a format that +can be easily accesed from Linux/UNIX/Windows. + +You can however access the icons from the resource files. OS X Icons like +those from http://interfacelift.com/icons-mac/ are compressed in .sit files. +These files can be uncompressed using Aladdin Stuffit Expander for Linux, +which can be obtained from http://www.stuffit.com/unix/index.html + +When unstuffing, be sure to use a command similar to the following: + +unstuff --text=auto --macbinary=auto --eol=unix icons.hqx.sit + +This will help ensure that the resource forks are uncompressed into +MacBinary files, so that icns2png can read them. + +If there are resource forks in the files, when stuffit decompresses them, +it will create two files from the one mac file. For example, if the mac +file was named "Gnu", the resulting decomressed files will be +"Gnu", and "Gnu_1". The "Snowflake_1" file is the resource +fork. This is the file you will want to extract the icon from. The file +"Gnu" does not contain any icon data. If, however, there is no +"Gnu_1", then the file may be in the .icns format, and you will +extract the icon from "Gnu" - resulting in a file "Gnu.png" + +It is really fairly simple, once you get the hang of it - you will also +notice that if the icon was in the resource fork, then the other main +file will be etremely small, sometimes even 0k. + +The underlying data in both of the files is similar - they both hold the +following icon data (Although most icons to not have a complete set): +16x12 pixels - 1 bit mask - 1, 4, or 8 bit icon +16x16 pixels - 1 or 8 bit mask - 1, 4, 8 or 24 bit icon +32x32 pixels - 1 or 8 bit mask - 1, 4, 8, or 24 bit icon +64x64 pixels - 1 or 8 bit mask - 1, 4, 8, or 24 bit icon +128x128 pixels - 8 bit mask - 24 bit icon diff --git a/src/add-ons/translators/icns/libicns/config.h b/src/add-ons/translators/icns/libicns/config.h new file mode 100644 index 0000000000..ad438a4e97 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/config.h @@ -0,0 +1,30 @@ +#define HAVE_DLFCN_H 1 +#define HAVE_FORK 1 +#define HAVE_GETOPT_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_PNG_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_UNALIGNED_MEMCPY 1 +#define HAVE_UNISTD_H 1 +#define HAVE_VFORK 1 +#define HAVE_WORKING_FORK 1 +#define HAVE_WORKING_VFORK 1 +#define ICNS_OPENJPEG 1 +#define STDC_HEADERS 1 +#define VERSION "0.8.1" + +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif diff --git a/src/add-ons/translators/icns/libicns/icns.h b/src/add-ons/translators/icns/libicns/icns.h new file mode 100644 index 0000000000..f8344974d0 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns.h @@ -0,0 +1,212 @@ +/* +File: icns.h +Copyright (C) 2001-2012 Mathew Eis +Copyright (C) 2002 Chenxiao Zhao + +With the exception of the limited portions mentiond, this library +is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published +by the Free Software Foundation; either version 2.1 of the License, +or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#ifndef _ICNS_H_ +#define _ICNS_H_ + +/* basic data types */ +typedef uint8_t icns_bool_t; + +typedef uint8_t icns_uint8_t; +typedef int8_t icns_sint8_t; +typedef uint16_t icns_uint16_t; +typedef int16_t icns_sint16_t; +typedef uint32_t icns_uint32_t; +typedef int32_t icns_sint32_t; +typedef uint64_t icns_uint64_t; +typedef int64_t icns_sint64_t; + +typedef uint8_t icns_byte_t; + + +/* data header types */ +typedef uint32_t icns_type_t; +typedef int32_t icns_size_t; + +/* icon family and element types */ +typedef struct icns_element_t { + icns_type_t elementType; /* 'ICN#', 'icl8', etc... */ + icns_size_t elementSize; /* Total size of element */ + icns_byte_t elementData[1]; /* icon image data */ +} icns_element_t; + +typedef struct icns_family_t { + icns_type_t resourceType; /* Always should be 'icns' */ + icns_size_t resourceSize; /* Total size of resource */ + icns_element_t elements[1]; /* icon elements */ +} icns_family_t; + +/* icon image data structure */ +typedef struct icns_image_t +{ + icns_uint32_t imageWidth; // width of image in pixels + icns_uint32_t imageHeight; // height of image in pixels + icns_uint8_t imageChannels; // number of channels in data + icns_uint16_t imagePixelDepth;// number of bits-per-pixel + icns_uint64_t imageDataSize; // bytes = width * height * depth / bits-per-pixel + icns_byte_t *imageData; // pointer to base address of uncompressed raw image data +} icns_image_t; + +/* used for getting information about various types */ +/* not part of the actual icns data format */ +typedef struct icns_icon_info_t +{ + icns_type_t iconType; // type of icon (or mask) + icns_bool_t isImage; // is this type an image + icns_bool_t isMask; // is this type a mask + icns_uint32_t iconWidth; // width of icon in pixels + icns_uint32_t iconHeight; // height of icon in pixels + icns_uint8_t iconChannels; // number of channels in data + icns_uint16_t iconPixelDepth; // number of bits-per-pixel + icns_uint16_t iconBitDepth; // overall bit depth = iconPixelDepth * iconChannels + icns_uint64_t iconRawDataSize; // uncompressed bytes = width * height * depth / bits-per-pixel +} icns_icon_info_t; + +/* icns element type constants */ + +#define ICNS_TABLE_OF_CONTENTS 0x544F4320 // "TOC " + +#define ICNS_ICON_VERSION 0x69636E56 // "icnV" + +#define ICNS_1024x1024_32BIT_ARGB_DATA 0x69633130 // "ic10" + +#define ICNS_512x512_32BIT_ARGB_DATA 0x69633039 // "ic09" +#define ICNS_256x256_32BIT_ARGB_DATA 0x69633038 // "ic08" + +#define ICNS_128X128_32BIT_DATA 0x69743332 // "it32" +#define ICNS_128X128_8BIT_MASK 0x74386D6B // "t8mk" + +#define ICNS_48x48_1BIT_DATA 0x69636823 // "ich#" +#define ICNS_48x48_4BIT_DATA 0x69636834 // "ich4" +#define ICNS_48x48_8BIT_DATA 0x69636838 // "ich8" +#define ICNS_48x48_32BIT_DATA 0x69683332 // "ih32" +#define ICNS_48x48_1BIT_MASK 0x69636823 // "ich#" +#define ICNS_48x48_8BIT_MASK 0x68386D6B // "h8mk" + +#define ICNS_32x32_1BIT_DATA 0x49434E23 // "ICN#" +#define ICNS_32x32_4BIT_DATA 0x69636C34 // "icl4" +#define ICNS_32x32_8BIT_DATA 0x69636C38 // "icl8" +#define ICNS_32x32_32BIT_DATA 0x696C3332 // "il32" +#define ICNS_32x32_1BIT_MASK 0x49434E23 // "ICN#" +#define ICNS_32x32_8BIT_MASK 0x6C386D6B // "l8mk" + +#define ICNS_16x16_1BIT_DATA 0x69637323 // "ics#" +#define ICNS_16x16_4BIT_DATA 0x69637334 // "ics4" +#define ICNS_16x16_8BIT_DATA 0x69637338 // "ics8" +#define ICNS_16x16_32BIT_DATA 0x69733332 // "is32" +#define ICNS_16x16_1BIT_MASK 0x69637323 // "ics#" +#define ICNS_16x16_8BIT_MASK 0x73386D6B // "s8mk" + +#define ICNS_16x12_1BIT_DATA 0x69636D23 // "icm#" +#define ICNS_16x12_4BIT_DATA 0x69636D34 // "icm4" +#define ICNS_16x12_1BIT_MASK 0x69636D23 // "icm#" +#define ICNS_16x12_8BIT_DATA 0x69636D38 // "icm8" + +#define ICNS_32x32_1BIT_ICON 0x49434F4E // "ICON" + +#define ICNS_TILE_VARIANT 0x74696C65 // "tile" +#define ICNS_ROLLOVER_VARIANT 0x6F766572 // "over" +#define ICNS_DROP_VARIANT 0x64726F70 // "drop" +#define ICNS_OPEN_VARIANT 0x6F70656E // "open" +#define ICNS_OPEN_DROP_VARIANT 0x6F647270 // "odrp" + +#define ICNS_NULL_DATA 0x00000000 +#define ICNS_NULL_MASK 0x00000000 + +/* icns file / resource type constants */ + +#define ICNS_FAMILY_TYPE 0x69636E73 // "icns" + +#define ICNS_MACBINARY_TYPE 0x6D42494E // "mBIN" + +#define ICNS_NULL_TYPE 0x00000000 + +/* icns error return values */ + +#define ICNS_STATUS_OK 0 + +#define ICNS_STATUS_NULL_PARAM -1 +#define ICNS_STATUS_NO_MEMORY -2 +#define ICNS_STATUS_INVALID_DATA -3 + +#define ICNS_STATUS_IO_READ_ERR 1 +#define ICNS_STATUS_IO_WRITE_ERR 2 +#define ICNS_STATUS_DATA_NOT_FOUND 3 +#define ICNS_STATUS_UNSUPPORTED 4 + +/* icns function prototypes */ +/* NOTE: internal functions are found in icns_internals.h */ + +// icns_io.c +int icns_write_family_to_file(FILE *dataFile,icns_family_t *iconFamilyIn); +int icns_read_family_from_file(FILE *dataFile,icns_family_t **iconFamilyOut); +int icns_read_family_from_rsrc(FILE *rsrcFile,icns_family_t **iconFamilyOut); +int icns_export_family_data(icns_family_t *iconFamily,icns_size_t *dataSizeOut,icns_byte_t **dataPtrOut); +int icns_import_family_data(icns_size_t dataSize,icns_byte_t *data,icns_family_t **iconFamilyOut); + +// icns_family.c +int icns_create_family(icns_family_t **iconFamilyOut); +int icns_count_elements_in_family(icns_family_t *iconFamily, icns_sint32_t *elementTotal); + +// icns_element.c +int icns_get_element_from_family(icns_family_t *iconFamily,icns_type_t iconType,icns_element_t **iconElementOut); +int icns_set_element_in_family(icns_family_t **iconFamilyRef,icns_element_t *newIconElement); +int icns_add_element_in_family(icns_family_t **iconFamilyRef,icns_element_t *newIconElement); +int icns_remove_element_in_family(icns_family_t **iconFamilyRef,icns_type_t iconType); +int icns_new_element_from_image(icns_image_t *imageIn,icns_type_t iconType,icns_element_t **iconElementOut); +int icns_new_element_from_mask(icns_image_t *imageIn,icns_type_t iconType,icns_element_t **iconElementOut); +int icns_update_element_with_image(icns_image_t *imageIn,icns_element_t **iconElement); +int icns_update_element_with_mask(icns_image_t *imageIn,icns_element_t **iconElement); + +// icns_image.c +int icns_get_image32_with_mask_from_family(icns_family_t *iconFamily,icns_type_t sourceType,icns_image_t *imageOut); +int icns_get_image_from_element(icns_element_t *iconElement,icns_image_t *imageOut); +int icns_get_mask_from_element(icns_element_t *iconElement,icns_image_t *imageOut); +int icns_init_image_for_type(icns_type_t iconType,icns_image_t *imageOut); +int icns_init_image(icns_uint32_t iconWidth,icns_uint32_t iconHeight,icns_uint32_t iconChannels,icns_uint32_t iconPixelDepth,icns_image_t *imageOut); +int icns_free_image(icns_image_t *imageIn); + +// icns_rle24.c +int icns_decode_rle24_data(icns_size_t rawDataSize, icns_byte_t *rawDataPtr,icns_size_t expectedPixelCount, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut); +int icns_encode_rle24_data(icns_size_t dataSizeIn, icns_byte_t *dataPtrIn,icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut); + +// icns_jp2.c +int icns_jp2_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut); +int icns_image_to_jp2(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut); + +// icns_utils.c +icns_icon_info_t icns_get_image_info_for_type(icns_type_t iconType); +icns_type_t icns_get_mask_type_for_icon_type(icns_type_t); +icns_type_t icns_get_type_from_image_info(icns_icon_info_t iconInfo); +icns_type_t icns_get_type_from_image(icns_image_t iconImage); +icns_type_t icns_get_type_from_mask(icns_image_t iconImage); +icns_bool_t icns_types_equal(icns_type_t typeA,icns_type_t typeB); +icns_bool_t icns_types_not_equal(icns_type_t typeA,icns_type_t typeB); +const char * icns_type_str(icns_type_t type, char *strbuf); +void icns_set_print_errors(icns_bool_t shouldPrint); + +#endif diff --git a/src/add-ons/translators/icns/libicns/icns_colormaps.h b/src/add-ons/translators/icns/libicns/icns_colormaps.h new file mode 100644 index 0000000000..74b9b81ad2 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_colormaps.h @@ -0,0 +1,314 @@ +/* +File: icns_colormaps.h +Copyright (C) 2001-2012 Mathew Eis +Copyright (C) 2004 Brion Vibber +Copyright (C) 2007 Lyonel Vincent + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#ifndef _COLORMAPS_H_ +#define _COLORMAPS_H_ 1 + +typedef struct icns_colormap_rgb_t +{ + icns_byte_t r; + icns_byte_t g; + icns_byte_t b; +} icns_colormap_rgb_t; + + +static const icns_colormap_rgb_t icns_colormap_4[] = +{ + {0xFF, 0xFF, 0xFF}, + {0xFC, 0xF3, 0x05}, + {0xFF, 0x64, 0x02}, + {0xDD, 0x08, 0x06}, + {0xF2, 0x08, 0x84}, + {0x46, 0x00, 0xA5}, + {0x00, 0x00, 0xD4}, + {0x02, 0xAB, 0xEA}, + {0x1F, 0xB7, 0x14}, + {0x00, 0x64, 0x11}, + {0x56, 0x2C, 0x05}, + {0x90, 0x71, 0x3A}, + {0xC0, 0xC0, 0xC0}, + {0x80, 0x80, 0x80}, + {0x40, 0x40, 0x40}, + {0x00, 0x00, 0x00} +}; + +static const icns_colormap_rgb_t icns_colormap_8[] = +{ + {0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xCC}, + {0xFF, 0xFF, 0x99}, + {0xFF, 0xFF, 0x66}, + {0xFF, 0xFF, 0x33}, + {0xFF, 0xFF, 0x00}, + {0xFF, 0xCC, 0xFF}, + {0xFF, 0xCC, 0xCC}, + {0xFF, 0xCC, 0x99}, + {0xFF, 0xCC, 0x66}, + {0xFF, 0xCC, 0x33}, + {0xFF, 0xCC, 0x00}, + {0xFF, 0x99, 0xFF}, + {0xFF, 0x99, 0xCC}, + {0xFF, 0x99, 0x99}, + {0xFF, 0x99, 0x66}, + {0xFF, 0x99, 0x33}, + {0xFF, 0x99, 0x00}, + {0xFF, 0x66, 0xFF}, + {0xFF, 0x66, 0xCC}, + {0xFF, 0x66, 0x99}, + {0xFF, 0x66, 0x66}, + {0xFF, 0x66, 0x33}, + {0xFF, 0x66, 0x00}, + {0xFF, 0x33, 0xFF}, + {0xFF, 0x33, 0xCC}, + {0xFF, 0x33, 0x99}, + {0xFF, 0x33, 0x66}, + {0xFF, 0x33, 0x33}, + {0xFF, 0x33, 0x00}, + {0xFF, 0x00, 0xFF}, + {0xFF, 0x00, 0xCC}, + {0xFF, 0x00, 0x99}, + {0xFF, 0x00, 0x66}, + {0xFF, 0x00, 0x33}, + {0xFF, 0x00, 0x00}, + {0xCC, 0xFF, 0xFF}, + {0xCC, 0xFF, 0xCC}, + {0xCC, 0xFF, 0x99}, + {0xCC, 0xFF, 0x66}, + {0xCC, 0xFF, 0x33}, + {0xCC, 0xFF, 0x00}, + {0xCC, 0xCC, 0xFF}, + {0xCC, 0xCC, 0xCC}, + {0xCC, 0xCC, 0x99}, + {0xCC, 0xCC, 0x66}, + {0xCC, 0xCC, 0x33}, + {0xCC, 0xCC, 0x00}, + {0xCC, 0x99, 0xFF}, + {0xCC, 0x99, 0xCC}, + {0xCC, 0x99, 0x99}, + {0xCC, 0x99, 0x66}, + {0xCC, 0x99, 0x33}, + {0xCC, 0x99, 0x00}, + {0xCC, 0x66, 0xFF}, + {0xCC, 0x66, 0xCC}, + {0xCC, 0x66, 0x99}, + {0xCC, 0x66, 0x66}, + {0xCC, 0x66, 0x33}, + {0xCC, 0x66, 0x00}, + {0xCC, 0x33, 0xFF}, + {0xCC, 0x33, 0xCC}, + {0xCC, 0x33, 0x99}, + {0xCC, 0x33, 0x66}, + {0xCC, 0x33, 0x33}, + {0xCC, 0x33, 0x00}, + {0xCC, 0x00, 0xFF}, + {0xCC, 0x00, 0xCC}, + {0xCC, 0x00, 0x99}, + {0xCC, 0x00, 0x66}, + {0xCC, 0x00, 0x33}, + {0xCC, 0x00, 0x00}, + {0x99, 0xFF, 0xFF}, + {0x99, 0xFF, 0xCC}, + {0x99, 0xFF, 0x99}, + {0x99, 0xFF, 0x66}, + {0x99, 0xFF, 0x33}, + {0x99, 0xFF, 0x00}, + {0x99, 0xCC, 0xFF}, + {0x99, 0xCC, 0xCC}, + {0x99, 0xCC, 0x99}, + {0x99, 0xCC, 0x66}, + {0x99, 0xCC, 0x33}, + {0x99, 0xCC, 0x00}, + {0x99, 0x99, 0xFF}, + {0x99, 0x99, 0xCC}, + {0x99, 0x99, 0x99}, + {0x99, 0x99, 0x66}, + {0x99, 0x99, 0x33}, + {0x99, 0x99, 0x00}, + {0x99, 0x66, 0xFF}, + {0x99, 0x66, 0xCC}, + {0x99, 0x66, 0x99}, + {0x99, 0x66, 0x66}, + {0x99, 0x66, 0x33}, + {0x99, 0x66, 0x00}, + {0x99, 0x33, 0xFF}, + {0x99, 0x33, 0xCC}, + {0x99, 0x33, 0x99}, + {0x99, 0x33, 0x66}, + {0x99, 0x33, 0x33}, + {0x99, 0x33, 0x00}, + {0x99, 0x00, 0xFF}, + {0x99, 0x00, 0xCC}, + {0x99, 0x00, 0x99}, + {0x99, 0x00, 0x66}, + {0x99, 0x00, 0x33}, + {0x99, 0x00, 0x00}, + {0x66, 0xFF, 0xFF}, + {0x66, 0xFF, 0xCC}, + {0x66, 0xFF, 0x99}, + {0x66, 0xFF, 0x66}, + {0x66, 0xFF, 0x33}, + {0x66, 0xFF, 0x00}, + {0x66, 0xCC, 0xFF}, + {0x66, 0xCC, 0xCC}, + {0x66, 0xCC, 0x99}, + {0x66, 0xCC, 0x66}, + {0x66, 0xCC, 0x33}, + {0x66, 0xCC, 0x00}, + {0x66, 0x99, 0xFF}, + {0x66, 0x99, 0xCC}, + {0x66, 0x99, 0x99}, + {0x66, 0x99, 0x66}, + {0x66, 0x99, 0x33}, + {0x66, 0x99, 0x00}, + {0x66, 0x66, 0xFF}, + {0x66, 0x66, 0xCC}, + {0x66, 0x66, 0x99}, + {0x66, 0x66, 0x66}, + {0x66, 0x66, 0x33}, + {0x66, 0x66, 0x00}, + {0x66, 0x33, 0xFF}, + {0x66, 0x33, 0xCC}, + {0x66, 0x33, 0x99}, + {0x66, 0x33, 0x66}, + {0x66, 0x33, 0x33}, + {0x66, 0x33, 0x00}, + {0x66, 0x00, 0xFF}, + {0x66, 0x00, 0xCC}, + {0x66, 0x00, 0x99}, + {0x66, 0x00, 0x66}, + {0x66, 0x00, 0x33}, + {0x66, 0x00, 0x00}, + {0x33, 0xFF, 0xFF}, + {0x33, 0xFF, 0xCC}, + {0x33, 0xFF, 0x99}, + {0x33, 0xFF, 0x66}, + {0x33, 0xFF, 0x33}, + {0x33, 0xFF, 0x00}, + {0x33, 0xCC, 0xFF}, + {0x33, 0xCC, 0xCC}, + {0x33, 0xCC, 0x99}, + {0x33, 0xCC, 0x66}, + {0x33, 0xCC, 0x33}, + {0x33, 0xCC, 0x00}, + {0x33, 0x99, 0xFF}, + {0x33, 0x99, 0xCC}, + {0x33, 0x99, 0x99}, + {0x33, 0x99, 0x66}, + {0x33, 0x99, 0x33}, + {0x33, 0x99, 0x00}, + {0x33, 0x66, 0xFF}, + {0x33, 0x66, 0xCC}, + {0x33, 0x66, 0x99}, + {0x33, 0x66, 0x66}, + {0x33, 0x66, 0x33}, + {0x33, 0x66, 0x00}, + {0x33, 0x33, 0xFF}, + {0x33, 0x33, 0xCC}, + {0x33, 0x33, 0x99}, + {0x33, 0x33, 0x66}, + {0x33, 0x33, 0x33}, + {0x33, 0x33, 0x00}, + {0x33, 0x00, 0xFF}, + {0x33, 0x00, 0xCC}, + {0x33, 0x00, 0x99}, + {0x33, 0x00, 0x66}, + {0x33, 0x00, 0x33}, + {0x33, 0x00, 0x00}, + {0x00, 0xFF, 0xFF}, + {0x00, 0xFF, 0xCC}, + {0x00, 0xFF, 0x99}, + {0x00, 0xFF, 0x66}, + {0x00, 0xFF, 0x33}, + {0x00, 0xFF, 0x00}, + {0x00, 0xCC, 0xFF}, + {0x00, 0xCC, 0xCC}, + {0x00, 0xCC, 0x99}, + {0x00, 0xCC, 0x66}, + {0x00, 0xCC, 0x33}, + {0x00, 0xCC, 0x00}, + {0x00, 0x99, 0xFF}, + {0x00, 0x99, 0xCC}, + {0x00, 0x99, 0x99}, + {0x00, 0x99, 0x66}, + {0x00, 0x99, 0x33}, + {0x00, 0x99, 0x00}, + {0x00, 0x66, 0xFF}, + {0x00, 0x66, 0xCC}, + {0x00, 0x66, 0x99}, + {0x00, 0x66, 0x66}, + {0x00, 0x66, 0x33}, + {0x00, 0x66, 0x00}, + {0x00, 0x33, 0xFF}, + {0x00, 0x33, 0xCC}, + {0x00, 0x33, 0x99}, + {0x00, 0x33, 0x66}, + {0x00, 0x33, 0x33}, + {0x00, 0x33, 0x00}, + {0x00, 0x00, 0xFF}, + {0x00, 0x00, 0xCC}, + {0x00, 0x00, 0x99}, + {0x00, 0x00, 0x66}, + {0x00, 0x00, 0x33}, + {0xEE, 0x00, 0x00}, + {0xDD, 0x00, 0x00}, + {0xBB, 0x00, 0x00}, + {0xAA, 0x00, 0x00}, + {0x88, 0x00, 0x00}, + {0x77, 0x00, 0x00}, + {0x55, 0x00, 0x00}, + {0x44, 0x00, 0x00}, + {0x22, 0x00, 0x00}, + {0x11, 0x00, 0x00}, + {0x00, 0xEE, 0x00}, + {0x00, 0xDD, 0x00}, + {0x00, 0xBB, 0x00}, + {0x00, 0xAA, 0x00}, + {0x00, 0x88, 0x00}, + {0x00, 0x77, 0x00}, + {0x00, 0x55, 0x00}, + {0x00, 0x44, 0x00}, + {0x00, 0x22, 0x00}, + {0x00, 0x11, 0x00}, + {0x00, 0x00, 0xEE}, + {0x00, 0x00, 0xDD}, + {0x00, 0x00, 0xBB}, + {0x00, 0x00, 0xAA}, + {0x00, 0x00, 0x88}, + {0x00, 0x00, 0x77}, + {0x00, 0x00, 0x55}, + {0x00, 0x00, 0x44}, + {0x00, 0x00, 0x22}, + {0x00, 0x00, 0x11}, + {0xEE, 0xEE, 0xEE}, + {0xDD, 0xDD, 0xDD}, + {0xBB, 0xBB, 0xBB}, + {0xAA, 0xAA, 0xAA}, + {0x88, 0x88, 0x88}, + {0x77, 0x77, 0x77}, + {0x55, 0x55, 0x55}, + {0x44, 0x44, 0x44}, + {0x22, 0x22, 0x22}, + {0x11, 0x11, 0x11}, + {0x00, 0x00, 0x00} +}; + +#endif /*_COLORMAPS_H_ */ diff --git a/src/add-ons/translators/icns/libicns/icns_debug.c b/src/add-ons/translators/icns/libicns/icns_debug.c new file mode 100644 index 0000000000..a3dd075149 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_debug.c @@ -0,0 +1,61 @@ +/* +File: icns_debug.c +Copyright (C) 2001-2012 Mathew Eis + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" +#ifdef ICNS_DEBUG +void bin_print_byte(int x) +{ + int n; + for(n=0; n<8; n++) + { + if((x & 0x80) !=0) + { + printf("1"); + } + else + { + printf("0"); + } + if(n==3) + { + printf(" "); /* insert a space between nybbles */ + } + x = x<<1; + } +} + +void bin_print_int(int x) +{ + int hi, lo; + hi=(x>>8) & 0xff; + lo=x&0xff; + bin_print_byte(hi); + printf(" "); + bin_print_byte(lo); +} +#endif /* ifdef ICNS_DEBUG */ + + diff --git a/src/add-ons/translators/icns/libicns/icns_element.c b/src/add-ons/translators/icns/libicns/icns_element.c new file mode 100644 index 0000000000..afc7521a24 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_element.c @@ -0,0 +1,740 @@ +/* +File: icns_element.c +Copyright (C) 2001-2012 Mathew Eis + 2007 Thomas Lübking + 2002 Chenxiao Zhao + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" + + +//***************************** icns_get_element_from_family **************************// +// Parses requested data from an icon family - puts it into a icon element + +int icns_get_element_from_family(icns_family_t *iconFamily,icns_type_t iconType,icns_element_t **iconElementOut) +{ + int error = ICNS_STATUS_OK; + int foundData = 0; + icns_type_t iconFamilyType = ICNS_NULL_TYPE; + icns_size_t iconFamilySize = 0; + icns_element_t *iconElement = NULL; + icns_type_t elementType = ICNS_NULL_TYPE; + icns_size_t elementSize = 0; + icns_uint32_t dataOffset = 0; + + if(iconFamily == NULL) + { + icns_print_err("icns_get_element_from_family: icns family is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconElementOut == NULL) + { + icns_print_err("icns_get_element_in_family: icns element out is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + else + { + *iconElementOut = NULL; + } + + if(iconFamily->resourceType != ICNS_FAMILY_TYPE) + { + icns_print_err("icns_get_element_from_family: Invalid icns family!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + ICNS_READ_UNALIGNED(iconFamilyType, &(iconFamily->resourceType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(iconFamilySize, &(iconFamily->resourceSize),sizeof( icns_size_t)); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf("Looking for icon element of type: '%s'\n",icns_type_str(iconType,typeStr)); + printf(" icon family type check: '%s'\n",icns_type_str(iconFamilyType,typeStr)); + printf(" icon family size check: %d\n",iconFamilySize); + } + #endif + + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + while ( (foundData == 0) && (dataOffset < iconFamilySize) ) + { + iconElement = ((icns_element_t*)(((icns_byte_t*)iconFamily)+dataOffset)); + + if( iconFamilySize < (dataOffset+sizeof(icns_type_t)+sizeof(icns_size_t)) ) + { + icns_print_err("icns_get_element_from_family: Corrupted icns family!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + ICNS_READ_UNALIGNED(elementType, &(iconElement->elementType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(elementSize, &(iconElement->elementSize),sizeof( icns_size_t)); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf("element data...\n"); + printf(" type: '%s'%s\n",icns_type_str(elementType,typeStr),(elementType == iconType) ? " - match!" : " "); + printf(" size: %d\n",(int)elementSize); + } + #endif + + if( (elementSize < 8) || ((dataOffset+elementSize) > iconFamilySize) ) + { + icns_print_err("icns_get_element_from_family: Invalid element size! (%d)\n",elementSize); + return ICNS_STATUS_INVALID_DATA; + } + + if(elementType == iconType) + foundData = 1; + else + dataOffset += elementSize; + } + + if(foundData) + { + *iconElementOut = malloc(elementSize); + if(*iconElementOut == NULL) + { + icns_print_err("icns_get_element_from_family: Unable to allocate memory block of size: %d!\n",elementSize); + return ICNS_STATUS_NO_MEMORY; + } + memcpy( *iconElementOut, iconElement, elementSize); + } + else + { + icns_print_err("icns_get_element_from_family: Unable to find requested icon data!\n"); + error = ICNS_STATUS_DATA_NOT_FOUND; + } + + return error; +} + +//***************************** icns_set_element_in_family **************************// +// Adds/updates the icns element of it's type in the icon family + +int icns_set_element_in_family(icns_family_t **iconFamilyRef,icns_element_t *newIconElement) +{ + int error = ICNS_STATUS_OK; + int foundData = 0; + int copiedData = 0; + icns_family_t *iconFamily = NULL; + icns_type_t iconFamilyType = ICNS_NULL_TYPE; + icns_size_t iconFamilySize = 0; + icns_element_t *iconElement = NULL; + icns_type_t newElementType = ICNS_NULL_TYPE; + icns_size_t newElementSize = 0; + icns_type_t elementType = ICNS_NULL_TYPE; + icns_size_t elementSize = 0; + icns_uint32_t dataOffset = 0; + icns_size_t newIconFamilySize = 0; + icns_family_t *newIconFamily = NULL; + icns_uint32_t newDataOffset = 0; + icns_uint32_t elementOrder = 0; + icns_uint32_t newElementOrder = 0; + + + if(iconFamilyRef == NULL) + { + icns_print_err("icns_set_element_in_family: icns family reference is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + iconFamily = *iconFamilyRef; + + if(iconFamily == NULL) + { + icns_print_err("icns_set_element_in_family: icns family is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + #ifdef ICNS_DEBUG + printf("Setting element in icon family...\n"); + #endif + + if(iconFamily->resourceType != ICNS_FAMILY_TYPE) + { + icns_print_err("icns_set_element_in_family: Invalid icns family!\n"); + error = ICNS_STATUS_INVALID_DATA; + } + + ICNS_READ_UNALIGNED(iconFamilyType, &(iconFamily->resourceType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(iconFamilySize, &(iconFamily->resourceSize),sizeof( icns_size_t)); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" family type '%s'\n",icns_type_str(iconFamilyType,typeStr)); + printf(" family size: %d (0x%08X)\n",(int)iconFamilySize,iconFamilySize); + } + #endif + + if(newIconElement == NULL) + { + icns_print_err("icns_set_element_in_family: icns element is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + // Retrieve first, then swap. May help with problems on some arch + ICNS_READ_UNALIGNED(newElementType, &(newIconElement->elementType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(newElementSize, &(newIconElement->elementSize),sizeof( icns_size_t)); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" element type '%s'\n",icns_type_str(newElementType,typeStr)); + printf(" element size: %d (0x%08X)\n",(int)newElementSize,newElementSize); + } + #endif + + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + while ( (foundData == 0) && (dataOffset < iconFamilySize) ) + { + iconElement = ((icns_element_t*)(((char*)iconFamily)+dataOffset)); + ICNS_READ_UNALIGNED(elementType, &(iconElement->elementType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(elementSize, &(iconElement->elementSize),sizeof( icns_size_t)); + + if(elementType == newElementType) + foundData = 1; + else + dataOffset += elementSize; + } + + if(foundData) + newIconFamilySize = iconFamilySize - elementSize + newElementSize; + else + newIconFamilySize = iconFamilySize + newElementSize; + + #ifdef ICNS_DEBUG + printf(" new family type 'icns'\n"); + printf(" new family size: %d (0x%08X)\n",(int)newIconFamilySize,newIconFamilySize); + #endif + + newIconFamily = malloc(newIconFamilySize); + + if(newIconFamily == NULL) + { + icns_print_err("icns_set_element_in_family: Unable to allocate memory block of size: %d!\n",newIconFamilySize); + return ICNS_STATUS_NO_MEMORY; + } + + newIconFamily->resourceType = ICNS_FAMILY_TYPE; + newIconFamily->resourceSize = newIconFamilySize; + + newDataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + copiedData = 0; + + newElementOrder = icns_get_element_order(newElementType); + + while ( dataOffset < iconFamilySize ) + { + iconElement = ((icns_element_t*)(((char*)iconFamily)+dataOffset)); + ICNS_READ_UNALIGNED(elementType, &(iconElement->elementType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(elementSize, &(iconElement->elementSize),sizeof( icns_size_t)); + elementOrder = icns_get_element_order(elementType); + + if(!copiedData && (elementType == newElementType)) + { + memcpy( ((char *)(newIconFamily))+newDataOffset , (char *)newIconElement, newElementSize); + newDataOffset += newElementSize; + copiedData = 1; + } + else if(!copiedData && !foundData && newElementOrder < elementOrder) + { + memcpy( ((char *)(newIconFamily))+newDataOffset , (char *)newIconElement, newElementSize); + newDataOffset += newElementSize; + copiedData = 1; + + memcpy( ((char *)(newIconFamily))+newDataOffset , ((char *)(iconFamily))+dataOffset, elementSize); + newDataOffset += elementSize; + } + else + { + memcpy( ((char *)(newIconFamily))+newDataOffset , ((char *)(iconFamily))+dataOffset, elementSize); + newDataOffset += elementSize; + } + + dataOffset += elementSize; + } + + if(!copiedData) + { + memcpy( ((char *)(newIconFamily))+newDataOffset , (char *)newIconElement, newElementSize); + newDataOffset += newElementSize; + } + + *iconFamilyRef = newIconFamily; + + free(iconFamily); + + return error; +} + +//***************************** icns_add_element_in_family **************************// +// Adds/updates the icns element of it's type in the icon family +// A convenience alias to icns_set_element_in_family + +int icns_add_element_in_family(icns_family_t **iconFamilyRef,icns_element_t *newIconElement) +{ + if(iconFamilyRef == NULL) + { + icns_print_err("icns_add_element_in_family: icns family reference is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(newIconElement == NULL) + { + icns_print_err("icns_add_element_in_family: icon element is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + return icns_set_element_in_family(iconFamilyRef,newIconElement); +} + +//***************************** icns_remove_element_in_family **************************// +// Parses requested data from an icon family - puts it into a "raw" image format + +int icns_remove_element_in_family(icns_family_t **iconFamilyRef,icns_type_t iconElementType) +{ + int error = ICNS_STATUS_OK; + int foundData = 0; + icns_family_t *iconFamily = NULL; + icns_type_t iconFamilyType = ICNS_NULL_TYPE; + icns_size_t iconFamilySize = 0; + icns_element_t *iconElement = NULL; + icns_type_t elementType = ICNS_NULL_TYPE; + icns_size_t elementSize = 0; + icns_uint32_t dataOffset = 0; + + icns_size_t newIconFamilySize = 0; + icns_family_t *newIconFamily = NULL; + icns_uint32_t newDataOffset = 0; + + if(iconFamilyRef == NULL) + { + icns_print_err("icns_remove_element_in_family: icon family reference is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + iconFamily = *iconFamilyRef; + + if(iconFamily == NULL) + { + icns_print_err("icns_remove_element_in_family: icon family is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconFamily->resourceType != ICNS_FAMILY_TYPE) + { + icns_print_err("icns_remove_element_in_family: Invalid icon family!\n"); + error = ICNS_STATUS_INVALID_DATA; + } + + ICNS_READ_UNALIGNED(iconFamilyType, &(iconFamily->resourceType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(iconFamilySize, &(iconFamily->resourceSize),sizeof( icns_size_t)); + + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + while ( (foundData == 0) && (dataOffset < iconFamilySize) ) + { + iconElement = ((icns_element_t*)(((char*)iconFamily)+dataOffset)); + ICNS_READ_UNALIGNED(elementType, &(iconElement->elementType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(elementSize, &(iconElement->elementSize),sizeof( icns_size_t)); + + if(elementType == iconElementType) + foundData = 1; + else + dataOffset += elementSize; + } + + if(!foundData) + { + icns_print_err("icns_remove_element_in_family: Unable to find requested icon data for removal!\n"); + return ICNS_STATUS_DATA_NOT_FOUND; + } + + + newIconFamilySize = iconFamilySize - elementSize; + newIconFamily = malloc(newIconFamilySize); + + if(newIconFamily == NULL) + { + icns_print_err("icns_remove_element_in_family: Unable to allocate memory block of size: %d!\n",newIconFamilySize); + return ICNS_STATUS_NO_MEMORY; + } + + newIconFamily->resourceType = ICNS_FAMILY_TYPE; + newIconFamily->resourceSize = newIconFamilySize; + + newDataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + while ( dataOffset < iconFamilySize ) + { + iconElement = ((icns_element_t*)(((char*)iconFamily)+dataOffset)); + ICNS_READ_UNALIGNED(elementType, &(iconElement->elementType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(elementSize, &(iconElement->elementSize),sizeof( icns_size_t)); + + if(elementType != iconElementType) + { + memcpy( ((char *)(newIconFamily))+newDataOffset , ((char *)(iconFamily))+dataOffset, elementSize); + newDataOffset += elementSize; + } + + dataOffset += elementSize; + } + + *iconFamilyRef = newIconFamily; + + free(iconFamily); + + return error; +} + + + +//***************************** icns_new_element_from_image **************************// +// Creates a new icon element from an image +int icns_new_element_from_image(icns_image_t *imageIn,icns_type_t iconType,icns_element_t **iconElementOut) +{ + return icns_new_element_from_image_or_mask(imageIn,iconType,0,iconElementOut); +} + +//***************************** icns_new_element_from_mask **************************// +// Creates a new icon element from an image +int icns_new_element_from_mask(icns_image_t *imageIn,icns_type_t iconType,icns_element_t **iconElementOut) +{ + return icns_new_element_from_image_or_mask(imageIn,iconType,1,iconElementOut); +} + + +//***************************** icns_new_element_from_image_or_mask **************************// +// Creates a new icon element from an image +int icns_new_element_from_image_or_mask(icns_image_t *imageIn,icns_type_t iconType,icns_bool_t isMask,icns_element_t **iconElementOut) +{ + icns_element_t *newElement = NULL; + icns_size_t newElementSize = 0; + + if(iconElementOut == NULL) + { + icns_print_err("icns_new_element_with_image_or_mask: Icon element reference is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + else + { + *iconElementOut = NULL; + } + + newElementSize = sizeof(icns_type_t) + sizeof(icns_size_t); + newElement = (icns_element_t *)malloc(newElementSize); + if(newElement == NULL) + { + icns_print_err("icns_new_element_with_image_or_mask: Unable to allocate memory block of size: %d!\n",(int)newElementSize); + return ICNS_STATUS_NO_MEMORY; + } + + newElement->elementType = iconType; + newElement->elementSize = newElementSize; + *iconElementOut = newElement; + + return icns_update_element_with_image_or_mask(imageIn,isMask,iconElementOut); +} + +//***************************** icns_update_element_from_image **************************// +// Updates an icon element with the given image +int icns_update_element_with_image(icns_image_t *imageIn,icns_element_t **iconElement) +{ + return icns_update_element_with_image_or_mask(imageIn,0,iconElement); +} + +//***************************** icns_update_element_from_mask **************************// +// Updates an icon element with the given mask +int icns_update_element_with_mask(icns_image_t *imageIn,icns_element_t **iconElement) +{ + return icns_update_element_with_image_or_mask(imageIn,1,iconElement); +} + +//***************************** icns_update_element_with_image_or_mask **************************// +// Updates an icon element with the given image or mask +int icns_update_element_with_image_or_mask(icns_image_t *imageIn,icns_bool_t isMask,icns_element_t **iconElement) +{ + int error = ICNS_STATUS_OK; + icns_type_t iconType; + icns_icon_info_t iconInfo; + + // Finally, done with all the preliminary checks + icns_size_t imageDataSize = 0; + icns_byte_t *imageDataPtr = NULL; + + // For use to easily track deallocation if we use rle24, or jp2 + icns_size_t newDataSize = 0; + icns_byte_t *newDataPtr = NULL; + + + if(imageIn == NULL) + { + icns_print_err("icns_update_element_with_image_or_mask: Icon image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconElement == NULL) + { + icns_print_err("icns_update_element_with_image_or_mask: Icon element reference is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(*iconElement == NULL) + { + icns_print_err("icns_update_element_with_image_or_mask: Icon element is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + iconType = (*iconElement)->elementType; + + if(iconType == ICNS_NULL_DATA) { + icns_print_err("icns_update_element_with_image_or_mask: Invalid icon type!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + // Determine what the height and width ought to be, to check the incoming image + iconInfo = icns_get_image_info_for_type(iconType); + + // Check the image width, height, and pixel depth + + if(imageIn->imageWidth != iconInfo.iconWidth) + { + icns_print_err("icns_update_element_with_image_or_mask: Invalid input image width: %d\n",imageIn->imageWidth); + return ICNS_STATUS_INVALID_DATA; + } + + if(imageIn->imageWidth != iconInfo.iconWidth) + { + icns_print_err("icns_update_element_with_image_or_mask: Invalid input image width: %d\n",imageIn->imageWidth); + return ICNS_STATUS_INVALID_DATA; + } + + if(imageIn->imageHeight != iconInfo.iconHeight) + { + icns_print_err("icns_update_element_with_image_or_mask: Invalid input image height: %d\n",imageIn->imageHeight); + return ICNS_STATUS_INVALID_DATA; + } + + if(imageIn->imagePixelDepth != (iconInfo.iconBitDepth/iconInfo.iconChannels)) + { + icns_print_err("icns_update_element_with_image_or_mask: libicns does't support bit depth conversion yet.\n"); + return ICNS_STATUS_INVALID_DATA; + } + + // Check the image data size and data pointer + + if(imageIn->imageDataSize == 0) + { + icns_print_err("icns_update_element_with_image_or_mask: Invalid input image data size: %d\n",(int)imageIn->imageDataSize); + return ICNS_STATUS_INVALID_DATA; + } + + if(imageIn->imageData == NULL) + { + icns_print_err("icns_update_element_with_image_or_mask: Invalid input image data\n"); + return ICNS_STATUS_INVALID_DATA; + } + + switch(iconType) + { + case ICNS_1024x1024_32BIT_ARGB_DATA: + case ICNS_256x256_32BIT_ARGB_DATA: + case ICNS_512x512_32BIT_ARGB_DATA: + error = icns_image_to_jp2(imageIn,&newDataSize,&newDataPtr); + imageDataSize = newDataSize; + imageDataPtr = newDataPtr; + break; + case ICNS_128X128_32BIT_DATA: + case ICNS_48x48_32BIT_DATA: + case ICNS_32x32_32BIT_DATA: + case ICNS_16x16_32BIT_DATA: + newDataSize = imageIn->imageDataSize; + + // Note: icns_encode_rle24_data allocates memory that must be freed later + if( (error = icns_encode_rle24_data(imageIn->imageDataSize,imageIn->imageData,&newDataSize,&newDataPtr)) ) + { + icns_print_err("icns_update_element_with_image_or_mask: Error rle encoding image data.\n"); + error = ICNS_STATUS_INVALID_DATA; + } + + imageDataSize = newDataSize; + imageDataPtr = newDataPtr; + break; + // Note that ICNS_NNxNN_1BIT_DATA == ICNS_NNxNN_1BIT_MASK + // so we do not need to put them here twice + case ICNS_48x48_1BIT_DATA: + case ICNS_32x32_1BIT_DATA: + case ICNS_16x16_1BIT_DATA: + case ICNS_16x12_1BIT_DATA: + { + icns_byte_t *existingData = NULL; + icns_size_t existingDataSize = 0; + icns_size_t existingDataOffset = 0; + + if(imageIn->imageDataSize != iconInfo.iconRawDataSize) + { + icns_print_err("icns_update_element_with_image_or_mask: Invalid input image data size: %d!\n",imageIn->imageDataSize); + return ICNS_STATUS_INVALID_DATA; + } + + newDataSize = iconInfo.iconRawDataSize * 2; + newDataPtr = (icns_byte_t *)malloc(newDataSize); + if(newDataPtr == NULL) + { + icns_print_err("icns_update_element_with_image_or_mask: Unable to allocate memory block of size: %d!\n",newDataSize); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } + + memset (newDataPtr,0,newDataSize); + + existingData = (icns_byte_t*)(*iconElement); + existingDataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + existingDataSize = (*iconElement)->elementSize - existingDataOffset; + + // No icon data + if(existingDataSize == 0) + { + if(isMask == 0) { + memcpy(newDataPtr,imageIn->imageData,imageIn->imageDataSize); + } else { + memcpy(newDataPtr,imageIn->imageData + iconInfo.iconRawDataSize,imageIn->imageDataSize); + } + } + // Only image data + else if(existingDataSize == iconInfo.iconRawDataSize) + { + if(isMask == 0) { + memcpy(newDataPtr,imageIn->imageData,imageIn->imageDataSize); + } else { + memcpy(newDataPtr,existingData+existingDataOffset,iconInfo.iconRawDataSize); + memcpy(newDataPtr,imageIn->imageData + iconInfo.iconRawDataSize,imageIn->imageDataSize); + } + } + // Image + Mask data + else if(existingDataSize == newDataSize) + { + if(isMask == 0) { + memcpy(newDataPtr,imageIn->imageData,imageIn->imageDataSize); + memcpy(newDataPtr,existingData+existingDataOffset+iconInfo.iconRawDataSize,iconInfo.iconRawDataSize); + } else { + memcpy(newDataPtr,existingData+existingDataOffset,iconInfo.iconRawDataSize); + memcpy(newDataPtr,imageIn->imageData + iconInfo.iconRawDataSize,imageIn->imageDataSize); + } + } + else + { + icns_print_err("icns_update_element_with_image_or_mask: Unexpected element data size: %d!\n",existingDataSize); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + imageDataSize = newDataSize; + imageDataPtr = newDataPtr; + } + break; + default: + imageDataSize = imageIn->imageDataSize; + imageDataPtr = imageIn->imageData; + break; + } + + if(error == ICNS_STATUS_OK) + { + icns_element_t *newElement = NULL; + icns_size_t newElementSize = 0; + icns_type_t newElementType = ICNS_NULL_DATA; + icns_size_t newElementHeaderSize = 0; + + if(imageDataSize == 0) + { + icns_print_err("icns_update_element_with_image_or_mask: Image data size should not be 0!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + if(imageDataPtr == NULL) + { + icns_print_err("icns_update_element_with_image_or_mask: Image data should not be NULL!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + // Set up and create the new element + newElementHeaderSize = sizeof(icns_type_t) + sizeof(icns_size_t); + newElementSize = newElementHeaderSize + imageDataSize; + newElementType = iconType; + + newElement = (icns_element_t *)malloc(newElementSize); + + if(newElement == NULL) + { + icns_print_err("icns_update_element_with_image_or_mask: Unable to allocate memory block of size: %d!\n",(int)newElementSize); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } + + // Set up the element info + newElement->elementType = newElementType; + newElement->elementSize = newElementSize; + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" updated element data...\n"); + printf(" type: '%s'\n",icns_type_str(newElementType,typeStr)); + printf(" size: %d\n",(int)newElementSize); + } + #endif + + // Copy in the image data + memcpy(newElement->elementData,imageDataPtr,imageDataSize); + + // Free the old element... + if(*iconElement != NULL) + free(*iconElement); + + // and move the pointer to the new element + *iconElement = newElement; + } + +exception: + + // We might have allocated new memory earlier... + if(newDataPtr != NULL) + { + free(newDataPtr); + newDataPtr = NULL; + } + + return error; +} diff --git a/src/add-ons/translators/icns/libicns/icns_family.c b/src/add-ons/translators/icns/libicns/icns_family.c new file mode 100644 index 0000000000..bcc4d70d88 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_family.c @@ -0,0 +1,111 @@ +/* +File: icns_family.c +Copyright (C) 2001-2012 Mathew Eis + 2007 Thomas Lübking + 2002 Chenxiao Zhao + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" + +/***************************** icns_create_family **************************/ + +int icns_create_family(icns_family_t **iconFamilyOut) +{ + icns_family_t *newIconFamily = NULL; + icns_type_t iconFamilyType = ICNS_NULL_TYPE; + icns_size_t iconFamilySize = 0; + + if(iconFamilyOut == NULL) + { + icns_print_err("icns_create_family: icon family reference is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + *iconFamilyOut = NULL; + + iconFamilyType = ICNS_FAMILY_TYPE; + iconFamilySize = sizeof(icns_type_t) + sizeof(icns_size_t); + + newIconFamily = malloc(iconFamilySize); + + if(newIconFamily == NULL) + { + icns_print_err("icns_create_family: Unable to allocate memory block of size: %d!\n",iconFamilySize); + return ICNS_STATUS_NO_MEMORY; + } + + ICNS_WRITE_UNALIGNED(&(newIconFamily->resourceType), iconFamilyType, sizeof(icns_type_t)); + ICNS_WRITE_UNALIGNED(&(newIconFamily->resourceSize), iconFamilySize, sizeof(icns_size_t)); + + *iconFamilyOut = newIconFamily; + + return ICNS_STATUS_OK; +} + + +/***************************** icns_count_elements_in_family **************************/ + +int icns_count_elements_in_family(icns_family_t *iconFamily, icns_sint32_t *elementTotal) +{ + icns_type_t iconFamilyType = ICNS_NULL_TYPE; + icns_size_t iconFamilySize = 0; + icns_uint32_t dataOffset = 0; + icns_uint32_t elementCount = 0; + + if(iconFamily == NULL) + { + icns_print_err("icns_count_elements_in_family: icns family is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(elementTotal == NULL) + { + icns_print_err("icns_count_elements_in_family: element count ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + ICNS_READ_UNALIGNED(iconFamilyType, &(iconFamily->resourceType),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(iconFamilySize, &(iconFamily->resourceSize),sizeof( icns_size_t)); + + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + while( dataOffset < iconFamilySize ) + { + icns_element_t *iconElement = NULL; + icns_size_t elementSize = 0; + + iconElement = ((icns_element_t*)(((char*)iconFamily)+dataOffset)); + ICNS_READ_UNALIGNED(elementSize, &(iconElement->elementSize),sizeof( icns_size_t)); + + elementCount++; + + dataOffset += elementSize; + } + + *elementTotal = elementCount; + + return ICNS_STATUS_OK; +} + + diff --git a/src/add-ons/translators/icns/libicns/icns_image.c b/src/add-ons/translators/icns/libicns/icns_image.c new file mode 100644 index 0000000000..5b596b560a --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_image.c @@ -0,0 +1,794 @@ +/* +File: icns_image.c +Copyright (C) 2001-2012 Mathew Eis + 2007 Thomas Lübking + 2002 Chenxiao Zhao + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" +#include "icns_colormaps.h" + + +int icns_get_image32_with_mask_from_family(icns_family_t *iconFamily,icns_type_t iconType,icns_image_t *imageOut) +{ + int error = ICNS_STATUS_OK; + icns_type_t maskType = ICNS_NULL_TYPE; + icns_element_t *iconElement = NULL; + icns_element_t *maskElement = NULL; + icns_image_t iconImage; + icns_image_t maskImage; + unsigned long dataCount = 0; + icns_byte_t dataValue = 0; + unsigned long pixelCount = 0; + unsigned long pixelID = 0; + icns_byte_t colorIndex = 0; + + memset ( &iconImage, 0, sizeof(icns_image_t) ); + memset ( &maskImage, 0, sizeof(icns_image_t) ); + + if(iconFamily == NULL) + { + icns_print_err("icns_get_image32_with_mask_from_family: Icon family is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(imageOut == NULL) + { + icns_print_err("icns_get_image32_with_mask_from_family: Icon image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + else + { + icns_free_image(imageOut); + } + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf("Making 32-bit image...\n"); + printf(" using icon type '%s'\n",icns_type_str(iconType,typeStr)); + } + #endif + + + if((iconType == ICNS_128X128_8BIT_MASK) || \ + (iconType == ICNS_48x48_8BIT_MASK) || \ + (iconType == ICNS_32x32_8BIT_MASK) || \ + (iconType == ICNS_16x16_8BIT_MASK) ) + { + icns_print_err("icns_get_image32_with_mask_from_family: Can't make an image with mask from a mask\n"); + return ICNS_STATUS_INVALID_DATA; + } + + // Preliminaries checked - carry on with the icon/mask merge + + // Load icon element then image + error = icns_get_element_from_family(iconFamily,iconType,&iconElement); + + if(error) { + icns_print_err("icns_get_image32_with_mask_from_family: Unable to load icon element from icon family!\n"); + goto cleanup; + } + + error = icns_get_image_from_element(iconElement,&iconImage); + + if(error) { + icns_print_err("icns_get_image32_with_mask_from_family: Unable to load icon image data from icon element!\n"); + goto cleanup; + } + + // We used the jp2 processor for these two, so we're done! + if( (iconType == ICNS_256x256_32BIT_ARGB_DATA) || (iconType == ICNS_512x512_32BIT_ARGB_DATA) || (iconType == ICNS_1024x1024_32BIT_ARGB_DATA) ) { + memcpy(imageOut,&iconImage,sizeof(icns_image_t)); + if(iconElement != NULL) { + free(iconElement); + iconElement = NULL; + } + return error; + } + + maskType = icns_get_mask_type_for_icon_type(iconType); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" using mask type '%s'\n",icns_type_str(maskType,typeStr)); + } + #endif + + if( (maskType == ICNS_NULL_DATA) ) + { + char typeStr[5]; + icns_print_err("icns_get_image32_with_mask_from_family: Can't find mask for type '%s'\n",icns_type_str(iconType,typeStr)); + return ICNS_STATUS_DATA_NOT_FOUND; + } + + // Load mask element then image... + error = icns_get_element_from_family(iconFamily,maskType,&maskElement); + + // Note that we could arguably recover from not having a mask + // by creating a dummy blank mask. However, the icns data type + // should always have the corresponding mask present. This + // function was designed to retreive a VALID image... There are + // other API functions better used if the goal is editing, data + // recovery, etc. + if(error) { + icns_print_err("icns_get_image32_with_mask_from_family: Unable to load mask element from icon family!\n"); + goto cleanup; + } + + error = icns_get_mask_from_element(maskElement,&maskImage); + + if(error) { + icns_print_err("icns_get_image32_with_mask_from_family: Unable to load mask image data from icon element!\n"); + goto cleanup; + } + + if(iconImage.imageWidth != maskImage.imageWidth) { + icns_print_err("icns_get_image32_with_mask_from_family: icon and mask widths do not match! (%d != %d)\n",iconImage.imageWidth,maskImage.imageHeight); + goto cleanup; + } + + if(iconImage.imageHeight != maskImage.imageHeight) { + icns_print_err("icns_get_image32_with_mask_from_family: icon and mask heights do not match! (%d != %d)\n",iconImage.imageHeight,maskImage.imageHeight); + goto cleanup; + } + + // Unpack image pixels if depth is < 32 + if((iconImage.imagePixelDepth * iconImage.imageChannels) < 32) + { + icns_byte_t *oldData = NULL; + icns_byte_t *newData = NULL; + icns_uint32_t oldBitDepth = 0; + unsigned long newBlockSize = 0; + unsigned long newDataSize = 0; + icns_colormap_rgb_t colorRGB; + + oldBitDepth = (iconImage.imagePixelDepth * iconImage.imageChannels); + + pixelCount = iconImage.imageWidth * iconImage.imageHeight; + + newBlockSize = iconImage.imageWidth * 32; + newDataSize = newBlockSize * iconImage.imageHeight; + + oldData = iconImage.imageData; + newData = (icns_byte_t *)malloc(newDataSize); + + if(newData == NULL) + { + icns_print_err("icns_get_image32_with_mask_from_family: Unable to allocate memory block of size: %d!\n",(int)newDataSize); + return ICNS_STATUS_NO_MEMORY; + } + + dataCount = 0; + + // 8-Bit Icon Image Data Types + if((iconType == ICNS_48x48_8BIT_DATA) || \ + (iconType == ICNS_32x32_8BIT_DATA) || \ + (iconType == ICNS_16x16_8BIT_DATA) || \ + (iconType == ICNS_16x12_8BIT_DATA) ) + { + if(oldBitDepth != 8) + { + icns_print_err("icns_get_image32_with_mask_from_family: Invalid bit depth - type mismatch!\n"); + free(newData); + error = ICNS_STATUS_INVALID_DATA; + goto cleanup; + } + for(pixelID = 0; pixelID < pixelCount; pixelID++) + { + colorIndex = oldData[dataCount++]; + colorRGB = icns_colormap_8[colorIndex]; + newData[pixelID * 4 + 0] = colorRGB.r; + newData[pixelID * 4 + 1] = colorRGB.g; + newData[pixelID * 4 + 2] = colorRGB.b; + newData[pixelID * 4 + 3] = 0xff; + } + } + // 4-Bit Icon Image Data Types + else if((iconType == ICNS_48x48_4BIT_DATA) || \ + (iconType == ICNS_32x32_4BIT_DATA) || \ + (iconType == ICNS_16x16_4BIT_DATA) || \ + (iconType == ICNS_16x12_4BIT_DATA) ) + { + if(oldBitDepth != 4) + { + icns_print_err("icns_get_image32_with_mask_from_family: Invalid bit depth - type mismatch!\n"); + free(newData); + error = ICNS_STATUS_INVALID_DATA; + goto cleanup; + } + for(pixelID = 0; pixelID < pixelCount; pixelID++) + { + if(pixelID % 2 == 0) + dataValue = oldData[dataCount++]; + colorIndex = (dataValue & 0xF0) >> 4; + dataValue = dataValue << 4; + colorRGB = icns_colormap_4[colorIndex]; + newData[pixelID * 4 + 0] = colorRGB.r; + newData[pixelID * 4 + 1] = colorRGB.g; + newData[pixelID * 4 + 2] = colorRGB.b; + newData[pixelID * 4 + 3] = 0xFF; + } + } + // 1-Bit Icon Image Data Types + else if((iconType == ICNS_48x48_1BIT_DATA) || \ + (iconType == ICNS_32x32_1BIT_DATA) || \ + (iconType == ICNS_16x16_1BIT_DATA) || \ + (iconType == ICNS_16x12_1BIT_DATA) ) + { + if(oldBitDepth != 1) + { + icns_print_err("icns_get_image32_with_mask_from_family: Invalid bit depth - type mismatch!\n"); + free(newData); + error = ICNS_STATUS_INVALID_DATA; + goto cleanup; + } + for(pixelID = 0; pixelID < pixelCount; pixelID++) + { + if(pixelID % 8 == 0) + dataValue = oldData[dataCount++]; + colorIndex = (dataValue & 0x80) ? 0x00 : 0xFF; + dataValue = dataValue << 1; + newData[pixelID * 4 + 0] = colorIndex; + newData[pixelID * 4 + 1] = colorIndex; + newData[pixelID * 4 + 2] = colorIndex; + newData[pixelID * 4 + 3] = 0xFF; + } + } + else + { + char typeStr[5]; + icns_print_err("icns_get_image32_with_mask_from_family: Unpack error - unknown icon type! ('%s')\n",icns_type_str(iconType,typeStr)); + free(newData); + error = ICNS_STATUS_INVALID_DATA; + goto cleanup; + } + + iconImage.imagePixelDepth = 8; + iconImage.imageChannels = 4; + iconImage.imageDataSize = newDataSize; + iconImage.imageData = newData; + + free(oldData); + } + + // 8-Bit Icon Mask Data Types + if((maskType == ICNS_128X128_8BIT_MASK) || \ + (maskType == ICNS_48x48_8BIT_MASK) || \ + (maskType == ICNS_32x32_8BIT_MASK) || \ + (maskType == ICNS_16x16_8BIT_MASK) ) + { + pixelCount = maskImage.imageWidth * maskImage.imageHeight; + dataCount = 0; + if((maskImage.imagePixelDepth * maskImage.imageChannels) != 8) + { + icns_print_err("icns_get_image32_with_mask_from_family: Invalid bit depth - mismatch!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto cleanup; + } + for(pixelID = 0; pixelID < pixelCount; pixelID++) + { + iconImage.imageData[pixelID * 4 + 3] = maskImage.imageData[dataCount++]; + } + } + // 1-Bit Icon Mask Data Types + else if((maskType == ICNS_48x48_1BIT_MASK) || \ + (maskType == ICNS_32x32_1BIT_MASK) || \ + (maskType == ICNS_16x16_1BIT_MASK) || \ + (maskType == ICNS_16x12_1BIT_MASK) ) + { + pixelCount = maskImage.imageWidth * maskImage.imageHeight; + dataCount = 0; + if((maskImage.imagePixelDepth * maskImage.imageChannels) != 1) + { + icns_print_err("icns_get_image32_with_mask_from_family: Invalid bit depth - mismatch!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto cleanup; + } + for(pixelID = 0; pixelID < pixelCount; pixelID++) + { + if(pixelID % 8 == 0) + dataValue = maskImage.imageData[dataCount++]; + colorIndex = (dataValue & 0x80) ? 0xFF : 0x00; + dataValue = dataValue << 1; + iconImage.imageData[pixelID * 4 + 3] = colorIndex; + } + } + else + { + char typeStr[5]; + icns_print_err("icns_get_image32_with_mask_from_family: Unpack error - unknown mask type! ('%s')\n",icns_type_str(maskType,typeStr)); + error = ICNS_STATUS_INVALID_DATA; + goto cleanup; + } + +cleanup: + + if(maskElement != NULL) { + free(maskElement); + maskElement = NULL; + } + icns_free_image(&maskImage); + + if(iconElement != NULL) { + free(iconElement); + iconElement = NULL; + } + + // We only free the icon image if there was an error. Otherwise, we + // pass the data onto the outgoing image + if(error) { + icns_free_image(&iconImage); + } else { + memcpy(imageOut,&iconImage,sizeof(icns_image_t)); + #ifdef ICNS_DEBUG + printf("Finished 32-bit image...\n"); + printf(" height: %d\n",imageOut->imageHeight); + printf(" width: %d\n",imageOut->imageHeight); + printf(" channels: %d\n",imageOut->imageChannels); + printf(" pixel depth: %d\n",imageOut->imagePixelDepth); + printf(" data size: %d\n",(int)(imageOut->imageDataSize)); + #endif + } + + return error; +} + + +//***************************** icns_get_image_from_element **************************// +// Actual conversion of the icon data into uncompressed raw pixels + +int icns_get_image_from_element(icns_element_t *iconElement,icns_image_t *imageOut) +{ + int error = ICNS_STATUS_OK; + unsigned long dataCount = 0; + icns_type_t elementType = ICNS_NULL_TYPE; + icns_size_t elementSize = 0; + icns_type_t iconType = ICNS_NULL_TYPE; + unsigned long rawDataSize = 0; + icns_byte_t *rawDataPtr = NULL; + icns_uint32_t iconBitDepth = 0; + unsigned long iconDataRowSize = 0; + + if(iconElement == NULL) + { + icns_print_err("icns_get_image_from_element: Icon element is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(imageOut == NULL) + { + icns_print_err("icns_get_image_from_element: Icon image structure is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + elementType = iconElement->elementType; + elementSize = iconElement->elementSize; + + #if ICNS_DEBUG + { + char typeStr[5]; + printf("Retreiving image from icon element...\n"); + printf(" type is: '%s'\n",icns_type_str(elementType,typeStr)); + printf(" size is: %d\n",(int)elementSize); + } + #endif + + if(elementSize <= 8) + { + icns_print_err("icns_get_image_from_element: Invalid element size! (%d)\n",elementSize); + return ICNS_STATUS_INVALID_DATA; + } + + iconType = elementType; + rawDataSize = elementSize - sizeof(icns_type_t) - sizeof(icns_size_t); + rawDataPtr = (icns_byte_t*)&(iconElement->elementData[0]); + + #if ICNS_DEBUG + printf(" data size is: %d\n",(int)rawDataSize); + #endif + + switch(iconType) + { + // 32-Bit Icon Image Data Types ( > 256px ) + case ICNS_256x256_32BIT_ARGB_DATA: + case ICNS_512x512_32BIT_ARGB_DATA: + case ICNS_1024x1024_32BIT_ARGB_DATA: + { + uint8_t magicPNG[] = {0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A}; + uint8_t magicByt[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + + ICNS_READ_UNALIGNED(magicByt[0], rawDataPtr, 8); + + // 256x256+ sizes may or may not be PNG dta as of 10.7 Lion, so check + if(memcmp(&magicByt[0], &magicPNG[0], 8) == 0) { + // We know to use the PNG processor + error = icns_png_to_image((int)rawDataSize, (icns_byte_t *)rawDataPtr, imageOut); + } else { + // We assume use of the jp2 processor + error = icns_jp2_to_image((int)rawDataSize, (icns_byte_t *)rawDataPtr, imageOut); + } + return error; + } + case ICNS_128X128_32BIT_DATA: + case ICNS_48x48_32BIT_DATA: + case ICNS_32x32_32BIT_DATA: + case ICNS_16x16_32BIT_DATA: + + error = icns_init_image_for_type(iconType,imageOut); + if(error) + { + icns_print_err("icns_get_image_from_element: Error allocating new icns image!\n"); + icns_free_image(imageOut); + return error; + } + + iconBitDepth = imageOut->imagePixelDepth * imageOut->imageChannels; + iconDataRowSize = imageOut->imageWidth * iconBitDepth / ICNS_BYTE_BITS; + + if(rawDataSize < imageOut->imageDataSize) + { + icns_uint32_t pixelCount = 0; + icns_size_t decodedDataSize = imageOut->imageDataSize; + icns_byte_t *decodedImageData = imageOut->imageData; + + pixelCount = imageOut->imageWidth * imageOut->imageHeight; + error = icns_decode_rle24_data(rawDataSize,rawDataPtr,pixelCount,&decodedDataSize,&decodedImageData); + if(error) + { + icns_print_err("icns_get_image_from_element: Error decoding RLE data!\n"); + icns_free_image(imageOut); + return error; + } + else + { + imageOut->imageDataSize = decodedDataSize; + imageOut->imageData = decodedImageData; + } + } + else + { + unsigned long pixelCount = 0; + icns_byte_t *swapPtr = NULL; + icns_argb_t *pixelPtr = NULL; + + for(dataCount = 0; dataCount < imageOut->imageHeight; dataCount++) + memcpy(&(((char*)(imageOut->imageData))[dataCount*iconDataRowSize]),&(((char*)(rawDataPtr))[dataCount*iconDataRowSize]),iconDataRowSize); + + pixelCount = imageOut->imageWidth * imageOut->imageHeight; + #ifdef ICNS_DEBUG + printf("Converting %d pixels from argb to rgba\n",(int)pixelCount); + #endif + swapPtr = imageOut->imageData; + for(dataCount = 0; dataCount < pixelCount; dataCount++) + { + pixelPtr = (icns_argb_t *)(swapPtr + (dataCount * 4)); + *((icns_rgba_t *)pixelPtr) = ICNS_ARGB_TO_RGBA( *((icns_argb_t *)pixelPtr) ); + } + } + break; + case ICNS_48x48_8BIT_DATA: + case ICNS_32x32_8BIT_DATA: + case ICNS_16x16_8BIT_DATA: + case ICNS_16x12_8BIT_DATA: + case ICNS_48x48_4BIT_DATA: + case ICNS_32x32_4BIT_DATA: + case ICNS_16x16_4BIT_DATA: + case ICNS_16x12_4BIT_DATA: + case ICNS_48x48_1BIT_DATA: + case ICNS_32x32_1BIT_DATA: + case ICNS_16x16_1BIT_DATA: + case ICNS_16x12_1BIT_DATA: + + error = icns_init_image_for_type(iconType,imageOut); + if(error) + { + icns_print_err("icns_get_image_from_element: Error allocating new icns image!\n"); + icns_free_image(imageOut); + return error; + } + + iconBitDepth = imageOut->imagePixelDepth * imageOut->imageChannels; + iconDataRowSize = imageOut->imageWidth * iconBitDepth / ICNS_BYTE_BITS; + + for(dataCount = 0; dataCount < imageOut->imageHeight; dataCount++) + memcpy(&(((char*)(imageOut->imageData))[dataCount*iconDataRowSize]),&(((char*)(rawDataPtr))[dataCount*iconDataRowSize]),iconDataRowSize); + break; + default: + { + char typeStr[5]; + icns_print_err("icns_get_image_from_element: Unknown icon type! ('%s')\n",icns_type_str(iconType,typeStr)); + icns_free_image(imageOut); + } + return ICNS_STATUS_INVALID_DATA; + } + + return error; +} + +//***************************** icns_get_mask_from_element **************************// +// Actual conversion of the mask data into uncompressed raw pixels + +int icns_get_mask_from_element(icns_element_t *maskElement,icns_image_t *imageOut) +{ + int error = ICNS_STATUS_OK; + unsigned long dataCount = 0; + icns_type_t elementType = ICNS_NULL_TYPE; + icns_size_t elementSize = 0; + icns_type_t maskType = ICNS_NULL_TYPE; + unsigned long rawDataSize = 0; + icns_byte_t *rawDataPtr = NULL; + icns_uint32_t maskBitDepth = 0; + unsigned long maskDataSize = 0; + unsigned long maskDataRowSize = 0; + + if(maskElement == NULL) + { + icns_print_err("icns_get_mask_from_element: Mask element is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(imageOut == NULL) + { + icns_print_err("icns_get_mask_from_element: Mask image structure is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + elementType = maskElement->elementType; + elementSize = maskElement->elementSize; + + #if ICNS_DEBUG + { + char typeStr[5]; + printf("Retreiving image from mask element...\n"); + printf(" type is: '%s'\n",icns_type_str(elementType,typeStr)); + printf(" size is: %d\n",(int)elementSize); + } + #endif + + if(elementSize <= 8) + { + icns_print_err("icns_get_image_from_element: Invalid element size! (%d)\n",elementSize); + return ICNS_STATUS_INVALID_DATA; + } + + maskType = elementType; + rawDataSize = elementSize - sizeof(icns_type_t) - sizeof(icns_size_t); + rawDataPtr = (icns_byte_t*)&(maskElement->elementData[0]); + + #if ICNS_DEBUG + printf(" data size is: %d\n",(int)rawDataSize); + #endif + + switch(maskType) + { + case ICNS_128X128_8BIT_MASK: + case ICNS_48x48_8BIT_MASK: + case ICNS_32x32_8BIT_MASK: + case ICNS_16x16_8BIT_MASK: + + error = icns_init_image_for_type(maskType,imageOut); + if(error) + { + icns_print_err("icns_get_mask_from_element: Error allocating new icns image!\n"); + icns_free_image(imageOut); + return error; + } + + maskBitDepth = imageOut->imagePixelDepth * imageOut->imageChannels; + + if(maskBitDepth != 8) { + icns_print_err("icns_get_mask_from_element: Unknown bit depth!\n"); + icns_free_image(imageOut); + return ICNS_STATUS_INVALID_DATA; + } + + maskDataSize = imageOut->imageDataSize; + maskDataRowSize = imageOut->imageWidth * maskBitDepth / ICNS_BYTE_BITS; + + for(dataCount = 0; dataCount < imageOut->imageHeight; dataCount++) + memcpy(&(((char*)(imageOut->imageData))[dataCount*maskDataRowSize]),&(((char*)(rawDataPtr))[dataCount*maskDataRowSize]),maskDataRowSize); + + break; + case ICNS_48x48_1BIT_MASK: + case ICNS_32x32_1BIT_MASK: + case ICNS_16x16_1BIT_MASK: + case ICNS_16x12_1BIT_MASK: + + error = icns_init_image_for_type(maskType,imageOut); + if(error) + { + icns_print_err("icns_get_mask_from_element: Error allocating new icns image!\n"); + icns_free_image(imageOut); + return error; + } + + maskBitDepth = imageOut->imagePixelDepth * imageOut->imageChannels; + + if(maskBitDepth != 1) { + icns_print_err("icns_get_mask_from_element: Unknown bit depth!\n"); + icns_free_image(imageOut); + return ICNS_STATUS_INVALID_DATA; + } + + maskDataSize = imageOut->imageDataSize; + maskDataRowSize = imageOut->imageWidth * maskBitDepth / ICNS_BYTE_BITS; + + #if ICNS_DEBUG + printf(" raw mask data size is: %d\n",(int)rawDataSize); + printf(" image mask data size is: %d\n",(int)maskDataSize); + #endif + + if(rawDataSize == (maskDataSize * 2) ) + { + #if ICNS_DEBUG + printf(" mask data in second memory block\n"); + #endif + // Mask data found - Copy the second block of memory + for(dataCount = 0; dataCount < imageOut->imageHeight; dataCount++) + memcpy(&(((char*)(imageOut->imageData))[dataCount*maskDataRowSize]),&(((char*)(rawDataPtr))[dataCount*maskDataRowSize+maskDataSize]),maskDataRowSize); + } + else + { + #if ICNS_DEBUG + printf(" using icon data from first memory block\n"); + #endif + // Hmm, no mask - copy the first block of memory + for(dataCount = 0; dataCount < imageOut->imageHeight; dataCount++) + memcpy(&(((char*)(imageOut->imageData))[dataCount*maskDataRowSize]),&(((char*)(rawDataPtr))[dataCount*maskDataRowSize]),maskDataRowSize); + } + + break; + default: + { + char typeStr[5]; + icns_print_err("icns_get_mask_from_element: Unknown mask type! ('%s')\n",icns_type_str(maskType,typeStr)); + icns_free_image(imageOut); + } + return ICNS_STATUS_INVALID_DATA; + } + + return error; +} + + + +//***************************** icns_init_image_for_type **************************// +// Initialize a new image structure for holding the data +// using the information for the specified type + +int icns_init_image_for_type(icns_type_t iconType,icns_image_t *imageOut) +{ + icns_icon_info_t iconInfo; + + if(imageOut == NULL) + { + icns_print_err("icns_init_image_for_type: Icon image structure is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + // Determine what the height and width ought to be, to check the incoming image + + iconInfo = icns_get_image_info_for_type(iconType); + + if(iconType != iconInfo.iconType) + { + char typeStr[5]; + icns_print_err("icns_init_image_for_type: Couldn't determine information for type! ('%s')\n",icns_type_str(iconType,typeStr)); + return ICNS_STATUS_INVALID_DATA; + } + + return icns_init_image(iconInfo.iconWidth,iconInfo.iconHeight,iconInfo.iconChannels,iconInfo.iconPixelDepth,imageOut); + +} + +//***************************** icns_init_image **************************// +// Initialize a new image structure for holding the data + +int icns_init_image(icns_uint32_t iconWidth,icns_uint32_t iconHeight,icns_uint32_t iconChannels,icns_uint32_t iconPixelDepth,icns_image_t *imageOut) +{ + icns_uint32_t iconBitDepth = 0; + unsigned long iconDataSize = 0; + unsigned long iconDataRowSize = 0; + + if(imageOut == NULL) + { + icns_print_err("icns_init_image: Icon image structure is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconWidth == 0) + { + icns_print_err("icns_init_image: icon width is 0!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + if(iconHeight == 0) + { + icns_print_err("icns_init_image: icon height is 0!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + if(iconChannels == 0) + { + icns_print_err("icns_init_image: icon channels is 0!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + if(iconPixelDepth == 0) + { + icns_print_err("icns_init_image: icon pixel depth is 0!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + iconBitDepth = iconPixelDepth * iconChannels; + iconDataRowSize = iconWidth * iconBitDepth / ICNS_BYTE_BITS; + iconDataSize = iconHeight * iconDataRowSize; + + #ifdef ICNS_DEBUG + printf("Initializing new image...\n"); + printf(" width is: %d\n",iconWidth); + printf(" height is: %d\n",iconHeight); + printf(" channels are: %d\n",iconChannels); + printf(" bit depth is: %d\n",iconBitDepth); + printf(" data size is: %d\n",(int)iconDataSize); + #endif + + imageOut->imageWidth = iconWidth; + imageOut->imageHeight = iconHeight; + imageOut->imageChannels = iconChannels; + imageOut->imagePixelDepth = (iconBitDepth / iconChannels); + imageOut->imageDataSize = iconDataSize; + imageOut->imageData = (icns_byte_t *)malloc(iconDataSize); + if(!imageOut->imageData) + { + icns_print_err("icns_init_image: Unable to allocate memory block of size: %d ($s:%m)!\n",(int)iconDataSize); + return ICNS_STATUS_NO_MEMORY; + } + memset(imageOut->imageData,0,iconDataSize); + + return ICNS_STATUS_OK; +} + +//***************************** icns_free_image **************************// +// Deallocate data in an image structure + +int icns_free_image(icns_image_t *imageIn) +{ + imageIn->imageWidth = 0; + imageIn->imageHeight = 0; + imageIn->imageChannels = 0; + imageIn->imagePixelDepth = 0; + imageIn->imageDataSize = 0; + + if(imageIn->imageData != NULL) + { + free(imageIn->imageData); + imageIn->imageData = NULL; + } + + return ICNS_STATUS_OK; +} + diff --git a/src/add-ons/translators/icns/libicns/icns_internals.h b/src/add-ons/translators/icns/libicns/icns_internals.h new file mode 100644 index 0000000000..4775c850b5 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_internals.h @@ -0,0 +1,207 @@ +/* +File: icns.h +Copyright (C) 2001-2012 Mathew Eis +Copyright (C) 2002 Chenxiao Zhao + +With the exception of the limited portions mentiond, this library +is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published +by the Free Software Foundation; either version 2.1 of the License, +or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" + +#include "config.h" + +#ifndef _ICNS_INTERNALS_H_ +#define _ICNS_INTERNALS_H_ + +/* Compile-time variables */ +/* These should really be set from the Makefile */ + +// Enable debugging messages? +// #define ICNS_DEBUG 1 + +// Enable supprt for 256x256, 512x512 and 1024x1024 icons +// Use either Jasper or OpenJPEG, but not both +// #define ICNS_JASPER +// #define ICNS_OPENJPEG + +/* Make sure we're not using both libraries */ +#if defined(ICNS_JASPER) && defined(ICNS_OPENJPEG) + #error "Must use either Jasper or OpenJPEG, but not both!" +#endif + +/* Include Jasper headers */ +#ifdef ICNS_JASPER +#include +#endif + +/* Include OpenJPEG headers */ +#ifdef ICNS_OPENJPEG +#include +#endif + +// We do not want to expose any of the internal stuff +#pragma GCC visibility push(hidden) + +/* icns structures */ + +typedef struct icns_rgba_t +{ + icns_byte_t r; + icns_byte_t g; + icns_byte_t b; + icns_byte_t a; +} icns_rgba_t; + +typedef struct icns_argb_t +{ + icns_byte_t a; + icns_byte_t r; + icns_byte_t g; + icns_byte_t b; +} icns_argb_t; + +typedef struct icns_rgb_t +{ + icns_byte_t r; + icns_byte_t g; + icns_byte_t b; +} icns_rgb_t; + +/* icns constants */ + + +typedef enum icns_rsrc_endian_t +{ + ICNS_BE_RSRC = 0, + ICNS_LE_RSRC = 1 +} icns_rsrc_endian_t; + +#define ICNS_BYTE_BITS 8 + +#define ICNS_APPLE_SINGLE_MAGIC 0x00051600 +#define ICNS_APPLE_DOUBLE_MAGIC 0x00051607 + +#define ICNS_APPLE_ENC_DATA 1 +#define ICNS_APPLE_ENC_RSRC 2 + +/* icns macros */ + +/* +These functions swap the position of the alpha channel +*/ +static inline icns_rgba_t ICNS_ARGB_TO_RGBA(icns_argb_t pxin) { + icns_rgba_t pxout; + pxout.r = pxin.r; + pxout.g = pxin.g; + pxout.b = pxin.b; + pxout.a = pxin.a; + return pxout; +} + +static inline icns_argb_t ICNS_RGBA_TO_ARGB(icns_rgba_t pxin) { + icns_argb_t pxout; + pxout.r = pxin.r; + pxout.g = pxin.g; + pxout.b = pxin.b; + pxout.a = pxin.a; + return pxout; +} + +/* +These macros will work on systems that support unaligned +accesses, as well as those that don't support it. +Unfortunately, gcc doesn't support unaligned access well +with memcpy on some architectures due to a combination of +memcpy being inlined during the optimization process and +memory alignment. So, we try to work around this here. +*/ + +// If the autotools didn't tell us, try and make a good guess +#ifndef HAVE_UNALIGNED_MEMCPY + #if defined(__GNUC__) && (defined(__arm__) || defined(__thumb__) || defined(__sparc__)) + #define HAVE_UNALIGNED_MEMCPY 0 + #else + #define HAVE_UNALIGNED_MEMCPY 1 + #endif +#endif + +// Set up the macros +#if HAVE_UNALIGNED_MEMCPY == 0 + __attribute__ ((noinline)) void *icns_memcpy( void *dst, const void *src, size_t num ); + #define ICNS_READ_UNALIGNED(val, addr, size) icns_memcpy(&(val), (addr), size) + #define ICNS_WRITE_UNALIGNED(addr, val, size) icns_memcpy((addr), &(val), size) +#else + #define ICNS_READ_UNALIGNED(val, addr, size) memcpy(&(val), (addr), size) + #define ICNS_WRITE_UNALIGNED(addr, val, size) memcpy((addr), &(val), size) +#endif + +/* global variables */ +extern icns_bool_t gShouldPrintErrors; + +/* icns function prototypes */ + +// icns_debug.c +void bin_print_byte(int x); +void bin_print_int(int x); + +// icns_element.c +int icns_new_element_from_image_or_mask(icns_image_t *imageIn,icns_type_t iconType,icns_bool_t isMask,icns_element_t **iconElementOut); +int icns_update_element_with_image_or_mask(icns_image_t *imageIn,icns_bool_t isMask,icns_element_t **iconElement); + +// icns_io.c +int icns_parse_family_data(icns_size_t dataSize,icns_byte_t *data,icns_family_t **iconFamilyOut); +int icns_find_family_in_mac_resource(icns_size_t resDataSize, icns_byte_t *resData, icns_rsrc_endian_t fileEndian, icns_family_t **dataOut); +int icns_read_macbinary_resource_fork(icns_size_t dataSize,icns_byte_t *dataPtr,icns_type_t *dataTypeOut, icns_type_t *dataCreatorOut,icns_size_t *parsedResSizeOut,icns_byte_t **parsedResDataOut); +int icns_read_apple_encoded_resource_fork(icns_size_t dataSize,icns_byte_t *dataPtr,icns_type_t *dataTypeOut, icns_type_t *dataCreatorOut,icns_size_t *parsedResSizeOut,icns_byte_t **parsedResDataOut); +icns_bool_t icns_icns_header_check(icns_size_t dataSize,icns_byte_t *dataPtr); +icns_bool_t icns_rsrc_header_check(icns_size_t dataSize,icns_byte_t *dataPtr,icns_rsrc_endian_t fileEndian); +icns_bool_t icns_macbinary_header_check(icns_size_t dataSize,icns_byte_t *dataPtr); +icns_bool_t icns_apple_encoded_header_check(icns_size_t dataSize,icns_byte_t *dataPtr); + +// icns_png.c +int icns_image_to_png(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut); +int icns_png_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut); + +// icns_jp2.c +#ifdef ICNS_JASPER +int icns_jas_jp2_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut); +int icns_jas_image_to_jp2(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut); +#endif +#ifdef ICNS_OPENJPEG +int icns_opj_jp2_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut); +int icns_opj_jp2_dec(icns_size_t dataSize, icns_byte_t *dataPtr, opj_image_t **imageOut); +int icns_opj_to_image(opj_image_t *image, icns_image_t *outIcon); +int icns_opj_image_to_jp2(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut); +void icns_opj_error_callback(const char *msg, void *client_data); +void icns_opj_warning_callback(const char *msg, void *client_data); +void icns_opj_info_callback(const char *msg, void *client_data); +#endif +void icns_place_jp2_cdef(icns_byte_t *dataPtr, icns_size_t dataSize); + +// icns_utils.c +icns_uint32_t icns_get_element_order(icns_type_t iconType); +void icns_print_err(const char *template, ...); + +// Stop hiding symbols +#pragma GCC visibility pop + +#endif /* _ICNS_INTERNALS_H_ */ diff --git a/src/add-ons/translators/icns/libicns/icns_io.c b/src/add-ons/translators/icns/libicns/icns_io.c new file mode 100644 index 0000000000..f2b624f701 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_io.c @@ -0,0 +1,1522 @@ +/* +File: icns_io.c +Copyright (C) 2001-2012 Mathew Eis + 2007 Thomas Lübking + 2002 Chenxiao Zhao + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" + +/***************************** ICNS_MEMCPY **************************/ +#if HAVE_UNALIGNED_MEMCPY == 0 +__attribute__ ((noinline)) void *icns_memcpy( void *dst, const void *src, size_t num ) { + return memcpy(dst,src,num); +} +#endif + +/***************************** ICNS_READ_UNALIGNED_BE **************************/ +/* NOTE: only accessible to icns_io.c */ +#define ICNS_READ_UNALIGNED_BE(val, addr, size) icns_read_be(&(val), (addr), (size)) +static inline void icns_read_be(void *outp, void *inp, int size) +{ + icns_byte_t b[8] = {0,0,0,0,0,0,0,0}; + + if(outp == NULL) + return; + + if(inp == NULL) + return; + + memcpy(&b, inp, size); + + #ifdef ICNS_DEBUG + int i = 0; + printf("Reading %d bytes: ",size); + for(i = 0; i < size; i++) + printf("0x%02X ",b[i]); + printf("\n"); + #endif + + switch(size) + { + case 1: + *((uint8_t *)(outp)) = b[0]; + break; + case 2: + *((uint16_t *)(outp)) = b[1]|b[0]<< 8; + break; + case 4: + *((uint32_t *)(outp)) = b[3]|b[2]<<8| \ + b[1]<<16|b[0]<<24; + break; + case 8: + *((uint64_t *)(outp)) = b[7]|b[6]<<8| \ + b[5]<<16|b[4]<<24| \ + (uint64_t)b[3]<<32|(uint64_t)b[2]<<40| \ + (uint64_t)b[1]<<48|(uint64_t)b[0]<<56; + break; + + // This is a special case needed by icns_read_macbinary_resource_fork + case 3: + *((uint32_t *)(outp)) = ((uint16_t)b[2]|(uint16_t)b[1]<<8|(uint16_t)b[0]<<16) & 0x00FFFFFF; + break; + + default: + break; + } +} + +#define ICNS_READ_UNALIGNED_LE(val, addr, size) icns_read_le(&(val), (addr), (size)) +static inline void icns_read_le(void *outp, void *inp, int size) +{ + icns_byte_t b[8] = {0,0,0,0,0,0,0,0}; + + if(outp == NULL) + return; + + if(inp == NULL) + return; + + memcpy(&b, inp, size); + + #ifdef ICNS_DEBUG + int i = 0; + printf("Reading %d bytes: ",size); + for(i = 0; i < size; i++) + printf("0x%02X ",b[i]); + printf("\n"); + #endif + + switch(size) + { + case 1: + *((uint8_t *)(outp)) = b[0]; + break; + case 2: + *((uint16_t *)(outp)) = b[0]|b[1]<< 8; + break; + case 4: + *((uint32_t *)(outp)) = b[0]|b[1]<<8| b[2]<<16|b[3]<<24; + break; + case 8: + *((uint64_t *)(outp)) = b[0]|b[1]<<8| b[2]<<16|b[3]<<24| (uint64_t)b[4]<<32|(uint64_t)b[5]<<40| (uint64_t)b[6]<<48|(uint64_t)b[7]<<56; + break; + + // This is a special case needed by icns_read_macbinary_resource_fork + case 3: + *((uint32_t *)(outp)) = ((uint16_t)b[0]|(uint16_t)b[1]<<8|(uint16_t)b[2]<<16) & 0x00FFFFFF; + break; + + default: + break; + } +} + +/***************************** ICNS_WRITE_UNALIGNED_BE **************************/ +/* NOTE: only accessible to icns_io.c */ +#define ICNS_WRITE_UNALIGNED_BE(addr, val, size) icns_write_be((addr), &(val), (size)) +static inline void icns_write_be(void *outp, void *inp, int size) +{ + icns_byte_t b[8] = {0,0,0,0,0,0,0,0}; + + if(outp == NULL) + return; + + if(inp == NULL) + return; + + switch(size) + { + case 1: + { + uint8_t v = *((uint8_t *)inp); + b[0] = v; + } + break; + case 2: + { + uint16_t v = *((uint16_t *)inp); + b[0] = v >> 8; + b[1] = v; + } + break; + case 4: + { + uint32_t v = *((uint32_t *)inp); + b[0] = v >> 24; + b[1] = v >> 16; + b[2] = v >> 8; + b[3] = v; + } + break; + case 8: + { + uint64_t v = *((uint64_t *)inp); + b[0] = v >> 56; + b[1] = v >> 48; + b[2] = v >> 40; + b[3] = v >> 32; + b[4] = v >> 24; + b[5] = v >> 16; + b[6] = v >> 8; + b[7] = v; + } + break; + default: + break; + } + + #ifdef ICNS_DEBUG + int i = 0; + printf("Writing %d bytes: ",size); + for(i = 0; i < size; i++) + printf("0x%02X ",b[i]); + printf("\n"); + #endif + + memcpy(outp, &b, size); +} + +/***************************** icns_write_family_to_file **************************/ + +int icns_write_family_to_file(FILE *dataFile,icns_family_t *iconFamilyIn) +{ + int error = ICNS_STATUS_OK; + icns_size_t blockSize = 0; + icns_size_t blockCount = 0; + icns_size_t blocksWritten = 0; + icns_size_t dataWritten = 0; + icns_size_t dataSize = 0; + icns_byte_t *dataPtr = NULL; + + if( dataFile == NULL ) + { + icns_print_err("icns_write_family_to_file: NULL file pointer!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if( iconFamilyIn == NULL ) + { + icns_print_err("icns_write_family_to_file: NULL icns family!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + error = icns_export_family_data(iconFamilyIn,&dataSize,&dataPtr); + + if(error != ICNS_STATUS_OK) + return error; + + #ifdef ICNS_DEBUG + printf("Writing icon family data to file...\n"); + printf(" total data size: %d (0x%08X)\n",(int)dataSize,dataSize); + #endif + + blockSize = 1024; + blockCount = dataSize / blockSize; + + blocksWritten = fwrite ( dataPtr , blockSize , blockCount , dataFile ); + + if(blocksWritten < blockCount) + { + icns_print_err("icns_write_family_to_file: Error writing icns to file!\n"); + return ICNS_STATUS_IO_WRITE_ERR; + } + + dataWritten = (blockCount * blockSize); + blockSize = dataSize - (blockCount * blockSize); + blocksWritten = fwrite ( dataPtr + dataWritten , blockSize , 1 , dataFile ); + + if(blocksWritten != 1) + { + icns_print_err("icns_write_family_to_file: Error writing icns to file!\n"); + return ICNS_STATUS_IO_WRITE_ERR; + } + + free(dataPtr); + + return ICNS_STATUS_OK; +} + + +/***************************** icns_read_family_from_file **************************/ + +int icns_read_family_from_file(FILE *dataFile,icns_family_t **iconFamilyOut) +{ + int error = ICNS_STATUS_OK; + icns_uint32_t dataSize = 0; + void *dataPtr = NULL; + + if( dataFile == NULL ) + { + icns_print_err("icns_read_family_from_file: NULL file pointer!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if( iconFamilyOut == NULL ) + { + icns_print_err("icns_read_family_from_file: NULL icns family ref!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(fseek(dataFile,0,SEEK_END) == 0) + { + dataSize = ftell(dataFile); + rewind(dataFile); + + dataPtr = (void *)malloc(dataSize); + + if( (error == 0) && (dataPtr != NULL) ) + { + if(fread( dataPtr, sizeof(char), dataSize, dataFile) != dataSize) + { + free( dataPtr ); + dataPtr = NULL; + dataSize = 0; + error = ICNS_STATUS_IO_READ_ERR; + icns_print_err("icns_read_family_from_file: Error occured reading file!\n"); + goto exception; + } + } + else + { + icns_print_err("icns_read_family_from_file: Unable to allocate memory block of size: %d!\n",(int)dataSize); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } + } + else + { + error = ICNS_STATUS_IO_READ_ERR; + icns_print_err("icns_read_family_from_file: Error occured seeking to end of file!\n"); + goto exception; + } + + if(error == 0) + { + // Attempt 1 - try to import as an 'icns' file + if(icns_icns_header_check(dataSize,dataPtr)) + { + #ifdef ICNS_DEBUG + printf("Trying to read from icns file...\n"); + #endif + if((error = icns_parse_family_data(dataSize,dataPtr,iconFamilyOut))) + { + icns_print_err("icns_read_family_from_file: Error parsing icon family data!\n"); + *iconFamilyOut = NULL; + } + else // Success! + { + // icns_parse_family_data points to allocated memory + // clear these out so they won't be freed at the end + dataSize = 0; + dataPtr = NULL; + } + } + // Attempt 2 - try to import from an 'icns' resource in a big endian macintosh resource file + else if(icns_rsrc_header_check(dataSize,dataPtr,ICNS_BE_RSRC)) + { + #ifdef ICNS_DEBUG + printf("Trying to find icns data in resource file...\n"); + #endif + if((error = icns_find_family_in_mac_resource(dataSize,dataPtr,ICNS_BE_RSRC,iconFamilyOut))) + { + icns_print_err("icns_read_family_from_file: Error reading macintosh resource file!\n"); + *iconFamilyOut = NULL; + } + } + // Attempt 3 - try to import from an 'icns' resource in a little endian macintosh resource file + else if(icns_rsrc_header_check(dataSize,dataPtr,ICNS_LE_RSRC)) + { + #ifdef ICNS_DEBUG + printf("Trying to find icns data in resource file...\n"); + #endif + if((error = icns_find_family_in_mac_resource(dataSize,dataPtr,ICNS_LE_RSRC,iconFamilyOut))) + { + icns_print_err("icns_read_family_from_file: Error reading macintosh resource file!\n"); + *iconFamilyOut = NULL; + } + } + // Attempt 4 - try to import from an 'icns' resource in a macbinary resource fork + else if(icns_macbinary_header_check(dataSize,dataPtr)) + { + icns_size_t resourceSize; + icns_byte_t *resourceData; + #ifdef ICNS_DEBUG + printf("Trying to find icns data in macbinary resource fork...\n"); + #endif + if((error = icns_read_macbinary_resource_fork(dataSize,dataPtr,NULL,NULL,&resourceSize,&resourceData))) + { + icns_print_err("icns_read_family_from_file: Error reading macbinary resource fork!\n"); + *iconFamilyOut = NULL; + } + + if(error == 0) + { + if((error = icns_find_family_in_mac_resource(resourceSize,resourceData,ICNS_BE_RSRC,iconFamilyOut))) + { + icns_print_err("icns_read_family_from_file: Error reading icns data from macbinary resource fork!\n"); + *iconFamilyOut = NULL; + } + } + + if(resourceData != NULL) + { + free(resourceData); + resourceData = NULL; + } + } + // Attempt 5 - try to import from an 'icns' resource in a apple encoded resource fork + else if(icns_apple_encoded_header_check(dataSize,dataPtr)) + { + icns_size_t resourceSize; + icns_byte_t *resourceData; + #ifdef ICNS_DEBUG + printf("Trying to find icns data in apple encoded resource fork...\n"); + #endif + if((error = icns_read_apple_encoded_resource_fork(dataSize,dataPtr,NULL,NULL,&resourceSize,&resourceData))) + { + icns_print_err("icns_read_family_from_file: Error reading macbinary resource fork!\n"); + *iconFamilyOut = NULL; + } + + if(error == 0) + { + if((error = icns_find_family_in_mac_resource(resourceSize,resourceData,ICNS_BE_RSRC,iconFamilyOut))) + { + icns_print_err("icns_read_family_from_file: Error reading icns data from macbinary resource fork!\n"); + *iconFamilyOut = NULL; + } + } + + if(resourceData != NULL) + { + free(resourceData); + resourceData = NULL; + } + } + // All attempts failed + else + { + icns_print_err("icns_read_family_from_file: Error reading icns file - all parsing methods failed!\n"); + *iconFamilyOut = NULL; + error = ICNS_STATUS_INVALID_DATA; + } + + } + +exception: + + if(dataPtr != NULL) + { + free(dataPtr); + dataPtr = NULL; + } + + return error; +} + +/***************************** icns_read_family_from_rsrc **************************/ + +int icns_read_family_from_rsrc(FILE *dataFile,icns_family_t **iconFamilyOut) +{ + int error = ICNS_STATUS_OK; + icns_uint32_t dataSize = 0; + void *dataPtr = NULL; + + if( dataFile == NULL ) + { + icns_print_err("icns_read_family_from_rsrc: NULL file pointer!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if( iconFamilyOut == NULL ) + { + icns_print_err("icns_read_family_from_rsrc: NULL icns family ref!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(fseek(dataFile,0,SEEK_END) == 0) + { + dataSize = ftell(dataFile); + rewind(dataFile); + + dataPtr = (void *)malloc(dataSize); + + if( (error == 0) && (dataPtr != NULL) ) + { + if(fread( dataPtr, sizeof(char), dataSize, dataFile) != dataSize) + { + free( dataPtr ); + dataPtr = NULL; + dataSize = 0; + error = ICNS_STATUS_IO_READ_ERR; + icns_print_err("icns_read_family_from_rsrc: Error occured reading file!\n"); + goto exception; + } + } + else + { + icns_print_err("icns_read_family_from_rsrc: Unable to allocate memory block of size: %d!\n",(int)dataSize); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } + } + else + { + error = ICNS_STATUS_IO_READ_ERR; + icns_print_err("icns_read_family_from_rsrc: Error occured seeking to end of file!\n"); + goto exception; + } + + if(error == 0) + { + // Read from big endian resource file + if(icns_rsrc_header_check(dataSize,dataPtr,ICNS_BE_RSRC)) + { + #ifdef ICNS_DEBUG + printf("Trying to find icns data in big endian mac resource file...\n"); + #endif + if((error = icns_find_family_in_mac_resource(dataSize,dataPtr,ICNS_BE_RSRC,iconFamilyOut))) + { + icns_print_err("icns_read_family_from_rsrc: Error reading macintosh resource file!\n"); + *iconFamilyOut = NULL; + } + } + // Read from little endian resource file + else if(icns_rsrc_header_check(dataSize,dataPtr,ICNS_LE_RSRC)) + { + #ifdef ICNS_DEBUG + printf("Trying to find icns data in little endian mac resource file...\n"); + #endif + if((error = icns_find_family_in_mac_resource(dataSize,dataPtr,ICNS_LE_RSRC,iconFamilyOut))) + { + icns_print_err("icns_read_family_from_rsrc: Error reading macintosh resource file!\n"); + *iconFamilyOut = NULL; + } + } + // All attempts failed + else + { + icns_print_err("icns_read_family_from_rsrc: Error reading rsrc file - all parsing methods failed!\n"); + *iconFamilyOut = NULL; + error = ICNS_STATUS_INVALID_DATA; + } + + } + +exception: + + if(dataPtr != NULL) + { + free(dataPtr); + dataPtr = NULL; + } + + return error; +} + + +/***************************** icns_export_family_data **************************/ + +int icns_export_family_data(icns_family_t *iconFamily,icns_size_t *dataSizeOut,icns_byte_t **dataPtrOut) +{ + int error = ICNS_STATUS_OK; + icns_type_t dataType = ICNS_NULL_TYPE; + icns_size_t dataSize = 0; + icns_byte_t *dataPtr = NULL; + + if(iconFamily == NULL) + { + icns_print_err("icns_export_family_data: icon family is NULL\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataPtrOut == NULL) + { + icns_print_err("icns_export_family_data: data ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + #ifdef ICNS_DEBUG + printf("Writing icns family to data...\n"); + #endif + + // Check the data type + if(iconFamily->resourceType != ICNS_FAMILY_TYPE) + { + icns_print_err("icns_export_family_data: Invalid type in header! (%d)\n",dataSize); + *dataPtrOut = NULL; + return ICNS_STATUS_INVALID_DATA; + } + else + { + dataType = iconFamily->resourceType; + } + + // Check the data size + if(iconFamily->resourceSize < 8) + { + icns_print_err("icns_export_family_data: Invalid size in header! (%d)\n",dataSize); + *dataPtrOut = NULL; + return ICNS_STATUS_INVALID_DATA; + } + else + { + dataSize = iconFamily->resourceSize; + } + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" data type is '%s'\n",icns_type_str(dataType,typeStr)); + printf(" data size is %d\n",dataSize); + } + #endif + + // Allocate a new block of memory for the outgoing data + dataPtr = (icns_byte_t *)malloc(dataSize); + + if(dataPtr == NULL) + { + icns_print_err("icns_import_family_data: Unable to allocate memory block of size: %d!\n",dataSize); + error = ICNS_STATUS_NO_MEMORY; + } + else + { + memcpy( dataPtr, iconFamily, dataSize); + } + + if(error == 0) + { + unsigned long dataOffset = 0; + icns_type_t elementType = ICNS_NULL_TYPE; + icns_size_t elementSize = 0; + + ICNS_WRITE_UNALIGNED_BE(dataPtr, dataType, sizeof(icns_type_t)); + ICNS_WRITE_UNALIGNED_BE(dataPtr + 4, dataSize, sizeof(icns_size_t)); + + // Skip past the icns header + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + // Iterate through the icns resource, converting the 'size' values to big endian + while( ((dataOffset+8) < dataSize) && (error == 0) ) + { + ICNS_READ_UNALIGNED(elementType, dataPtr+dataOffset,sizeof(icns_type_t)); + ICNS_READ_UNALIGNED(elementSize, dataPtr+dataOffset+4,sizeof(icns_size_t)); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" checking element type... type is %s\n",icns_type_str(elementType,typeStr)); + printf(" checking element size... size is %d\n",elementSize); + } + #endif + + if( (elementSize < 8) || (dataOffset+elementSize > dataSize) ) + { + icns_print_err("icns_export_family_data: Invalid element size! (%d)\n",elementSize); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + // Reset the values to big endian + ICNS_WRITE_UNALIGNED_BE( dataPtr+dataOffset, elementType, sizeof(icns_type_t)); + ICNS_WRITE_UNALIGNED_BE( dataPtr+dataOffset+4, elementSize, sizeof(icns_size_t)); + + // Move on to the next element + dataOffset += elementSize; + } + + } + +exception: + + if(error != 0) + { + *dataSizeOut = 0; + *dataPtrOut = NULL; + } + else + { + *dataSizeOut = dataSize; + *dataPtrOut = dataPtr; + } + + return error; +} + +/***************************** icns_import_family_data **************************/ + +int icns_import_family_data(icns_size_t dataSize,icns_byte_t *dataPtr,icns_family_t **iconFamilyOut) +{ + int error = ICNS_STATUS_OK; + icns_byte_t *iconFamilyData; + + if(dataSize < 8) + { + icns_print_err("icns_import_family_data: data size is %d - missing icns header!\n",(int)dataSize); + return ICNS_STATUS_INVALID_DATA; + } + + if(dataPtr == NULL) + { + icns_print_err("icns_import_family_data: data is NULL\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconFamilyOut == NULL) + { + icns_print_err("icns_import_family_data: icon family ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + // icns_parse_family_data is destructive, so we allocate a new block of memory + iconFamilyData = malloc(dataSize); + + if(iconFamilyData != NULL) + { + memcpy( iconFamilyData , dataPtr,dataSize); + if((error = icns_parse_family_data(dataSize,iconFamilyData,iconFamilyOut))) + { + icns_print_err("icns_import_family_data: Error parsing icon family!\n"); + *iconFamilyOut = NULL; + } + } + else + { + icns_print_err("icns_import_family_data: Unable to allocate memory block of size: %d!\n",(int)dataSize); + error = ICNS_STATUS_NO_MEMORY; + *iconFamilyOut = NULL; + } + + return error; +} + +/***************************** icns_parse_family_data **************************/ + +int icns_parse_family_data(icns_size_t dataSize,icns_byte_t *dataPtr,icns_family_t **iconFamilyOut) +{ + int error = ICNS_STATUS_OK; + icns_type_t resourceType = ICNS_NULL_TYPE; + icns_size_t resourceSize = 0; + + if(dataSize < 8) + { + icns_print_err("icns_parse_family_data: data size is %d - missing icns header!\n",(int)dataSize); + return ICNS_STATUS_INVALID_DATA; + } + + if(dataPtr == NULL) + { + icns_print_err("icns_parse_family_data: data is NULL\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconFamilyOut == NULL) + { + icns_print_err("icns_parse_family_data: icon family ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + ICNS_READ_UNALIGNED_BE(resourceType, dataPtr,sizeof(icns_type_t)); + ICNS_READ_UNALIGNED_BE(resourceSize, dataPtr + 4,sizeof(icns_size_t)); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf("Reading icns family from data...\n"); + printf(" resource type is '%s'\n",icns_type_str(resourceType,typeStr)); + printf(" resource size is %d\n",resourceSize); + } + #endif + + if(resourceType == ICNS_FAMILY_TYPE) + { + if( dataSize == resourceSize ) + { + // 'Fix' the values for working with the data later + ICNS_WRITE_UNALIGNED(dataPtr, resourceType, sizeof(icns_type_t)); + ICNS_WRITE_UNALIGNED(dataPtr + 4, resourceSize, sizeof(icns_size_t)); + } + else + { + icns_print_err("icns_parse_family_data: Invalid icon family resource size! (%d)\n",resourceSize); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + } + else + { + char typeStr[5]; + icns_print_err("icns_parse_family_data: Invalid icon family resource type! ('%s')\n",icns_type_str(resourceType,typeStr)); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + if(error == 0) + { + unsigned long dataOffset = 0; + icns_type_t elementType = ICNS_NULL_TYPE; + icns_size_t elementSize = 0; + + // Skip past the icns header + dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); + + // Iterate through the icns resource, converting the 'type' and 'size' values to native endian + while( ((dataOffset+8) < resourceSize) && (error == 0) ) + { + ICNS_READ_UNALIGNED_BE(elementType, dataPtr+dataOffset,sizeof(icns_type_t)); + ICNS_READ_UNALIGNED_BE(elementSize, dataPtr+dataOffset+4,sizeof(icns_size_t)); + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" checking element type... type is '%s'\n",icns_type_str(elementType,typeStr)); + printf(" checking element size... size is %d\n",elementSize); + } + #endif + + if( (elementSize < 8) || (dataOffset+elementSize > resourceSize) ) + { + icns_print_err("icns_parse_family_data: Invalid element size! (%d)\n",elementSize); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + // 'Fix' the value's endianess for working with with them + ICNS_WRITE_UNALIGNED( dataPtr+dataOffset, elementType, sizeof(icns_type_t)); + ICNS_WRITE_UNALIGNED( dataPtr+dataOffset+4, elementSize, sizeof(icns_size_t)); + + // Move on to the next element + dataOffset += elementSize; + } + + } + + if(error == 0) + *iconFamilyOut = (icns_family_t *)(dataPtr); + +exception: + + return error; +} + +/***************************** icns_find_family_in_mac_resource **************************/ + +int icns_find_family_in_mac_resource(icns_size_t resDataSize, icns_byte_t *resData, icns_rsrc_endian_t fileEndian, icns_family_t **dataOut) +{ + icns_bool_t error = ICNS_STATUS_OK; + icns_bool_t found = 0; + icns_uint32_t count = 0; + + icns_sint32_t resHeadDataOffset = 0; + icns_sint32_t resHeadMapOffset = 0; + icns_sint32_t resHeadDataSize = 0; + icns_sint32_t resHeadMapSize = 0; + + icns_sint16_t resMapAttributes = 0; + icns_sint16_t resMapTypeOffset = 0; + icns_sint16_t resMapNameOffset = 0; + icns_sint16_t resMapNumTypes = 0; + + icns_type_t getResType = ICNS_FAMILY_TYPE; + + icns_size_t iconDataSize = 0; + icns_byte_t *iconData = NULL; + + #ifdef ICNS_DEBUG + printf("Parsing resource data...\n"); + printf(" total data size: %d (0x%08X)\n",resDataSize,resDataSize); + #endif + + if(resDataSize < 16) + { + // rsrc header is 16 bytes - We cannot have a file of a smaller size. + icns_print_err("icns_find_family_in_mac_resource: Unable to decode rsrc data! - Data size too small.\n"); + return ICNS_STATUS_INVALID_DATA; + } + + // Load Resource Header to if we are dealing with a raw resource fork. + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resHeadDataOffset, (resData+0),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resHeadMapOffset, (resData+4),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resHeadDataSize, (resData+8),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resHeadMapSize, (resData+12),sizeof( icns_sint32_t)); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resHeadDataOffset, (resData+0),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_LE(resHeadMapOffset, (resData+4),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_LE(resHeadDataSize, (resData+8),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_LE(resHeadMapSize, (resData+12),sizeof( icns_sint32_t)); + } + + #ifdef ICNS_DEBUG + printf(" data offset: %d (0x%08X)\n",resHeadDataOffset,resHeadDataOffset); + printf(" map offset: %d (0x%08X)\n",resHeadMapOffset,resHeadMapOffset); + printf(" data size: %d (0x%08X)\n",resHeadDataSize,resHeadDataSize); + printf(" map size: %d (0x%08X)\n",resHeadMapSize,resHeadMapSize); + #endif + + // Check to see if file is not a raw resource file + if( (resHeadMapOffset+resHeadMapSize != resDataSize) || (resHeadDataOffset+resHeadDataSize != resHeadMapOffset) ) + { + icns_print_err("icns_find_family_in_mac_resource: Invalid resource header!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + if(resHeadMapOffset+28 > resDataSize) + { + icns_print_err("icns_find_family_in_mac_resource: Invalid resource header!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + // Load Resource Map + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resMapAttributes, (resData+resHeadMapOffset+0+22),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(resMapTypeOffset, (resData+resHeadMapOffset+2+22),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(resMapNameOffset, (resData+resHeadMapOffset+4+22),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(resMapNumTypes, (resData+resHeadMapOffset+6+22),sizeof( icns_sint16_t)); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resMapAttributes, (resData+resHeadMapOffset+0+22),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_LE(resMapTypeOffset, (resData+resHeadMapOffset+2+22),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_LE(resMapNameOffset, (resData+resHeadMapOffset+4+22),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_LE(resMapNumTypes, (resData+resHeadMapOffset+6+22),sizeof( icns_sint16_t)); + } + + // 0 == 1 here, so fix that + resMapNumTypes = resMapNumTypes + 1; + + if( (resHeadMapOffset+resMapTypeOffset+2+(count*8)) > resDataSize) + { + icns_print_err("icns_find_family_in_mac_resource: Invalid resource map!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + #ifdef ICNS_DEBUG + printf(" parsing resource map...\n"); + #endif + + for(count = 0; count < resMapNumTypes && found == 0; count++) + { + icns_type_t resType = ICNS_NULL_TYPE; + icns_sint16_t resNumItems = 0; + icns_sint16_t resOffset = 0; + + ICNS_READ_UNALIGNED_BE(resType, (resData+resHeadMapOffset+resMapTypeOffset+2+(count*8)),sizeof( icns_type_t)); + + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resNumItems, (resData+resHeadMapOffset+resMapTypeOffset+6+(count*8)),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(resOffset, (resData+resHeadMapOffset+resMapTypeOffset+8+(count*8)),sizeof( icns_sint16_t)); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resNumItems, (resData+resHeadMapOffset+resMapTypeOffset+6+(count*8)),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_LE(resOffset, (resData+resHeadMapOffset+resMapTypeOffset+8+(count*8)),sizeof( icns_sint16_t)); + } + + // 0 == 1 here, so fix that + resNumItems = resNumItems + 1; + + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" found %d items of type '%s'\n",resNumItems, icns_type_str(resType,typeStr)); + } + #endif + + if(resType == getResType) + { + icns_sint16_t resID = 0; + icns_sint8_t resAttributes = 0; + icns_sint16_t resNameOffset = 0; + icns_sint8_t resNameLength = 0; + char resName[256] = {0}; + icns_sint32_t resItemDataOffset = 0; + icns_sint32_t resItemDataSize = 0; + icns_byte_t *resItemData = NULL; + + found = 1; + + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resID, (resData+resHeadMapOffset+resMapTypeOffset+resOffset),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(resNameOffset, (resData+resHeadMapOffset+resMapTypeOffset+resOffset+2),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(resAttributes, (resData+resHeadMapOffset+resMapTypeOffset+resOffset+4),sizeof( icns_sint8_t)); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resID, (resData+resHeadMapOffset+resMapTypeOffset+resOffset),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_LE(resNameOffset, (resData+resHeadMapOffset+resMapTypeOffset+resOffset+2),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_LE(resAttributes, (resData+resHeadMapOffset+resMapTypeOffset+resOffset+4),sizeof( icns_sint8_t)); + } + + // Read in the resource name, if it exists (-1 indicates it doesn't) + if(resNameOffset != -1) + { + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resNameLength, (resData+resHeadMapOffset+resMapNameOffset+resNameOffset),sizeof( icns_sint8_t)); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resNameLength, (resData+resHeadMapOffset+resMapNameOffset+resNameOffset),sizeof( icns_sint8_t)); + } + + if(resNameLength > 0) + memcpy(&resName[0],(resData+resHeadMapOffset+resMapNameOffset+resNameOffset+1),resNameLength); + + resName[resNameLength] = 0; + } + + // Read three byte int starting at resHeadMapOffset+resMapTypeOffset+resOffset+5 + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resItemDataOffset, (resData+resHeadMapOffset+resMapTypeOffset+resOffset+5), 3); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resItemDataOffset, (resData+resHeadMapOffset+resMapTypeOffset+resOffset+5), 3); + } + + #ifdef ICNS_DEBUG + printf(" data offset is: %d (0x%08X)\n",resItemDataOffset,resItemDataOffset); + printf(" actual offset is: %d (0x%08X)\n",resHeadDataOffset+resItemDataOffset,resHeadDataOffset+resItemDataOffset); + #endif + + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resItemDataSize, (resData+resHeadDataOffset+resItemDataOffset),sizeof( icns_sint32_t)); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resItemDataSize, (resData+resHeadDataOffset+resItemDataOffset),sizeof( icns_sint32_t)); + } + + #ifdef ICNS_DEBUG + printf(" data size is: %d\n",resItemDataSize); + #endif + + if( (resHeadDataOffset+resItemDataOffset) > resDataSize ) + { + icns_print_err("icns_find_family_in_mac_resource: Resource icns id# %d has invalid data offset!\n",resID); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + if( (resItemDataSize <= 0) || (resItemDataSize > (resDataSize-(resHeadDataOffset+resItemDataOffset+4))) ) + { + char typeStr[5]; + icns_print_err("icns_find_family_in_mac_resource: Resource type '%s' id# %d has invalid size!\n",icns_type_str(resType,typeStr),resID); + icns_print_err("icns_find_family_in_mac_resource: (size %d not within range of %d to %d)\n",resItemDataSize,1,(resDataSize-(resHeadDataOffset+resItemDataOffset+4))); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + resItemData = (icns_byte_t*)malloc(resItemDataSize); + + if(resItemData != NULL) + { + memcpy( resItemData ,(resData+resHeadDataOffset+resItemDataOffset+4),resItemDataSize); + + iconDataSize = resItemDataSize; + iconData = resItemData; + } + else + { + icns_print_err("icns_find_family_in_mac_resource: Unable to allocate memory block of size: %d!\n",resItemDataSize); + error = ICNS_STATUS_NO_MEMORY; + iconData = NULL; + } + } + } + + if(found) + { + if(error == 0) + { + if(iconData != NULL) + { + if((error = icns_parse_family_data(iconDataSize,iconData,dataOut))) + { + icns_print_err("icns_parse_family_data: Error parsing icon family data!\n"); + *dataOut = NULL; + } + } + else + { + icns_print_err("icns_find_family_in_mac_resource: Found icon data is NULL!\n"); + error = ICNS_STATUS_NULL_PARAM; + } + } + } + else + { + char typeStr[5]; + icns_print_err("icns_find_family_in_mac_resource: Unable to find data of type '%s' in resource file!\n",icns_type_str(getResType,typeStr)); + error = ICNS_STATUS_DATA_NOT_FOUND; + } + +exception: + + return error; +} + + +//**************** icns_read_macbinary_resource_fork *******************// +// Parses a MacBinary file resource fork +// Returns the resource fork type, creator, size, and data + +int icns_read_macbinary_resource_fork(icns_size_t dataSize,icns_byte_t *dataPtr,icns_type_t *dataTypeOut, icns_type_t *dataCreatorOut,icns_size_t *parsedResSizeOut,icns_byte_t **parsedResDataOut) +{ + // This code is based off information from the MacBinaryIII specification at + // http://web.archive.org/web/*/www.lazerware.com/formats/macbinary/macbinary_iii.html + + int error = ICNS_STATUS_OK; + icns_type_t dataType = ICNS_NULL_TYPE; + icns_type_t dataCreator = ICNS_NULL_TYPE; + icns_bool_t isValid = 0; + icns_sint16_t secondHeaderLength = 0; + icns_sint32_t fileDataPadding = 0; + icns_sint32_t fileDataSize = 0; + icns_sint32_t resourceDataSize = 0; + icns_sint32_t resourceDataStart = 0; + icns_byte_t *resourceDataPtr = NULL; + + if(dataPtr == NULL) + { + icns_print_err("icns_read_macbinary_resource_fork: macbinary data is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataTypeOut != NULL) + *dataTypeOut = ICNS_NULL_TYPE; + + if(dataCreatorOut != NULL) + *dataCreatorOut = ICNS_NULL_TYPE; + + if(parsedResSizeOut == NULL) + { + icns_print_err("icns_read_macbinary_resource_fork: parsedResSizeOut is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + else + { + *parsedResSizeOut = 0; + } + + if(parsedResDataOut == NULL) + { + icns_print_err("icns_read_macbinary_resource_fork: parsedResSizeOut is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + else + { + *parsedResDataOut = NULL; + } + + if(dataSize < 128) + { + // MacBinary header is 128 bytes - We cannot have a file of a smaller size. + icns_print_err("icns_read_macbinary_resource_fork: Unable to decode MacBinary data! - Data size too small.\n"); + return ICNS_STATUS_INVALID_DATA; + } + + // Read headers + ICNS_READ_UNALIGNED_BE(dataType, (dataPtr+65),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED_BE(dataCreator, (dataPtr+69),sizeof( icns_type_t)); + + // Checking for valid MacBinary data... + if(dataType == ICNS_MACBINARY_TYPE) + { + // Valid MacBinary III file + isValid = 1; + } + else + { + icns_sint8_t byte00 = 0; + icns_sint8_t byte74 = 0; + icns_sint8_t byte82 = 0; + + isValid = 1; + + ICNS_READ_UNALIGNED_BE(byte00, (dataPtr+0),sizeof( icns_sint8_t)); + ICNS_READ_UNALIGNED_BE(byte74, (dataPtr+74),sizeof( icns_sint8_t)); + ICNS_READ_UNALIGNED_BE(byte74, (dataPtr+82),sizeof( icns_sint8_t)); + + // Bytes 0, 74, and 82 should all be zero in a valid MacBinary file + if( ( byte00 != 0 ) || ( byte74 != 0 ) || ( byte82 != 0 ) ) + isValid = 0; + } + + if( !isValid ) + { + icns_print_err("icns_read_macbinary_resource_fork: Invalid MacBinary data!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + // If mac file type is requested, pass it up + if(dataTypeOut != NULL) + *dataTypeOut = dataType; + + // If mac file creator is requested, pass it up + if(dataCreatorOut != NULL) + *dataCreatorOut = dataCreator; + + // Start MacBinary Parsing routines + + // Load up the data lengths + ICNS_READ_UNALIGNED_BE(secondHeaderLength, (dataPtr+120),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(fileDataSize, (dataPtr+83),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resourceDataSize, (dataPtr+87),sizeof( icns_sint32_t)); + + // Calculate extra padding length for forks + fileDataPadding = (((fileDataSize + 127) >> 7) << 7) - fileDataSize; + + // Calculate starting offsets for data + resourceDataStart = fileDataSize + fileDataPadding + 128; + + // Check that we are not reading invalid memory + if( (resourceDataStart < 128) || (resourceDataStart > dataSize) ) { + icns_print_err("icns_read_macbinary_resource_fork: Invalid resource data start!\n"); + return ICNS_STATUS_INVALID_DATA; + } + if( (resourceDataSize < 16) || (resourceDataSize > (dataSize-128)) ) { + icns_print_err("icns_read_macbinary_resource_fork: Invalid resource data size!\n"); + return ICNS_STATUS_INVALID_DATA; + } + if( (resourceDataStart+resourceDataSize > dataSize) ) { + icns_print_err("icns_read_macbinary_resource_fork: Invalid resource data location!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + resourceDataPtr = (icns_byte_t *)malloc(resourceDataSize); + + if(resourceDataPtr == NULL) + { + icns_print_err("icns_read_macbinary_resource_fork: Unable to allocate memory block of size: %d!\n",(int)resourceDataSize); + return ICNS_STATUS_NO_MEMORY; + } + + memcpy(resourceDataPtr,(dataPtr+resourceDataStart),resourceDataSize); + + *parsedResSizeOut = resourceDataSize; + *parsedResDataOut = resourceDataPtr; + + return error; +} + + +//**************** icns_read_apple_encoded_resource_fork *******************// +// Parses a resource fork from an Apple Single or Apple Double file +// Returns the resource fork type, creator, size, and data + +int icns_read_apple_encoded_resource_fork(icns_size_t dataSize,icns_byte_t *dataPtr,icns_type_t *dataTypeOut, icns_type_t *dataCreatorOut,icns_size_t *parsedResSizeOut,icns_byte_t **parsedResDataOut) +{ + icns_uint32_t magic = 0; + icns_byte_t version[4] = {0,0,0,0}; + icns_byte_t filler[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + icns_uint16_t entries = 0; + icns_uint16_t curEntry = 0; + icns_uint32_t entryID = 0; + icns_uint32_t entryOffset = 0; + icns_uint32_t entryLen = 0; + icns_type_t fileType = ICNS_NULL_TYPE; + icns_type_t fileCreator = ICNS_NULL_TYPE; + icns_sint32_t resourceDataSize = 0; + icns_sint32_t resourceDataStart = 0; + icns_byte_t *resourceDataPtr = NULL; + + if(dataPtr == NULL) + { + icns_print_err("icns_read_apple_encoded_resource_fork: apple encoded data is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataTypeOut != NULL) + *dataTypeOut = ICNS_NULL_TYPE; + + if(dataCreatorOut != NULL) + *dataCreatorOut = ICNS_NULL_TYPE; + + if(parsedResSizeOut == NULL) + { + icns_print_err("icns_read_apple_encoded_resource_fork: parsedResSizeOut is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + else + { + *parsedResSizeOut = 0; + } + + if(parsedResDataOut == NULL) + { + icns_print_err("icns_read_apple_encoded_resource_fork: parsedResSizeOut is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + else + { + *parsedResDataOut = NULL; + } + + if(dataSize < 26) + { + // AppleSingle/AppleDouble header is 26 bytes - We cannot have a file of a smaller size. + icns_print_err("icns_read_apple_encoded_resource_fork: Unable to decode apple encoded data! - Data size too small.\n"); + return ICNS_STATUS_INVALID_DATA; + } + + ICNS_READ_UNALIGNED_BE(magic, (dataPtr+0),sizeof(icns_uint32_t)); + ICNS_READ_UNALIGNED(version[0], (dataPtr+4), 4); + ICNS_READ_UNALIGNED(filler[0], (dataPtr+8), 16); + ICNS_READ_UNALIGNED_BE(entries, (dataPtr+24),sizeof(icns_uint16_t)); + + #ifdef ICNS_DEBUG + printf(" magic is: 0x%08X\n",magic); + printf(" version is: %02X%02X%02X%02X\n",version[0],version[1],version[2],version[3]); + printf(" filler is: "); + printf("%02X%02X%02X%02X",filler[0],filler[1],filler[2],filler[3]); + printf("%02X%02X%02X%02X",filler[4],filler[5],filler[6],filler[7]); + printf("%02X%02X%02X%02X",filler[8],filler[9],filler[10],filler[11]); + printf("%02X%02X%02X%02X",filler[12],filler[13],filler[14],filler[15]); + printf("\n"); + printf(" entries count: %d\n",entries); + #endif + + if(dataSize < (26 + (entries * 12) + 8) ) + { + icns_print_err("icns_read_apple_encoded_resource_fork: Unable to decode apple encoded data! - Data size too small.\n"); + return ICNS_STATUS_INVALID_DATA; + } + + if( (magic != ICNS_APPLE_SINGLE_MAGIC) && (magic != ICNS_APPLE_DOUBLE_MAGIC) ) + { + icns_print_err("icns_read_apple_encoded_resource_fork: Unable to decode apple encoded data! - invalid magic bytes.\n"); + return ICNS_STATUS_INVALID_DATA; + } + + ICNS_READ_UNALIGNED(fileType, (dataPtr+26+(entries*12)+0),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED(fileCreator, (dataPtr+26+(entries*12)+4),sizeof( icns_type_t)); + + // If mac file type is requested, pass it up + if(dataTypeOut != NULL) + *dataTypeOut = fileType; + + // If mac file creator is requested, pass it up + if(dataCreatorOut != NULL) + *dataCreatorOut = fileCreator; + + for (curEntry = 0; curEntry < entries; curEntry++) + { + ICNS_READ_UNALIGNED_BE(entryID, (dataPtr+26+(curEntry*12)+0),sizeof(icns_uint32_t)); + ICNS_READ_UNALIGNED_BE(entryOffset, (dataPtr+26+(curEntry*12)+4),sizeof(icns_uint32_t)); + ICNS_READ_UNALIGNED_BE(entryLen, (dataPtr+26+(curEntry*12)+8),sizeof(icns_uint32_t)); + + #ifdef ICNS_DEBUG + printf(" decoding entry...\n"); + printf(" entryID is: %d\n",entryID); + printf(" entryOffset is: %d\n",entryOffset); + printf(" entryLen is: %d",entryLen); + #endif + + switch (entryID) { + case ICNS_APPLE_ENC_DATA: + // Do nothing + break; + case ICNS_APPLE_ENC_RSRC: + resourceDataStart = entryOffset; + resourceDataSize = entryLen; + break; + } + } + + if( (resourceDataStart < 38) || (resourceDataStart > dataSize) ) { + icns_print_err("icns_read_apple_encoded_resource_fork: Invalid resource data start!\n"); + return ICNS_STATUS_INVALID_DATA; + } + if( (resourceDataSize < 16) || (resourceDataSize > (dataSize-38)) ) { + icns_print_err("icns_read_apple_encoded_resource_fork: Invalid resource data size!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + resourceDataPtr = (icns_byte_t *)malloc(resourceDataSize); + + if(resourceDataPtr == NULL) + { + icns_print_err("icns_read_macbinary_resource_fork: Unable to allocate memory block of size: %d!\n",(int)resourceDataSize); + return ICNS_STATUS_NO_MEMORY; + } + + memcpy(resourceDataPtr,(dataPtr+resourceDataStart),resourceDataSize); + + *parsedResSizeOut = resourceDataSize; + *parsedResDataOut = resourceDataPtr; + + return ICNS_STATUS_OK; +} + + +//**************** icns_icns_header_check *******************// +icns_bool_t icns_icns_header_check(icns_size_t dataSize,icns_byte_t *dataPtr) +{ + icns_type_t resourceType = ICNS_NULL_TYPE; + icns_size_t resourceSize = 0; + + if(dataSize < 8) + return 0; + + if(dataPtr == 0) + return 0; + + ICNS_READ_UNALIGNED_BE(resourceType, dataPtr,sizeof(icns_type_t)); + ICNS_READ_UNALIGNED_BE(resourceSize, dataPtr + 4,sizeof(icns_size_t)); + + if(resourceType != ICNS_FAMILY_TYPE) + return 0; + + if(dataSize != resourceSize ) + return 0; + + return 1; +} + +//**************** icns_rsrc_header_check *******************// +icns_bool_t icns_rsrc_header_check(icns_size_t dataSize,icns_byte_t *dataPtr,icns_rsrc_endian_t fileEndian) +{ + icns_sint32_t resHeadDataOffset = 0; + icns_sint32_t resHeadMapOffset = 0; + icns_sint32_t resHeadDataSize = 0; + icns_sint32_t resHeadMapSize = 0; + + if(dataSize < 16) + return 0; + + // Load Resource Header to if we are dealing with a raw little endian resource fork. + if(fileEndian == ICNS_BE_RSRC) { + ICNS_READ_UNALIGNED_BE(resHeadDataOffset, (dataPtr+0),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resHeadMapOffset, (dataPtr+4),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resHeadDataSize, (dataPtr+8),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resHeadMapSize, (dataPtr+12),sizeof( icns_sint32_t)); + } else if(fileEndian == ICNS_LE_RSRC) { + ICNS_READ_UNALIGNED_LE(resHeadDataOffset, (dataPtr+0),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_LE(resHeadMapOffset, (dataPtr+4),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_LE(resHeadDataSize, (dataPtr+8),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_LE(resHeadMapSize, (dataPtr+12),sizeof( icns_sint32_t)); + } else { + return 0; + } + + // Check to see if file is not a raw resource file + if( (resHeadMapOffset+resHeadMapSize != dataSize) || (resHeadDataOffset+resHeadDataSize != resHeadMapOffset) ) + return 0; + + if(resHeadMapOffset+28 > dataSize) + return 0; + + return 1; +} + +//**************** icns_macbinary_header_check *******************// +icns_bool_t icns_macbinary_header_check(icns_size_t dataSize,icns_byte_t *dataPtr) +{ + icns_bool_t isValid = 0; + icns_type_t dataType = ICNS_NULL_TYPE; + icns_type_t dataCreator = ICNS_NULL_TYPE; + icns_sint16_t secondHeaderLength = 0; + icns_sint32_t fileDataPadding = 0; + icns_sint32_t fileDataSize = 0; + icns_sint32_t resourceDataSize = 0; + icns_sint32_t resourceDataStart = 0; + + if(dataPtr == NULL) + return 0; + + if(dataSize < 128) + return 0; + + ICNS_READ_UNALIGNED_BE(dataType, (dataPtr+65),sizeof( icns_type_t)); + ICNS_READ_UNALIGNED_BE(dataCreator, (dataPtr+69),sizeof( icns_type_t)); + + // Checking for valid MacBinary data... + if(dataType == ICNS_MACBINARY_TYPE) + { + // Valid MacBinary III file + isValid = 1; + } + else + { + icns_sint8_t byte00 = 0; + icns_sint8_t byte74 = 0; + icns_sint8_t byte82 = 0; + + isValid = 1; + + ICNS_READ_UNALIGNED_BE(byte00, (dataPtr+0),sizeof( icns_sint8_t)); + ICNS_READ_UNALIGNED_BE(byte74, (dataPtr+74),sizeof( icns_sint8_t)); + ICNS_READ_UNALIGNED_BE(byte74, (dataPtr+82),sizeof( icns_sint8_t)); + + // Bytes 0, 74, and 82 should all be zero in a valid MacBinary file + if( ( byte00 != 0 ) || ( byte74 != 0 ) || ( byte82 != 0 ) ) + isValid = 0; + } + + if( !isValid ) + return 0; + + ICNS_READ_UNALIGNED_BE(secondHeaderLength, (dataPtr+120),sizeof( icns_sint16_t)); + ICNS_READ_UNALIGNED_BE(fileDataSize, (dataPtr+83),sizeof( icns_sint32_t)); + ICNS_READ_UNALIGNED_BE(resourceDataSize, (dataPtr+87),sizeof( icns_sint32_t)); + + fileDataPadding = (((fileDataSize + 127) >> 7) << 7) - fileDataSize; + + resourceDataStart = fileDataSize + fileDataPadding + 128; + + if( (resourceDataStart < 128) || (resourceDataStart > dataSize) ) + return 0; + + if( (resourceDataSize < 16) || (resourceDataSize > (dataSize-128)) ) + return 0; + + if( (resourceDataStart+resourceDataSize > dataSize) ) + return 0; + + return 1; +} + +//**************** icns_apple_encoded_header_check *******************// + +icns_bool_t icns_apple_encoded_header_check(icns_size_t dataSize,icns_byte_t *dataPtr) +{ + icns_uint32_t magic = 0; + icns_byte_t version[4] = {0,0,0,0}; + icns_byte_t filler[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + icns_uint16_t entries = 0; + + if(dataPtr == NULL) + return 0; + + if(dataSize < 26) + return 0; + + ICNS_READ_UNALIGNED_BE(magic, (dataPtr+0),sizeof(icns_uint32_t)); + ICNS_READ_UNALIGNED(version[0], (dataPtr+4), 4); + ICNS_READ_UNALIGNED(filler[0], (dataPtr+8), 16); + ICNS_READ_UNALIGNED_BE(entries, (dataPtr+24),sizeof(icns_uint16_t)); + + + if( (magic != ICNS_APPLE_SINGLE_MAGIC) && (magic != ICNS_APPLE_DOUBLE_MAGIC) ) + return 0; + + if(dataSize < (26 + (entries * 12) + 8) ) + return 0; + + return 1; +} diff --git a/src/add-ons/translators/icns/libicns/icns_jp2.c b/src/add-ons/translators/icns/libicns/icns_jp2.c new file mode 100644 index 0000000000..a96590a02c --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_jp2.c @@ -0,0 +1,961 @@ +/* +File: icns_jp2.c +Copyright (C) 2001-2012 Mathew Eis + 2007 Thomas Lübking + 2002 Chenxiao Zhao + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" + +#ifdef ICNS_JASPER +#include +#endif + +#ifdef ICNS_OPENJPEG +#include +#endif + +#define true 1 +#define false 0 + +#if defined(ICNS_JASPER) && defined(ICNS_OPENJPEG) + #error "Should use either Jasper or OpenJPEG, but not both!" +#endif + + +int icns_jp2_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut) +{ + int error = ICNS_STATUS_OK; + + if(dataPtr == NULL) + { + icns_print_err("icns_jp2_to_image: JP2 data is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(imageOut == NULL) + { + icns_print_err("icns_jp2_to_image: Image out is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSize == 0) + { + icns_print_err("icns_jp2_to_image: Invalid data size! (%d)\n",dataSize); + return ICNS_STATUS_INVALID_DATA; + } + + #ifdef ICNS_DEBUG + printf("Decoding JP2 image...\n"); + #endif + + #ifdef ICNS_JASPER + error = icns_jas_jp2_to_image(dataSize, dataPtr, imageOut); + #else + #ifdef ICNS_OPENJPEG + error = icns_opj_jp2_to_image(dataSize, dataPtr, imageOut); + #else + icns_print_err("icns_jp2_to_image: libicns requires jasper or openjpeg to convert jp2 data!\n"); + icns_free_image(imageOut); + error = ICNS_STATUS_UNSUPPORTED; + #endif + #endif + + #ifdef ICNS_DEBUG + if(error == ICNS_STATUS_OK) { + printf(" decode result:\n"); + printf(" width is: %d\n",imageOut->imageWidth); + printf(" height is: %d\n",imageOut->imageHeight); + printf(" channels are: %d\n",imageOut->imageChannels); + printf(" pixel depth is: %d\n",imageOut->imagePixelDepth); + printf(" data size is: %d\n",(int)imageOut->imageDataSize); + } else { + printf(" decode failed.\n"); + } + #endif + + return error; +} + + +int icns_image_to_jp2(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut) +{ + int error = ICNS_STATUS_OK; + + if(image == NULL) + { + icns_print_err("icns_image_to_jp2: Image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSizeOut == NULL) + { + icns_print_err("icns_image_to_jp2: Data size NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataPtrOut == NULL) + { + icns_print_err("icns_image_to_jp2: Data ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + #ifdef ICNS_DEBUG + printf("Encoding JP2 image...\n"); + #endif + + #ifdef ICNS_JASPER + error = icns_jas_image_to_jp2(image, dataSizeOut, dataPtrOut); + #else + #ifdef ICNS_OPENJPEG + error = icns_opj_image_to_jp2(image, dataSizeOut, dataPtrOut); + #else + *dataPtrOut = NULL; + error = ICNS_STATUS_UNSUPPORTED; + #endif + #endif + + return error; +} + + +#ifdef ICNS_JASPER + +int icns_jas_jp2_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut) +{ + int error = ICNS_STATUS_OK; + jas_stream_t *imagestream = NULL; + int datafmt = 0; + jas_image_t *image = NULL; + jas_matrix_t *bufs[4] = {NULL,NULL,NULL,NULL}; + icns_sint32_t imageChannels = 0; + icns_sint32_t imageWidth = 0; + icns_sint32_t imageHeight = 0; + icns_sint32_t imagePixelDepth = 0; + icns_sint32_t imageDataSize = 0; + icns_byte_t *imageData = NULL; + icns_sint8_t adjust[4] = {0,0,0,0}; + int x, y, c; + + if(dataPtr == NULL) + { + icns_print_err("icns_jas_jp2_to_image: JP2 data is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(imageOut == NULL) + { + icns_print_err("icns_jas_jp2_to_image: Image out is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSize == 0) + { + icns_print_err("icns_jas_jp2_to_image: Invalid data size! (%d)\n",dataSize); + return ICNS_STATUS_INVALID_DATA; + } + + jas_init(); + + // Connect a jasper stream to the memory + imagestream = jas_stream_memopen((char*)dataPtr, dataSize); + + if(imagestream == NULL) + { + icns_print_err("icns_jas_jp2_to_image: Unable to connect to buffer for decoding!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + // Determine the image format + datafmt = jas_image_getfmt(imagestream); + + if(datafmt < 0) + { + icns_print_err("icns_jas_jp2_to_image: Unable to determine jp2 data format! (%d)\n",datafmt); + jas_stream_close(imagestream); + return ICNS_STATUS_INVALID_DATA; + } + + //.Decode the image data + // WARNING: libjasper as of 1.9001 may 'crash' here if built with + // debugging enabled. There is an assertion in the decoding library + // that fails if there are not 3 channels or components (RGB). The + // data in icns files is usually RGBA - 4 channels. Thus, the + // assert will cause the program to crash. + if(!(image = jas_image_decode(imagestream, datafmt, 0))) + { + icns_print_err("icns_jas_jp2_to_image: Error while decoding jp2 data stream!\n"); + return ICNS_STATUS_INVALID_DATA; + } + jas_stream_close(imagestream); + + // JP2 components, i.e. channels in icns case + imageChannels = jas_image_numcmpts(image); + + #ifdef ICNS_DEBUG + printf("%d components in jp2 data\n",imageChannels); + #endif + + // There should be 4 of these + if( imageChannels != 4) + { + icns_print_err("icns_jas_jp2_to_image: Number of jp2 components (%d) is invalid!\n",imageChannels); + return ICNS_STATUS_INVALID_DATA; + } + + // Assume that we can retrieve all the relevant image + // information from componenent number zero. + imageWidth = jas_image_cmptwidth(image, 0); + imageHeight = jas_image_cmptheight(image, 0); + imagePixelDepth = jas_image_cmptprec(image, 0); + + #ifdef ICNS_DEBUG + for(c = 0; c < 4; c++) + { + printf("component %d type: %d\n",c,jas_image_cmpttype(image, c)); + } + #endif + + imageDataSize = imageHeight * imageWidth * imageChannels * (imagePixelDepth / ICNS_BYTE_BITS); + imageOut->imageWidth = imageWidth; + imageOut->imageHeight = imageHeight; + imageOut->imageChannels = imageChannels; + imageOut->imagePixelDepth = imagePixelDepth; + imageOut->imageDataSize = imageDataSize; + imageData = (icns_byte_t *)malloc(imageDataSize); + if(!imageData) { + icns_print_err("icns_jas_jp2_to_image: Unable to allocate memory block of size: %d!\n",imageDataSize); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } else { + memset(imageData,0,imageDataSize); + imageOut->imageData = imageData; + } + + for(c = 0; c < 4; c++) + { + int depth = jas_image_cmptprec(image, c); + if(depth > 8) { + adjust[c] = depth - 8; + #ifdef ICNS_DEBUG + printf("BMP CONVERSION: Will be trucating component %d (%d bits) by %d bits to 8 bits.\n",c,depth,adjust[c]); + #endif + } else { + adjust[c] = 0; + } + } + + for (c = 0; c < 4; c++) + { + if((bufs[c] = jas_matrix_create(1, imageWidth)) == NULL) + { + icns_print_err("icns_jas_jp2_to_image: Unable to create image matix! (No memory)\n"); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } + } + + for (y=0; yr = (icns_byte_t) ((r >> adjust[0])+((r >> (adjust[0]-1))%2)); + dst_pixel->g = (icns_byte_t) ((g >> adjust[1])+((g >> (adjust[1]-1))%2)); + dst_pixel->b = (icns_byte_t) ((b >> adjust[2])+((b >> (adjust[2]-1))%2)); + dst_pixel->a = (icns_byte_t) ((a >> adjust[3])+((a >> (adjust[3]-1))%2)); + + } + } + +exception: + + for(c = 0; c < 4; c++) { + if(bufs[c] != NULL) + jas_matrix_destroy(bufs[c]); + } + + jas_image_destroy(image); + jas_image_clearfmts(); + jas_cleanup(); + + return error; +} + + +int icns_jas_image_to_jp2(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut) +{ + int error = ICNS_STATUS_OK; + jas_stream_t *imagestream = NULL; + jas_image_t *jasimage = NULL; + jas_matrix_t *bufs[4] = {NULL,NULL,NULL,NULL}; + jas_image_cmptparm_t cmptparms[4]; + icns_sint32_t c = 0; + icns_sint32_t x = 0; + icns_sint32_t y = 0; + icns_sint32_t height = 0; + icns_sint32_t width = 0; + + if(image == NULL) + { + icns_print_err("icns_jas_image_to_jp2: Image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSizeOut == NULL) + { + icns_print_err("icns_jas_image_to_jp2: Data size NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataPtrOut == NULL) + { + icns_print_err("icns_jas_image_to_jp2: Data ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(image->imageChannels != 4) + { + icns_print_err("icns_jas_image_to_jp2: number if channels in input image should be 4!\n"); + return ICNS_STATUS_INVALID_DATA; + + } + + if(image->imagePixelDepth != 8) + { + // Maybe support 64/128-bit images (16/32-bits per channel) in the future? + icns_print_err("icns_jas_image_to_jp2: jp2 images currently need to be 8 bits per pixel per channel!\n"); + return ICNS_STATUS_INVALID_DATA; + + } + + // Set these NULL for now + *dataSizeOut = 0; + *dataPtrOut = NULL; + + // Apple JP2 icns format seems to be as follows: + // JP - JP2 Signature + // FTYP - File Type + // JP2 - JP2 Header + // IHDR + // COLR + // METH = 1 + // EnumCS = sRGB + // CDEF + // JP2C - JPEG 2000 Codestream + + // Set up the component parameters + for (c = 0; c < 4; c++) { + cmptparms[c].tlx = 0; + cmptparms[c].tly = 0; + cmptparms[c].hstep = 1; + cmptparms[c].vstep = 1; + cmptparms[c].width = image->imageWidth; + cmptparms[c].height = image->imageHeight; + cmptparms[c].prec = image->imagePixelDepth; + cmptparms[c].sgnd = false; + } + + // Initialize Jasper + jas_init(); + + // Allocate a new japser image + if(!(jasimage = jas_image_create(4, cmptparms, JAS_CLRSPC_UNKNOWN))) + { + icns_print_err("icns_jas_image_to_jp2: could not allocate new jasper image! (Likely out of memory)\n"); + return ICNS_STATUS_NO_MEMORY; + } + + // Set up the image components + jas_image_setclrspc(jasimage, JAS_CLRSPC_SRGB); + jas_image_setcmpttype(jasimage, 0, JAS_IMAGE_CT_RGB_R); + jas_image_setcmpttype(jasimage, 1, JAS_IMAGE_CT_RGB_G); + jas_image_setcmpttype(jasimage, 2, JAS_IMAGE_CT_RGB_B); + jas_image_setcmpttype(jasimage, 3, JAS_IMAGE_CT_OPACITY); + + width = image->imageWidth; + height = image->imageHeight; + + // Allocate the matrix buffers + for(c = 0; c < 4; c++) + { + if((bufs[c] = jas_matrix_create(height, width)) == NULL) + { + icns_print_err("icns_jas_image_to_jp2: Unable to create image matix! (No memory)\n"); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } + } + + // Copy all the image data into the jasper matrices + for (y=0; yimageData)[offset]); + + jas_matrix_set(bufs[0], y, x, src_pixel->r); + jas_matrix_set(bufs[1], y, x, src_pixel->g); + jas_matrix_set(bufs[2], y, x, src_pixel->b); + jas_matrix_set(bufs[3], y, x, src_pixel->a); + } + } + + // Write each channel component to the jasper image + for(c = 0; c < 4; c++) + { + if(jas_image_writecmpt(jasimage, c, 0, 0, width, height, bufs[c])) + { + icns_print_err("icns_jas_image_to_jp2: Unable to write data for component #%d!\n",c); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + } + + // Create a new in-memory stream - Jasper will allocate and grow this as needed + imagestream = jas_stream_memopen( NULL, 0); + + if(jas_image_encode(jasimage, imagestream, jas_image_strtofmt("jp2"),NULL)) { + icns_print_err("icns_jas_image_to_jp2: Unable to encode jp2 data!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + jas_stream_flush(imagestream); + + // Get the size of the stream - add 34 bytes for cdef + *dataSizeOut = jas_stream_length(imagestream)+34; + + #ifdef ICNS_DEBUG + printf("Compressed jp2 data size is %d\n",*dataSizeOut); + #endif + + // Offload the stream to our memory buffers + *dataPtrOut = (icns_byte_t *)malloc(*dataSizeOut); + if(!(*dataPtrOut)) + { + icns_print_err("icns_jas_image_to_jp2: Unable to allocate memory block of size: %d ($s:%m)!\n",(int)*dataSizeOut); + return ICNS_STATUS_NO_MEMORY; + } + + jas_stream_rewind(imagestream); + jas_stream_read(imagestream,*dataPtrOut,*dataSizeOut); + + jas_stream_close(imagestream); + + icns_place_jp2_cdef(*dataPtrOut,*dataSizeOut); + +exception: + + for(c = 0; c < 4; c++) { + if(bufs[c] != NULL) + jas_matrix_destroy(bufs[c]); + } + + jas_image_destroy(jasimage); + jas_image_clearfmts(); + jas_cleanup(); + + return error; +} + +#endif /* ifdef ICNS_JASPER */ + + + +// Only compile the openjpeg routines if we have support for it +#ifdef ICNS_OPENJPEG + +int icns_opj_jp2_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut) +{ + int error = ICNS_STATUS_OK; + opj_image_t *image = NULL; + + if(dataPtr == NULL) + { + icns_print_err("icns_opj_jp2_to_image: JP2 data is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(imageOut == NULL) + { + icns_print_err("icns_opj_jp2_to_image: Image out is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSize == 0) + { + icns_print_err("icns_opj_jp2_to_image: Invalid data size! (%d)\n",dataSize); + return ICNS_STATUS_INVALID_DATA; + } + + error = icns_opj_jp2_dec(dataSize, dataPtr, &image); + + if(!image) + return ICNS_STATUS_INVALID_DATA; + + error = icns_opj_to_image(image,imageOut); + + opj_image_destroy(image); + + return error; +} + +// Decode jp2 data using OpenJPEG +int icns_opj_jp2_dec(icns_size_t dataSize, icns_byte_t *dataPtr, opj_image_t **imageOut) +{ + opj_event_mgr_t event_mgr; + opj_dparameters_t parameters; + opj_dinfo_t *dinfo = NULL; + opj_cio_t *cio = NULL; + opj_image_t *image = NULL; + + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = icns_opj_error_callback; + event_mgr.warning_handler = icns_opj_warning_callback; + event_mgr.info_handler = icns_opj_info_callback; + + opj_set_default_decoder_parameters(¶meters); + + dinfo = opj_create_decompress(CODEC_JP2); + opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); + opj_setup_decoder(dinfo, ¶meters); + + cio = opj_cio_open((opj_common_ptr)dinfo, dataPtr, dataSize); + + image = opj_decode(dinfo, cio); + if(!image) { + icns_print_err("icns_opj_jp2_dec: failed to decode image!\n"); + opj_destroy_decompress(dinfo); + opj_cio_close(cio); + return ICNS_STATUS_INVALID_DATA; + } else { + *imageOut = image; + } + + opj_cio_close(cio); + opj_destroy_decompress(dinfo); + + return ICNS_STATUS_OK; +} + +// Convert from opj_image_t to icns_image_t +int icns_opj_to_image(opj_image_t *opjImg, icns_image_t *iconImg) +{ + int error = ICNS_STATUS_OK; + icns_sint8_t adjust[4] = {0,0,0,0}; + icns_byte_t *dataPtr = NULL; + int c = 0; + int i, j; + int rowOffset, colOffset; + + if(opjImg == NULL) + { + icns_print_err("icns_opj_to_image: OpenJPEG image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconImg == NULL) + { + icns_print_err("icns_opj_to_image: Icon image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + iconImg->imageWidth = opjImg->comps[0].w; + iconImg->imageHeight = opjImg->comps[0].h; + iconImg->imageChannels = opjImg->numcomps; + iconImg->imagePixelDepth = opjImg->comps[0].prec; + + iconImg->imageDataSize = iconImg->imageHeight * iconImg->imageWidth * iconImg->imagePixelDepth; // * iconChannels ? + iconImg->imageData = (icns_byte_t *)malloc(iconImg->imageDataSize); + if(!iconImg->imageData) { + icns_print_err("icns_create_family: Unable to allocate memory block of size: %d!\n",iconImg->imageDataSize); + return ICNS_STATUS_NO_MEMORY; + } + memset(iconImg->imageData,0,iconImg->imageDataSize); + + dataPtr = iconImg->imageData; + + for(c = 0; c < 4; c++) + { + int depth = opjImg->comps[c].prec; + if(depth > 8) { + adjust[c] = depth - 8; + #ifdef ICNS_DEBUG + printf("BMP CONVERSION: Will be trucating component %d (%d bits) by %d bits to 8 bits.\n",c,depth,adjust[c]); + #endif + } else { + adjust[c] = 0; + } + } + + for (i = 0; i < iconImg->imageHeight; i++) { + rowOffset = i * iconImg->imageChannels * iconImg->imageWidth; + for(j = 0; j < iconImg->imageWidth; j++) { + icns_rgba_t *dst_pixel; + int r, g, b, a; + + colOffset = j * iconImg->imageChannels; + + r = opjImg->comps[0].data[i*iconImg->imageWidth+j]; + r += (opjImg->comps[0].sgnd ? 1 << (opjImg->comps[0].prec - 1) : 0); + g = opjImg->comps[1].data[i*iconImg->imageWidth+j]; + g += (opjImg->comps[1].sgnd ? 1 << (opjImg->comps[1].prec - 1) : 0); + b = opjImg->comps[2].data[i*iconImg->imageWidth+j]; + b += (opjImg->comps[2].sgnd ? 1 << (opjImg->comps[2].prec - 1) : 0); + a = opjImg->comps[3].data[i*iconImg->imageWidth+j]; + a += (opjImg->comps[3].sgnd ? 1 << (opjImg->comps[3].prec - 1) : 0); + + dst_pixel = (icns_rgba_t *)&(dataPtr[rowOffset + colOffset]); + + dst_pixel->r = (icns_byte_t) ((r >> adjust[0])+((r >> (adjust[0]-1))%2)); + dst_pixel->g = (icns_byte_t) ((g >> adjust[1])+((g >> (adjust[1]-1))%2)); + dst_pixel->b = (icns_byte_t) ((b >> adjust[2])+((b >> (adjust[2]-1))%2)); + dst_pixel->a = (icns_byte_t) ((a >> adjust[3])+((a >> (adjust[3]-1))%2)); + } + } + + return error; +} + +int icns_opj_image_to_jp2(icns_image_t *iconImg, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut) +{ + int error = ICNS_STATUS_OK; + opj_event_mgr_t event_mgr; + opj_cparameters_t parameters; + OPJ_COLOR_SPACE color_space = CLRSPC_SRGB; + opj_image_cmptparm_t cmptparm[4]; + opj_image_t *opjImg = NULL; + icns_byte_t *dataPtr = NULL; + int i, j; + int rowOffset, colOffset; + opj_cinfo_t *cinfo = NULL; + opj_cio_t *cio = NULL; + int success = 0; + + if(iconImg == NULL) + { + icns_print_err("icns_opj_image_to_jp2: Image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSizeOut == NULL) + { + icns_print_err("icns_opj_image_to_jp2: Data size NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataPtrOut == NULL) + { + icns_print_err("icns_opj_image_to_jp2: Data ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(iconImg->imageChannels != 4) + { + icns_print_err("icns_image_to_opj: number if channels in input image should be 4!\n"); + return ICNS_STATUS_INVALID_DATA; + + } + + if(iconImg->imagePixelDepth != 8) + { + // Maybe support 64/128-bit images (16/32-bits per channel) in the future? + icns_print_err("icns_image_to_opj: jp2 images currently need to be 8 bits per pixel per channel!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + *dataSizeOut = 0; + *dataPtrOut = NULL; + + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = icns_opj_error_callback; + event_mgr.warning_handler = icns_opj_warning_callback; + event_mgr.info_handler = icns_opj_info_callback; + + opj_set_default_encoder_parameters(¶meters); + + parameters.tcp_numlayers = 1; + parameters.tcp_rates[0] = 1; + parameters.cp_disto_alloc = 1; + parameters.irreversible = 0; + + memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < 4; i++) { + + cmptparm[i].w = iconImg->imageWidth; + cmptparm[i].h = iconImg->imageHeight; + cmptparm[i].dx = 1; + cmptparm[i].dy = 1; + cmptparm[i].prec = iconImg->imagePixelDepth; + cmptparm[i].bpp = iconImg->imagePixelDepth; + cmptparm[i].sgnd = 0; + } + + opjImg = opj_image_create(4, &cmptparm[0], color_space); + if(!opjImg) { + icns_print_err("icns_image_to_opj: Unable to create new image!\n"); + return ICNS_STATUS_INVALID_DATA; + } + + opjImg->x0 = 0; + opjImg->y0 = 0; + opjImg->x1 = iconImg->imageWidth; + opjImg->y1 = iconImg->imageHeight; + + dataPtr = iconImg->imageData; + for (i = 0; i < iconImg->imageHeight; i++) { + rowOffset = i * iconImg->imageChannels * iconImg->imageWidth; + for(j = 0; j < iconImg->imageWidth; j++) { + icns_rgba_t *src_pixel; + int p = i * iconImg->imageWidth + j; + + colOffset = j * iconImg->imageChannels; + + src_pixel = (icns_rgba_t *)&(dataPtr[rowOffset + colOffset]); + + opjImg->comps[0].data[p] = src_pixel->r; + opjImg->comps[1].data[p] = src_pixel->g; + opjImg->comps[2].data[p] = src_pixel->b; + opjImg->comps[3].data[p] = src_pixel->a; + } + } + + cinfo = opj_create_compress(CODEC_JP2); + opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); + opj_setup_encoder(cinfo, ¶meters, opjImg); + + cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); + + success = opj_encode(cinfo, cio, opjImg, NULL); + if (!success) { + opj_cio_close(cio); + icns_print_err("icns_opj_jp2_enc: Error while encoding jp2 data!\n"); + error = ICNS_STATUS_INVALID_DATA; + goto exception; + } + + *dataSizeOut = cio_tell(cio) + 34; + *dataPtrOut = (icns_byte_t *)malloc(*dataSizeOut); + + if(!(*dataPtrOut)) + { + icns_print_err("icns_jas_image_to_jp2: Unable to allocate memory block of size: %d!\n",(int)*dataSizeOut); + error = ICNS_STATUS_NO_MEMORY; + goto exception; + } + + memcpy(*dataPtrOut,cio->buffer,*dataSizeOut - 34); + + icns_place_jp2_cdef(*dataPtrOut,*dataSizeOut); + +exception: + if(opjImg) { + opj_image_destroy(opjImg); + opjImg = NULL; + } + if(cio) { + opj_cio_close(cio); + cio = NULL; + } + if(cinfo) { + opj_destroy_compress(cinfo); + cinfo = NULL; + } + + return error; +} + +void icns_opj_error_callback(const char *msg, void *client_data) { +} + +void icns_opj_warning_callback(const char *msg, void *client_data) { +} + +void icns_opj_info_callback(const char *msg, void *client_data) { +} + +#endif /* ifdef ICNS_OPENJPEG */ + + +// Add cdef block - requires that dataPtr has 34 extra bytes! +void icns_place_jp2_cdef(icns_byte_t *dataPtr, icns_size_t dataSize) +{ + icns_sint32_t offset = 0; + icns_uint32_t blocksize = 0; + icns_uint32_t blocktype = 0; + icns_byte_t *bytes = NULL; + icns_uint32_t headeroffs = 0; + icns_uint32_t headersize = 0; + icns_byte_t cdef[34]; + + // Initialize CDEF block + + // big endian block size - 34 bytes + cdef[0] = 0x00; + cdef[1] = 0x00; + cdef[2] = 0x00; + cdef[3] = 0x22; + + // id = 'cdef' + cdef[4] = 'c'; + cdef[5] = 'd'; + cdef[6] = 'e'; + cdef[7] = 'f'; + + // component count - 4 + cdef[8] = 0x00; + cdef[9] = 0x04; + + // component number: 0 + cdef[10] = 0x00; + cdef[11] = 0x00; + // component type: 0=color component + cdef[12] = 0x00; + cdef[13] = 0x00; + // component association: 1=color 1 assoc + cdef[14] = 0x00; + cdef[15] = 0x01; + + // component number: 3 + cdef[16] = 0x00; + cdef[17] = 0x03; + // component type: 1=opacity component + cdef[18] = 0x00; + cdef[19] = 0x01; + // component association: 0=whole image assoc + cdef[20] = 0x00; + cdef[21] = 0x00; + + // component number: 1 + cdef[22] = 0x00; + cdef[23] = 0x01; + // component type: 0=color component + cdef[24] = 0x00; + cdef[25] = 0x00; + // component association: 2=color 2 assoc + cdef[26] = 0x00; + cdef[27] = 0x02; + + // component number: 2 + cdef[28] = 0x00; + cdef[29] = 0x02; + // component type: 0=color component + cdef[30] = 0x00; + cdef[31] = 0x00; + // component association: 3=color 3 assoc + cdef[32] = 0x00; + cdef[33] = 0x03; + + // skip 12 bytes to pass signature block + offset = 12; + bytes = dataPtr + offset; + + // look for jp2h block (0x6A73268) + do + { + blocksize = bytes[3]|bytes[2]<<8|bytes[1]<<16|bytes[0]<<24; + offset += 4; + bytes = dataPtr + offset; + blocktype = bytes[3]|bytes[2]<<8|bytes[1]<<16|bytes[0]<<24; + if(blocktype == 0x6A703268) { + offset += 4; + bytes = dataPtr + offset; + } else { + offset = offset + (blocksize - 4); + bytes = dataPtr + offset; + } + } while(blocktype != 0x6A703268 && offset < dataSize); + + // make sure we found the jp2h block + if(blocktype == 0x6A703268) + { + uint32_t c = 0; + + // keep track of the current header offset and size + headeroffs = offset; + headersize = blocksize-8; + + // update the header block size + bytes = dataPtr + (headeroffs-8); + blocksize += 34; + bytes[0] = blocksize >> 24; + bytes[1] = blocksize >> 16; + bytes[2] = blocksize >> 8; + bytes[3] = blocksize; + + // look for colr block (0x636F6C72) + offset = headeroffs; + bytes = dataPtr + offset; + do + { + blocksize = bytes[3]|bytes[2]<<8|bytes[1]<<16|bytes[0]<<24; + offset += 4; + bytes = dataPtr + offset; + blocktype = bytes[3]|bytes[2]<<8|bytes[1]<<16|bytes[0]<<24; + offset = offset + (blocksize - 4); + bytes = dataPtr + offset; + } while(blocktype != 0x636F6C72 && offset < headeroffs+headersize); + + // if we have colr block, place cdef after it + // otherwise, place cdef block at start of ihdr + if(blocktype != 0x636F6C72) { + offset = headeroffs; + } + + // shuffle the bytes backwards to make room for the cdef + bytes = dataPtr; + for(c = (dataSize)-35; c >= offset; c--) { + bytes[c+34] = bytes[c]; + } + + // copy in the cdef block + for(c = 0; c < 34; c++) { + bytes[c+offset] = cdef[c]; + } + } +} diff --git a/src/add-ons/translators/icns/libicns/icns_png.c b/src/add-ons/translators/icns/libicns/icns_png.c new file mode 100644 index 0000000000..254b7ec0fd --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_png.c @@ -0,0 +1,201 @@ +/* +File: icns_png.c +Copyright (C) 2001-2012 Mathew Eis + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" + +#include + +typedef struct icns_png_io_ref { + void* data; + size_t size; + size_t offset; +} icns_png_io_ref; + +static void icns_png_read_memory(png_structp png_ptr, png_bytep data, png_size_t length) { + icns_png_io_ref* _ref = (icns_png_io_ref*) png_get_io_ptr( png_ptr ); + memcpy( data, (char*)_ref->data + _ref->offset, length ); + _ref->offset += length; +} + +int icns_png_to_image(icns_size_t dataSize, icns_byte_t *dataPtr, icns_image_t *imageOut) +{ + int error = ICNS_STATUS_OK; + icns_png_io_ref io_data = { dataPtr, dataSize, 0 }; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 w; + png_uint_32 h; + png_bytep *rows; + int bit_depth; + int32_t color_type; + int row; + int rowsize; + + + if(dataPtr == NULL) + { + icns_print_err("icns_png_to_image: JP2 data is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(imageOut == NULL) + { + icns_print_err("icns_png_to_image: Image out is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSize == 0) + { + icns_print_err("icns_png_to_image: Invalid data size! (%d)\n",dataSize); + return ICNS_STATUS_INVALID_DATA; + } + + #ifdef ICNS_DEBUG + printf("Decoding PNG image...\n"); + #endif + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if(png_ptr == NULL) { + return ICNS_STATUS_NO_MEMORY; + } + + info_ptr = png_create_info_struct(png_ptr); + + if(info_ptr == NULL) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return ICNS_STATUS_NO_MEMORY; + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return ICNS_STATUS_INVALID_DATA; + } + + // set libpng to read from memory + png_set_read_fn(png_ptr, (void *)&io_data, &icns_png_read_memory); + + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL); + + switch (color_type) + { + case PNG_COLOR_TYPE_RGB: + if (bit_depth == 16) { + png_set_strip_16(png_ptr); + bit_depth = 8; + } + + png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth == 16) { + png_set_strip_16(png_ptr); + bit_depth = 8; + } + + break; + } + + png_read_update_info(png_ptr, info_ptr); + + rowsize = png_get_rowbytes(png_ptr, info_ptr); + rows = malloc (sizeof(png_bytep) * h); + + imageOut->imageWidth = w; + imageOut->imageHeight = h; + imageOut->imageChannels = 4; + imageOut->imagePixelDepth = 8; + imageOut->imageDataSize = w * h * 4; + imageOut->imageData = malloc( rowsize * h + 8 ); + + if(imageOut->imageData == NULL) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + free(rows); + return ICNS_STATUS_NO_MEMORY; + } + + rows[0] = imageOut->imageData; + for (row = 1; row < h; row++) { + rows[row] = rows[row-1] + rowsize; + } + + png_read_image(png_ptr, rows); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + free(rows); + + #ifdef ICNS_DEBUG + if(error == ICNS_STATUS_OK) { + printf(" decode result:\n"); + printf(" width is: %d\n",imageOut->imageWidth); + printf(" height is: %d\n",imageOut->imageHeight); + printf(" channels are: %d\n",imageOut->imageChannels); + printf(" pixel depth is: %d\n",imageOut->imagePixelDepth); + printf(" data size is: %d\n",(int)imageOut->imageDataSize); + } else { + printf(" decode failed.\n"); + } + #endif + + return error; +} + + +int icns_image_to_png(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut) +{ + int error = ICNS_STATUS_OK; + + if(image == NULL) + { + icns_print_err("icns_image_to_png: Image is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSizeOut == NULL) + { + icns_print_err("icns_image_to_png: Data size NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataPtrOut == NULL) + { + icns_print_err("icns_image_to_png: Data ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + #ifdef ICNS_DEBUG + printf("Encoding PNG image...\n"); + #endif + + // TODO: + // Verify that size is > 256x256 and 32-bit + // Then convert an icns_image to PNG data + return error; +} + diff --git a/src/add-ons/translators/icns/libicns/icns_rle24.c b/src/add-ons/translators/icns/libicns/icns_rle24.c new file mode 100644 index 0000000000..2f0721320d --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_rle24.c @@ -0,0 +1,411 @@ +/* +File: icns_rle24.c +Copyright (C) 2001-2012 Mathew Eis + 2007 Thomas Lübking + 2002 Chenxiao Zhao + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "icns.h" +#include "icns_internals.h" +//***************************** icns_decode_rle24_data ****************************// +// Decode a rgb 24 bit rle encoded data stream into 32 bit argb (alpha is ignored) + +int icns_decode_rle24_data(icns_size_t rawDataSize, icns_byte_t *rawDataPtr,icns_size_t expectedPixelCount, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut) +{ + icns_uint8_t colorOffset = 0; + icns_byte_t colorValue = 0; + icns_uint8_t runLength = 0; + icns_uint32_t dataOffset = 0; + icns_uint32_t pixelOffset = 0; + icns_uint32_t i = 0; + icns_byte_t *destIconData = NULL; // Decompressed Raw Icon Data + icns_uint32_t destIconDataSize = 0; + + if(rawDataPtr == NULL) + { + icns_print_err("icns_decode_rle24_data: rle decoder data in ptr is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSizeOut == NULL) + { + icns_print_err("icns_decode_rle24_data: rle decoder data out size ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataPtrOut == NULL) + { + icns_print_err("icns_decode_rle24_data: rle decoder data out ptr is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + // Calculate required data storage (pixels * 4 channels) + destIconDataSize = expectedPixelCount * 4; + + #ifdef ICNS_DEBUG + printf("Compressed RLE data size is %d\n",(int)rawDataSize); + printf("Decompressed will be %d bytes (%d pixels)\n",(int)destIconDataSize,(int)expectedPixelCount); + #endif + + if( (*dataSizeOut != destIconDataSize) || (*dataPtrOut == NULL) ) + { + if(*dataPtrOut != NULL) + free(*dataPtrOut); + + // Allocate the block for the decoded memory and set to 0 + destIconData = (icns_byte_t *)malloc(destIconDataSize); + if(!destIconData) + { + icns_print_err("icns_decode_rle24_data: Unable to allocate memory block of size: %d ($s:%m)!\n",(int)destIconDataSize); + return ICNS_STATUS_NO_MEMORY; + } + memset(destIconData,0,destIconDataSize); + } + else + { + destIconData = *dataPtrOut; + } + + #ifdef ICNS_DEBUG + printf("Decoding RLE data into RGB pixels...\n"); + #endif + + // What's this??? In the 128x128 icons, we need to start 4 bytes + // ahead. There is often a NULL padding here for some reason. If + // we don't, the red channel will be off by 2 pixels, or worse + if( *((icns_uint32_t*)rawDataPtr) == 0x00000000 ) + { + #ifdef ICNS_DEBUG + printf("4 byte null padding found in rle data!\n"); + #endif + dataOffset = 4; + } + else + { + dataOffset = 0; + } + + // Data is stored in red run, green run,blue run + // So we decompress to pixel format RGBA + // RED: byte[0], byte[4], byte[8] ... + // GREEN: byte[1], byte[5], byte[9] ... + // BLUE: byte[2], byte[6], byte[10] ... + // ALPHA: byte[3], byte[7], byte[11] do nothing with these bytes + for(colorOffset = 0; colorOffset < 3; colorOffset++) + { + pixelOffset = 0; + while((pixelOffset < expectedPixelCount) && (dataOffset < rawDataSize)) + { + if( (rawDataPtr[dataOffset] & 0x80) == 0) + { + // Top bit is clear - run of various values to follow + runLength = (0xFF & rawDataPtr[dataOffset++]) + 1; // 1 <= len <= 128 + for(i = 0; (i < runLength) && (pixelOffset < expectedPixelCount) && (dataOffset < rawDataSize); i++) { + destIconData[(pixelOffset * 4) + colorOffset] = rawDataPtr[dataOffset++]; + pixelOffset++; + } + } + else + { + // Top bit is set - run of one value to follow + runLength = (0xFF & rawDataPtr[dataOffset++]) - 125; // 3 <= len <= 130 + // Set the value to the color shifted to the correct bit offset + colorValue = rawDataPtr[dataOffset++]; + + for(i = 0; (i < runLength) && (pixelOffset < expectedPixelCount); i++) { + destIconData[(pixelOffset * 4) + colorOffset] = colorValue; + pixelOffset++; + } + } + } + } + + *dataSizeOut = destIconDataSize; + *dataPtrOut = destIconData; + + return ICNS_STATUS_OK; +} + +//***************************** icns_encode_rle24_data *******************************************// +// Encode an 32 bit argb data stream into a 24 bit rgb rle encoded data stream (alpha is ignored) + +int icns_encode_rle24_data(icns_size_t dataSizeIn, icns_byte_t *dataPtrIn,icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut) +{ + unsigned long dataInCount = 0; + unsigned long dataInChanSize = 0; + icns_byte_t *rgbaDataPtr = NULL; + icns_sint8_t *dataTemp = NULL; + unsigned long dataTempCount = 0; + icns_uint8_t colorOffset = 0; + icns_uint8_t dataByte = 0; + icns_uint8_t *dataRun = NULL; + icns_bool_t runType = 0; + icns_uint8_t runLength = 0; // Runs will never go over 130, one byte is ok + int runCount = 0; + + if(dataPtrIn == NULL) + { + icns_print_err("icns_encode_rle24_data: rle encoder data in ptr is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataSizeOut == NULL) + { + icns_print_err("icns_encode_rle24_data: rle encoder data out size ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + if(dataPtrOut == NULL) + { + icns_print_err("icns_encode_rle24_data: rle encoder data out ptr ref is NULL!\n"); + return ICNS_STATUS_NULL_PARAM; + } + + // Assumptions of what icns rle data is all about: + // A) Each channel is encoded indepenent of the next. + // B) An encoded channel looks like this: + // 0xRL 0xCV 0xCV 0xRL 0xCV - RL is run-length and CV is color value. + // C) There are two types of runs + // 1) Run of same value - high bit of RL is set + // 2) Run of differing values - high bit of RL is NOT set + // D) 0xRL also has two ranges + // 1) for set high bit RL, 3 to 130 + // 2) for clr high bit RL, 1 to 128 + // E) 0xRL byte is therefore set as follows: + // 1) for same values, RL = RL - 1 + // 2) different values, RL = RL + 125 + // 3) both methods will automatically set the high bit appropriately + // F) 0xCV byte are set accordingly + // 1) for differing values, run of all differing values + // 2) for same values, only one byte of that values + // Estimations put the absolute worst case scenario as the + // final compressed data being slightly LARGER. So we need to be + // careful about allocating memory. (Did I miss something?) + // tests seem to indicate it will never be larger than the original + + // This block is for the new RLE encoded data - make it 25% larger + dataTemp = (icns_sint8_t *)malloc(dataSizeIn + (dataSizeIn / 4)); + if(dataTemp == NULL) + { + icns_print_err("icns_encode_rle24_data: Unable to allocate memory block of size: %d!\n",(int)dataSizeIn); + return ICNS_STATUS_NO_MEMORY; + } + memset(dataTemp,0,dataSizeIn); + + // This block is for a run of RLE encoded data + dataRun = (icns_uint8_t *)malloc(140); + if(dataRun == NULL) + { + icns_print_err("icns_encode_rle24_data: Unable to allocate memory block of size: %d!\n",140); + free(dataTemp); + return ICNS_STATUS_NO_MEMORY; + } + memset(dataRun,0,140); + + // Set the data ptr + rgbaDataPtr = (icns_byte_t *)dataPtrIn; + + // There's always going to be 4 channels in this + // so we want our counter to increment through + // channels, not bytes.... + dataInChanSize = dataSizeIn / 4; + + // Move forward 4 bytes for 128 size - who knows why this should be + if(dataSizeIn >= 65536) + dataTempCount = 4; + + // Data is stored in red run, green run,blue run + // So we compress from pixel format RGBA + // RED: byte[0], byte[4], byte[8] ... + // GREEN: byte[1], byte[5], byte[9] ... + // BLUE: byte[2], byte[6], byte[10] ... + // ALPHA: byte[3], byte[7], byte[11] do nothing with these bytes + for(colorOffset = 0; colorOffset < 3; colorOffset++) + { + runCount = 0; + + // Set the first byte of the run... + dataRun[0] = *(rgbaDataPtr+colorOffset); + + // Start with a runlength of 1 for the first byte + runLength = 1; + + // Assume that the run will be different for now... We can change this later + runType = 0; // 0 for low bit (different), 1 for high bit (same) + + // Start one byte ahead + for(dataInCount = 1; dataInCount < dataInChanSize; dataInCount++) + { + dataByte = *(rgbaDataPtr+colorOffset+(dataInCount*4)); + + if(runLength < 2) + { + // Simply append to the current run + dataRun[runLength++] = dataByte; + } + else if(runLength == 2) + { + // Decide here if the run should be same values or different values + + // If the last three values were the same, we can change to a same-type run + if( (dataByte == dataRun[runLength-1]) && (dataByte == dataRun[runLength-2]) ) + runType = 1; + else + runType = 0; + + dataRun[runLength++] = dataByte; + } + else // Greater than or equal to 2 + { + if(runType == 0 && runLength < 128) // Different type run + { + // If the new value matches both of the last two values, we have a new + // same-type run starting with the previous two bytes + if( (dataByte == dataRun[runLength-1]) && (dataByte == dataRun[runLength-2]) ) + { + // Set the RL byte + *(dataTemp+dataTempCount) = runLength - 3; + dataTempCount++; + + // Copy 0 to runLength-2 bytes to the RLE data here + memcpy( dataTemp+dataTempCount , dataRun , runLength - 2 ); + dataTempCount = dataTempCount + (runLength - 2); + runCount++; + + // Set up the new same-type run + dataRun[0] = dataRun[runLength-2]; + dataRun[1] = dataRun[runLength-1]; + dataRun[2] = dataByte; + runLength = 3; + runType = 1; + } + else // They don't match, so we can proceed + { + dataRun[runLength++] = dataByte; + } + } + else if(runType == 1 && runLength < 130) // Same type run + { + // If the new value matches both of the last two values, we + // can safely continue + if( (dataByte == dataRun[runLength-1]) && (dataByte == dataRun[runLength-2]) ) + { + dataRun[runLength++] = dataByte; + } + else // They don't match, so we need to start a new run + { + // Set the RL byte + *(dataTemp+dataTempCount) = runLength + 125; + dataTempCount++; + + // Only copy the first byte, since all the remaining values are identical + *(dataTemp+dataTempCount) = dataRun[0]; + dataTempCount++; + runCount++; + + // Copy 0 to runLength bytes to the RLE data here + dataRun[0] = dataByte; + runLength = 1; + runType = 0; + } + } + else // Exceeded run limit, need to start a new one + { + if(runType == 0) + { + // Set the RL byte low + *(dataTemp+dataTempCount) = runLength - 1; + dataTempCount++; + + // Copy 0 to runLength bytes to the RLE data here + memcpy( dataTemp+dataTempCount , dataRun , runLength ); + dataTempCount = dataTempCount + runLength; + } + else if(runType == 1) + { + // Set the RL byte high + *(dataTemp+dataTempCount) = runLength + 125; + dataTempCount++; + + // Only copy the first byte, since all the remaining values are identical + *(dataTemp+dataTempCount) = dataRun[0]; + dataTempCount++; + } + + runCount++; + + // Copy 0 to runLength bytes to the RLE data here + dataRun[0] = dataByte; + runLength = 1; + runType = 0; + } + } + } + + // Copy the end of the last run + if(runLength > 0) + { + if(runType == 0) + { + // Set the RL byte low + *(dataTemp+dataTempCount) = runLength - 1; + dataTempCount++; + + // Copy 0 to runLength bytes to the RLE data here + memcpy( dataTemp+dataTempCount , dataRun , runLength ); + dataTempCount = dataTempCount + runLength; + } + else if(runType == 1) + { + // Set the RL byte high + *(dataTemp+dataTempCount) = runLength + 125; + dataTempCount++; + + // Only copy the first byte, since all the remaining values are identical + *(dataTemp+dataTempCount) = dataRun[0]; + dataTempCount++; + } + + runCount++; + } + } + + free(dataRun); + + // This block is for the final encoded data + (*dataPtrOut) = (icns_uint8_t *)malloc(dataTempCount); + if((*dataPtrOut) == NULL) + { + icns_print_err("icns_encode_rle24_data: Unable to allocate memory block of size: %d!\n",dataTempCount); + free(dataTemp); + return ICNS_STATUS_NO_MEMORY; + } + + *dataSizeOut = dataTempCount; + memcpy( (*dataPtrOut), dataTemp, dataTempCount); + + free(dataTemp); + + return ICNS_STATUS_OK; +} + diff --git a/src/add-ons/translators/icns/libicns/icns_utils.c b/src/add-ons/translators/icns/libicns/icns_utils.c new file mode 100644 index 0000000000..47bdbebb79 --- /dev/null +++ b/src/add-ons/translators/icns/libicns/icns_utils.c @@ -0,0 +1,763 @@ +/* +File: icns_utils.c +Copyright (C) 2001-2012 Mathew Eis + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + + +#include "icns.h" +#include "icns_internals.h" + + +/********* This variable is intentionally global ************/ +/********* scope is the internals of the icns library *******/ +#ifdef ICNS_DEBUG +icns_bool_t gShouldPrintErrors = 1; +#else +icns_bool_t gShouldPrintErrors = 0; +#endif + +icns_uint32_t icns_get_element_order(icns_type_t iconType) +{ + // Note: 1 bit mask is 'excluded' as + // 1 bit data and mask ID's are equal + // data stored in the same element + switch(iconType) + { + case ICNS_ICON_VERSION: + return 100; + case ICNS_1024x1024_32BIT_ARGB_DATA: + return 23; + case ICNS_512x512_32BIT_ARGB_DATA: + return 22; + case ICNS_256x256_32BIT_ARGB_DATA: + return 21; + case ICNS_128X128_8BIT_MASK: + return 20; + case ICNS_128X128_32BIT_DATA: + return 19; + case ICNS_48x48_8BIT_MASK: + return 18; + case ICNS_48x48_32BIT_DATA: + return 17; + case ICNS_48x48_8BIT_DATA: + return 16; + case ICNS_48x48_4BIT_DATA: + return 15; + case ICNS_48x48_1BIT_DATA: + return 14; + case ICNS_32x32_8BIT_MASK: + return 13; + case ICNS_32x32_32BIT_DATA: + return 12; + case ICNS_32x32_8BIT_DATA: + return 11; + case ICNS_32x32_4BIT_DATA: + return 10; + case ICNS_32x32_1BIT_DATA: + return 9; + case ICNS_16x16_8BIT_MASK: + return 8; + case ICNS_16x16_32BIT_DATA: + return 7; + case ICNS_16x16_8BIT_DATA: + return 6; + case ICNS_16x16_4BIT_DATA: + return 5; + case ICNS_16x16_1BIT_DATA: + return 4; + case ICNS_16x12_8BIT_DATA: + return 3; + case ICNS_16x12_4BIT_DATA: + return 2; + case ICNS_16x12_1BIT_DATA: + return 1; + case ICNS_TABLE_OF_CONTENTS: + return 0; + default: + return 1000; + } + + return 1000; +} + +icns_type_t icns_get_mask_type_for_icon_type(icns_type_t iconType) +{ + switch(iconType) + { + // Obviously the TOC type has no mask + case ICNS_TABLE_OF_CONTENTS: + return ICNS_NULL_MASK; + + // Obviously the version type has no mask + case ICNS_ICON_VERSION: + return ICNS_NULL_MASK; + + // 32-bit image types > 256x256 - no mask (mask is already in image) + case ICNS_1024x1024_32BIT_ARGB_DATA: + return ICNS_NULL_MASK; + case ICNS_512x512_32BIT_ARGB_DATA: + return ICNS_NULL_MASK; + case ICNS_256x256_32BIT_ARGB_DATA: + return ICNS_NULL_MASK; + + // 32-bit image types - 8-bit mask type + case ICNS_128X128_32BIT_DATA: + return ICNS_128X128_8BIT_MASK; + case ICNS_48x48_32BIT_DATA: + return ICNS_48x48_8BIT_MASK; + case ICNS_32x32_32BIT_DATA: + return ICNS_32x32_8BIT_MASK; + case ICNS_16x16_32BIT_DATA: + return ICNS_16x16_8BIT_MASK; + + // 8-bit image types - 1-bit mask types + case ICNS_48x48_8BIT_DATA: + return ICNS_48x48_1BIT_MASK; + case ICNS_32x32_8BIT_DATA: + return ICNS_32x32_1BIT_MASK; + case ICNS_16x16_8BIT_DATA: + return ICNS_16x16_1BIT_MASK; + case ICNS_16x12_8BIT_DATA: + return ICNS_16x12_1BIT_MASK; + + // 4 bit image types - 1-bit mask types + case ICNS_48x48_4BIT_DATA: + return ICNS_48x48_1BIT_MASK; + case ICNS_32x32_4BIT_DATA: + return ICNS_32x32_1BIT_MASK; + case ICNS_16x16_4BIT_DATA: + return ICNS_16x16_1BIT_MASK; + case ICNS_16x12_4BIT_DATA: + return ICNS_16x12_1BIT_MASK; + + // 1 bit image types - 1-bit mask types + case ICNS_48x48_1BIT_DATA: + return ICNS_48x48_1BIT_MASK; + case ICNS_32x32_1BIT_DATA: + return ICNS_32x32_1BIT_MASK; + case ICNS_16x16_1BIT_DATA: + return ICNS_16x16_1BIT_MASK; + case ICNS_16x12_1BIT_DATA: + return ICNS_16x12_1BIT_MASK; + default: + return ICNS_NULL_MASK; + } + + return ICNS_NULL_MASK; +} + +icns_icon_info_t icns_get_image_info_for_type(icns_type_t iconType) +{ + icns_icon_info_t iconInfo; + + memset(&iconInfo,0,sizeof(iconInfo)); + + if(iconType == ICNS_NULL_TYPE) + { + icns_print_err("icns_get_image_info_for_type: Unable to parse NULL type!\n"); + return iconInfo; + } + + /* + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf("Retrieving info for type '%s'...\n",icns_type_str(iconType,typeStr)); + } + #endif + */ + + iconInfo.iconType = iconType; + + switch(iconType) + { + // TOC type + case ICNS_TABLE_OF_CONTENTS: + iconInfo.isImage = 0; + iconInfo.isMask = 0; + iconInfo.iconWidth = 0; + iconInfo.iconHeight = 0; + iconInfo.iconChannels = 0; + iconInfo.iconPixelDepth = 0; + iconInfo.iconBitDepth = 0; + break; + // Version type + case ICNS_ICON_VERSION: + iconInfo.isImage = 0; + iconInfo.isMask = 0; + iconInfo.iconWidth = 0; + iconInfo.iconHeight = 0; + iconInfo.iconChannels = 0; + iconInfo.iconPixelDepth = 0; + iconInfo.iconBitDepth = 0; + break; + // 32-bit image types + case ICNS_1024x1024_32BIT_ARGB_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 1024; + iconInfo.iconHeight = 1024; + iconInfo.iconChannels = 4; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 32; + break; + case ICNS_512x512_32BIT_ARGB_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 512; + iconInfo.iconHeight = 512; + iconInfo.iconChannels = 4; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 32; + break; + case ICNS_256x256_32BIT_ARGB_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 256; + iconInfo.iconHeight = 256; + iconInfo.iconChannels = 4; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 32; + break; + case ICNS_128X128_32BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 128; + iconInfo.iconHeight = 128; + iconInfo.iconChannels = 4; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 32; + break; + case ICNS_48x48_32BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 48; + iconInfo.iconHeight = 48; + iconInfo.iconChannels = 4; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 32; + break; + case ICNS_32x32_32BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 32; + iconInfo.iconHeight = 32; + iconInfo.iconChannels = 4; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 32; + break; + case ICNS_16x16_32BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 16; + iconInfo.iconChannels = 4; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 32; + break; + + // 8-bit mask types + case ICNS_128X128_8BIT_MASK: + iconInfo.isImage = 0; + iconInfo.isMask = 1; + iconInfo.iconWidth = 128; + iconInfo.iconHeight = 128; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + case ICNS_48x48_8BIT_MASK: + iconInfo.isImage = 0; + iconInfo.isMask = 1; + iconInfo.iconWidth = 48; + iconInfo.iconHeight = 48; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + case ICNS_32x32_8BIT_MASK: + iconInfo.isImage = 0; + iconInfo.isMask = 1; + iconInfo.iconWidth = 32; + iconInfo.iconHeight = 32; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + case ICNS_16x16_8BIT_MASK: + iconInfo.isImage = 0; + iconInfo.isMask = 1; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 16; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + + // 8-bit image types + case ICNS_48x48_8BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 48; + iconInfo.iconHeight = 48; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + case ICNS_32x32_8BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 32; + iconInfo.iconHeight = 32; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + case ICNS_16x16_8BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 16; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + case ICNS_16x12_8BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 12; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 8; + iconInfo.iconBitDepth = 8; + break; + + // 4 bit image types + case ICNS_48x48_4BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 48; + iconInfo.iconHeight = 48; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 4; + iconInfo.iconBitDepth = 4; + break; + case ICNS_32x32_4BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 32; + iconInfo.iconHeight = 32; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 4; + iconInfo.iconBitDepth = 4; + break; + case ICNS_16x16_4BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 16; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 4; + iconInfo.iconBitDepth = 4; + break; + case ICNS_16x12_4BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 0; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 12; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 4; + iconInfo.iconBitDepth = 4; + break; + + // 1 bit image types - same as mask typess + case ICNS_48x48_1BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 1; + iconInfo.iconWidth = 48; + iconInfo.iconHeight = 48; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 1; + iconInfo.iconBitDepth = 1; + break; + case ICNS_32x32_1BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 1; + iconInfo.iconWidth = 32; + iconInfo.iconHeight = 32; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 1; + iconInfo.iconBitDepth = 1; + break; + case ICNS_16x16_1BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 1; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 16; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 1; + iconInfo.iconBitDepth = 1; + break; + case ICNS_16x12_1BIT_DATA: + iconInfo.isImage = 1; + iconInfo.isMask = 1; + iconInfo.iconWidth = 16; + iconInfo.iconHeight = 12; + iconInfo.iconChannels = 1; + iconInfo.iconPixelDepth = 1; + iconInfo.iconBitDepth = 1; + break; + default: + { + char typeStr[5]; + icns_print_err("icns_get_image_info_for_type: Unable to parse icon type '%s'\n",icns_type_str(iconType,typeStr)); + iconInfo.iconType = ICNS_NULL_TYPE; + } + break; + } + + iconInfo.iconRawDataSize = iconInfo.iconHeight * iconInfo.iconWidth * iconInfo.iconBitDepth / ICNS_BYTE_BITS; + + /* + #ifdef ICNS_DEBUG + { + char typeStr[5]; + printf(" type is: '%s'\n",icns_type_str(iconInfo.iconType)); + printf(" width is: %d\n",iconInfo.iconWidth); + printf(" height is: %d\n",iconInfo.iconHeight); + printf(" channels are: %d\n",iconInfo.iconChannels); + printf(" pixel depth is: %d\n",iconInfo.iconPixelDepth); + printf(" bit depth is: %d\n",iconInfo.iconBitDepth); + printf(" data size is: %d\n",(int)iconInfo.iconRawDataSize); + } + #endif + */ + + return iconInfo; +} + +icns_type_t icns_get_type_from_image_info(icns_icon_info_t iconInfo) +{ + // Give our best effort to returning a type from the given information + // But there is only so much we can't work with... + if( (iconInfo.isImage == 0) && (iconInfo.isMask == 0) ) + return ICNS_NULL_TYPE; + + if( (iconInfo.iconWidth == 0) || (iconInfo.iconHeight == 0) ) + { + // For some really small sizes, we can tell from just the data size... + switch(iconInfo.iconRawDataSize) + { + case 24: + // Data is too small to have both + if( (iconInfo.isImage == 1) && (iconInfo.isMask == 1) ) + return ICNS_NULL_TYPE; + if( iconInfo.isImage == 1 ) + return ICNS_16x12_1BIT_DATA; + if( iconInfo.isMask == 1 ) + return ICNS_16x12_1BIT_MASK; + break; + case 32: + // Data is too small to have both + if( (iconInfo.isImage == 1) && (iconInfo.isMask == 1) ) + return ICNS_NULL_TYPE; + if( iconInfo.isImage == 1 ) + return ICNS_16x16_1BIT_DATA; + if( iconInfo.isMask == 1 ) + return ICNS_16x16_1BIT_MASK; + break; + default: + return ICNS_NULL_TYPE; + } + } + + // We need the bit depth to determine the type for sizes < 128 + if( (iconInfo.iconBitDepth == 0) && (iconInfo.iconWidth < 128 || iconInfo.iconHeight < 128) ) + { + if(iconInfo.iconPixelDepth == 0 || iconInfo.iconChannels == 0) + return ICNS_NULL_TYPE; + else + iconInfo.iconBitDepth = iconInfo.iconPixelDepth * iconInfo.iconChannels; + } + + // Special case for these mini icons + if(iconInfo.iconWidth == 16 && iconInfo.iconHeight == 12) + { + switch(iconInfo.iconBitDepth) + { + case 1: + if(iconInfo.isImage == 1) + return ICNS_16x12_1BIT_DATA; + if(iconInfo.isMask == 1) + return ICNS_16x12_1BIT_MASK; + break; + case 4: + return ICNS_16x12_4BIT_DATA; + break; + case 8: + return ICNS_16x12_8BIT_DATA; + break; + default: + return ICNS_NULL_TYPE; + break; + } + } + + // Width must equal hieght from here on... + if(iconInfo.iconWidth != iconInfo.iconHeight) + return ICNS_NULL_TYPE; + + + switch(iconInfo.iconWidth) + { + case 16: + switch(iconInfo.iconBitDepth) + { + case 1: + if(iconInfo.isImage == 1) + return ICNS_16x16_1BIT_DATA; + if(iconInfo.isMask == 1) + return ICNS_16x16_1BIT_MASK; + break; + case 4: + return ICNS_16x16_4BIT_DATA; + break; + case 8: + if(iconInfo.isImage == 1) + return ICNS_16x16_8BIT_DATA; + if(iconInfo.isMask == 1) + return ICNS_16x16_8BIT_MASK; + break; + case 32: + return ICNS_16x16_32BIT_DATA; + break; + default: + return ICNS_NULL_TYPE; + break; + } + break; + case 32: + switch(iconInfo.iconBitDepth) + { + case 1: + if(iconInfo.isImage == 1) + return ICNS_32x32_1BIT_DATA; + if(iconInfo.isMask == 1) + return ICNS_32x32_1BIT_MASK; + break; + case 4: + return ICNS_32x32_4BIT_DATA; + break; + case 8: + if(iconInfo.isImage == 1) + return ICNS_32x32_8BIT_DATA; + if(iconInfo.isMask == 1) + return ICNS_32x32_8BIT_MASK; + break; + case 32: + return ICNS_32x32_32BIT_DATA; + break; + default: + return ICNS_NULL_TYPE; + break; + } + break; + case 48: + switch(iconInfo.iconBitDepth) + { + case 1: + if(iconInfo.isImage == 1) + return ICNS_48x48_1BIT_DATA; + if(iconInfo.isMask == 1) + return ICNS_48x48_1BIT_MASK; + break; + case 4: + return ICNS_48x48_4BIT_DATA; + break; + case 8: + if(iconInfo.isImage == 1) + return ICNS_48x48_8BIT_DATA; + if(iconInfo.isMask == 1) + return ICNS_48x48_8BIT_MASK; + break; + case 32: + return ICNS_48x48_32BIT_DATA; + break; + default: + return ICNS_NULL_TYPE; + break; + } + break; + case 128: + if(iconInfo.isImage == 1 || iconInfo.iconBitDepth == 32) + return ICNS_128X128_32BIT_DATA; + if(iconInfo.isMask == 1 || iconInfo.iconBitDepth == 8) + return ICNS_128X128_8BIT_MASK; + break; + case 256: + return ICNS_256x256_32BIT_ARGB_DATA; + break; + case 512: + return ICNS_512x512_32BIT_ARGB_DATA; + break; + case 1024: + return ICNS_1024x1024_32BIT_ARGB_DATA; + break; + + } + + return ICNS_NULL_TYPE; +} + +icns_type_t icns_get_type_from_image(icns_image_t iconImage) +{ + icns_icon_info_t iconInfo; + + iconInfo.iconWidth = iconImage.imageWidth; + iconInfo.iconHeight = iconImage.imageHeight; + iconInfo.iconChannels = iconImage.imageChannels; + iconInfo.iconPixelDepth = iconImage.imagePixelDepth; + iconInfo.iconBitDepth = iconInfo.iconPixelDepth * iconInfo.iconChannels; + iconInfo.iconRawDataSize = iconImage.imageDataSize; + + if(iconInfo.iconBitDepth == 1) + { + int flatSize = ((iconInfo.iconWidth * iconInfo.iconHeight) / 8); + if(iconInfo.iconRawDataSize == (flatSize * 2) ) + { + iconInfo.isImage = 1; + iconInfo.isMask = 1; + } + else + { + iconInfo.isImage = 1; + iconInfo.isMask = 0; + } + } + else + { + iconInfo.isImage = 1; + iconInfo.isMask = 0; + } + + return icns_get_type_from_image_info(iconInfo); +} + +icns_type_t icns_get_type_from_mask(icns_image_t iconImage) +{ + icns_icon_info_t iconInfo; + + iconInfo.iconWidth = iconImage.imageWidth; + iconInfo.iconHeight = iconImage.imageHeight; + iconInfo.iconChannels = iconImage.imageChannels; + iconInfo.iconPixelDepth = iconImage.imagePixelDepth; + iconInfo.iconBitDepth = iconInfo.iconPixelDepth * iconInfo.iconChannels; + iconInfo.iconRawDataSize = iconImage.imageDataSize; + + if(iconInfo.iconBitDepth == 1) + { + int flatSize = ((iconInfo.iconWidth * iconInfo.iconHeight) / 8); + if(iconInfo.iconRawDataSize == (flatSize * 2) ) + { + iconInfo.isImage = 1; + iconInfo.isMask = 1; + } + else + { + iconInfo.isImage = 0; + iconInfo.isMask = 1; + } + } + else + { + iconInfo.isImage = 0; + iconInfo.isMask = 1; + } + + return icns_get_type_from_image_info(iconInfo); +} + +icns_bool_t icns_types_equal(icns_type_t typeA,icns_type_t typeB) +{ + if(memcmp(&typeA, &typeB, sizeof(icns_type_t)) == 0) + return 1; + else + return 0; +} + +// This is is largely for conveniance and readability +icns_bool_t icns_types_not_equal(icns_type_t typeA,icns_type_t typeB) +{ + if(memcmp(&typeA, &typeB, sizeof(icns_type_t)) != 0) + return 1; + else + return 0; +} + +const char * icns_type_str(icns_type_t type, char *strbuf) +{ + if(strbuf != NULL) + { + uint32_t v = *((uint32_t *)(&type)); + strbuf[0] = v >> 24; + strbuf[1] = v >> 16; + strbuf[2] = v >> 8; + strbuf[3] = v; + strbuf[4] = 0; + return (const char *)strbuf; + } + return NULL; +} + +void icns_set_print_errors(icns_bool_t shouldPrint) +{ + #ifdef ICNS_DEBUG + if(shouldPrint == 0) { + icns_print_err("Debugging enabled - error message status cannot be disabled!\n"); + } + #else + gShouldPrintErrors = shouldPrint; + #endif +} + +void icns_print_err(const char *template, ...) +{ + va_list ap; + + #ifdef ICNS_DEBUG + printf ( "libicns: "); + va_start (ap, template); + vprintf (template, ap); + va_end (ap); + #else + if(gShouldPrintErrors) + { + fprintf (stderr, "libicns: "); + va_start (ap, template); + vfprintf (stderr, template, ap); + va_end (ap); + } + #endif +} + diff --git a/src/add-ons/translators/icns/main.cpp b/src/add-ons/translators/icns/main.cpp new file mode 100644 index 0000000000..2d11692e89 --- /dev/null +++ b/src/add-ons/translators/icns/main.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include + +#include "ICNSTranslator.h" +#include "TranslatorWindow.h" + +int +main(int /*argc*/, char ** /*argv*/) +{ + BApplication app("application/x-vnd.Haiku-ICNSTranslator"); + + status_t result; + result = LaunchTranslatorWindow(new ICNSTranslator, + "ICNS Settings", BRect(0, 0, 320, 200)); + if (result != B_OK) + return 1; + + app.Run(); + return 0; +} + diff --git a/src/add-ons/translators/icns/openjpeg/LICENSE b/src/add-ons/translators/icns/openjpeg/LICENSE new file mode 100644 index 0000000000..f7b3b66286 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/LICENSE @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2012, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2012, Professor Benoit Macq + * Copyright (c) 2003-2012, Antonin Descampe + * Copyright (c) 2003-2009, Francois-Olivier Devaux + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2001-2003, David Janssens + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ diff --git a/src/add-ons/translators/icns/openjpeg/README b/src/add-ons/translators/icns/openjpeg/README new file mode 100644 index 0000000000..018ba2dade --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/README @@ -0,0 +1,25 @@ + +OPENJPEG LIBRARY and APPLICATIONS +---------------------------------- + +Details on folders hierarchy: + +* libopenjpeg: contains the sources of the openjpeg library + * jpwl: contains the additional sources if you want to build a JPWL-flavoured library. +* applications: contains all applications that use the openjpeg library + * common: common files to all applications + * codec: a basic codec + * mj2: motion jpeg 2000 executables + * JavaOpenJPEG: java jni to use openjpeg in a java program + * jpip: complete client-server architecture for remote browsing of jpeg 2000 images. See corresponding README for more details. + * OPJViewer: gui for displaying j2k files (based on wxWidget) +* thirdparty: thirdparty libraries used by some applications. These libraries will be built only if there are not found on the system. Note that libopenjpeg itself does not have any dependency. +* doc: doxygen documentation setup file and man pages +* tests: configuration files and utilities for the openjpeg test suite. All test images are located in 'http://openjpeg.googlecode.com/svn/data' folder. +* CMake: cmake related files +* m4: autotools related files + +see LICENSE for license and copyright information. +see INSTALL for installation procedures. +see NEWS for user visible changes in successive releases. +see CHANGES for per-revision changes. diff --git a/src/add-ons/translators/icns/openjpeg/bio.c b/src/add-ons/translators/icns/openjpeg/bio.c new file mode 100644 index 0000000000..4c02f464d8 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/bio.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/** @defgroup BIO BIO - Individual bit input-output stream */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Write a bit +@param bio BIO handle +@param b Bit to write (0 or 1) +*/ +static void bio_putbit(opj_bio_t *bio, int b); +/** +Read a bit +@param bio BIO handle +@return Returns the read bit +*/ +static int bio_getbit(opj_bio_t *bio); +/** +Write a byte +@param bio BIO handle +@return Returns 0 if successful, returns 1 otherwise +*/ +static int bio_byteout(opj_bio_t *bio); +/** +Read a byte +@param bio BIO handle +@return Returns 0 if successful, returns 1 otherwise +*/ +static int bio_bytein(opj_bio_t *bio); + +/*@}*/ + +/*@}*/ + +/* +========================================================== + local functions +========================================================== +*/ + +static int bio_byteout(opj_bio_t *bio) { + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if (bio->bp >= bio->end) { + return 1; + } + *bio->bp++ = bio->buf >> 8; + return 0; +} + +static int bio_bytein(opj_bio_t *bio) { + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if (bio->bp >= bio->end) { + return 1; + } + bio->buf |= *bio->bp++; + return 0; +} + +static void bio_putbit(opj_bio_t *bio, int b) { + if (bio->ct == 0) { + bio_byteout(bio); + } + bio->ct--; + bio->buf |= b << bio->ct; +} + +static int bio_getbit(opj_bio_t *bio) { + if (bio->ct == 0) { + bio_bytein(bio); + } + bio->ct--; + return (bio->buf >> bio->ct) & 1; +} + +/* +========================================================== + Bit Input/Output interface +========================================================== +*/ + +opj_bio_t* bio_create(void) { + opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t)); + return bio; +} + +void bio_destroy(opj_bio_t *bio) { + if(bio) { + opj_free(bio); + } +} + +int bio_numbytes(opj_bio_t *bio) { + return (bio->bp - bio->start); +} + +void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int len) { + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 8; +} + +void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int len) { + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 0; +} + +void bio_write(opj_bio_t *bio, int v, int n) { + int i; + for (i = n - 1; i >= 0; i--) { + bio_putbit(bio, (v >> i) & 1); + } +} + +int bio_read(opj_bio_t *bio, int n) { + int i, v; + v = 0; + for (i = n - 1; i >= 0; i--) { + v += bio_getbit(bio) << i; + } + return v; +} + +int bio_flush(opj_bio_t *bio) { + bio->ct = 0; + if (bio_byteout(bio)) { + return 1; + } + if (bio->ct == 7) { + bio->ct = 0; + if (bio_byteout(bio)) { + return 1; + } + } + return 0; +} + +int bio_inalign(opj_bio_t *bio) { + bio->ct = 0; + if ((bio->buf & 0xff) == 0xff) { + if (bio_bytein(bio)) { + return 1; + } + bio->ct = 0; + } + return 0; +} diff --git a/src/add-ons/translators/icns/openjpeg/bio.h b/src/add-ons/translators/icns/openjpeg/bio.h new file mode 100644 index 0000000000..764d7cb2e9 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/bio.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __BIO_H +#define __BIO_H +/** +@file bio.h +@brief Implementation of an individual bit input-output (BIO) + +The functions in BIO.C have for goal to realize an individual bit input - output. +*/ + +/** @defgroup BIO BIO - Individual bit input-output stream */ +/*@{*/ + +/** +Individual bit input-output stream (BIO) +*/ +typedef struct opj_bio { + /** pointer to the start of the buffer */ + unsigned char *start; + /** pointer to the end of the buffer */ + unsigned char *end; + /** pointer to the present position in the buffer */ + unsigned char *bp; + /** temporary place where each byte is read or written */ + unsigned int buf; + /** coder : number of bits free to write. decoder : number of bits read */ + int ct; +} opj_bio_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new BIO handle +@return Returns a new BIO handle if successful, returns NULL otherwise +*/ +opj_bio_t* bio_create(void); +/** +Destroy a previously created BIO handle +@param bio BIO handle to destroy +*/ +void bio_destroy(opj_bio_t *bio); +/** +Number of bytes written. +@param bio BIO handle +@return Returns the number of bytes written +*/ +int bio_numbytes(opj_bio_t *bio); +/** +Init encoder +@param bio BIO handle +@param bp Output buffer +@param len Output buffer length +*/ +void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int len); +/** +Init decoder +@param bio BIO handle +@param bp Input buffer +@param len Input buffer length +*/ +void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int len); +/** +Write bits +@param bio BIO handle +@param v Value of bits +@param n Number of bits to write +*/ +void bio_write(opj_bio_t *bio, int v, int n); +/** +Read bits +@param bio BIO handle +@param n Number of bits to read +@return Returns the corresponding read number +*/ +int bio_read(opj_bio_t *bio, int n); +/** +Flush bits +@param bio BIO handle +@return Returns 1 if successful, returns 0 otherwise +*/ +int bio_flush(opj_bio_t *bio); +/** +Passes the ending bits (coming from flushing) +@param bio BIO handle +@return Returns 1 if successful, returns 0 otherwise +*/ +int bio_inalign(opj_bio_t *bio); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __BIO_H */ + diff --git a/src/add-ons/translators/icns/openjpeg/cidx_manager.c b/src/add-ons/translators/icns/openjpeg/cidx_manager.c new file mode 100644 index 0000000000..f3b251ffa0 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/cidx_manager.c @@ -0,0 +1,211 @@ +/* + * $Id: cidx_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + + +/* + * Write CPTR Codestream finder box + * + * @param[in] coff offset of j2k codestream + * @param[in] clen length of j2k codestream + * @param[in] cio file output handle + */ +void write_cptr(int coff, int clen, opj_cio_t *cio); + + +/* + * Write main header index table (box) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] cio file output handle + * @return length of mainmhix box + */ +int write_mainmhix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio); + + +/* + * Check if EPH option is used + * + * @param[in] coff offset of j2k codestream + * @param[in] markers marker information + * @param[in] marknum number of markers + * @param[in] cio file output handle + * @return true if EPH is used + */ +opj_bool check_EPHuse( int coff, opj_marker_info_t *markers, int marknum, opj_cio_t *cio); + + +int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen) +{ + int len, i, lenp; + opj_jp2_box_t *box; + int num_box = 0; + opj_bool EPHused; + (void)image; /* unused ? */ + + lenp = -1; + box = (opj_jp2_box_t *)opj_calloc( 32, sizeof(opj_jp2_box_t)); + + for (i=0;i<2;i++){ + + if(i) + cio_seek( cio, lenp); + + lenp = cio_tell( cio); + + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_CIDX, 4); /* CIDX */ + write_cptr( offset, cstr_info.codestream_size, cio); + + write_manf( i, num_box, box, cio); + + num_box = 0; + box[num_box].length = write_mainmhix( offset, cstr_info, cio); + box[num_box].type = JPIP_MHIX; + num_box++; + + box[num_box].length = write_tpix( offset, cstr_info, j2klen, cio); + box[num_box].type = JPIP_TPIX; + num_box++; + + box[num_box].length = write_thix( offset, cstr_info, cio); + box[num_box].type = JPIP_THIX; + num_box++; + + EPHused = check_EPHuse( offset, cstr_info.marker, cstr_info.marknum, cio); + + box[num_box].length = write_ppix( offset, cstr_info, EPHused, j2klen, cio); + box[num_box].type = JPIP_PPIX; + num_box++; + + box[num_box].length = write_phix( offset, cstr_info, EPHused, j2klen, cio); + box[num_box].type = JPIP_PHIX; + num_box++; + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + } + + opj_free( box); + + return len; +} + +void write_cptr(int coff, int clen, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_CPTR, 4); /* T */ + cio_write( cio, 0, 2); /* DR A PRECISER !! */ + cio_write( cio, 0, 2); /* CONT */ + cio_write( cio, coff, 8); /* COFF A PRECISER !! */ + cio_write( cio, clen, 8); /* CLEN */ + len = cio_tell( cio) - lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); +} + +void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio) +{ + int len, lenp, i; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_MANF,4); /* T */ + + if (second){ /* Write only during the second pass */ + for( i=0; i> 2) & 1)) + EPHused = OPJ_TRUE; + cio_seek( cio, org_pos); + + break; + } + } + return EPHused; +} diff --git a/src/add-ons/translators/icns/openjpeg/cidx_manager.h b/src/add-ons/translators/icns/openjpeg/cidx_manager.h new file mode 100644 index 0000000000..23eebd52ba --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/cidx_manager.h @@ -0,0 +1,56 @@ +/* + * $Id: cidx_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +/*! \file + * \brief Modification of jpip.h from 2KAN indexer + */ + + +#ifndef CIDX_MANAGER_H_ +# define CIDX_MANAGER_H_ + +#include "openjpeg.h" + + +/* + * Write Codestream index box (superbox) + * + * @param[in] offset offset of j2k codestream + * @param[in] cio file output handle + * @param[in] image image data + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @return length of cidx box + */ +int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen); + + +#endif /* !CIDX_MANAGER_H_ */ diff --git a/src/add-ons/translators/icns/openjpeg/cio.c b/src/add-ons/translators/icns/openjpeg/cio.c new file mode 100644 index 0000000000..c0cb02827b --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/cio.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/* ----------------------------------------------------------------------- */ + +opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length) { + opj_cp_t *cp = NULL; + opj_cio_t *cio = (opj_cio_t*)opj_malloc(sizeof(opj_cio_t)); + if(!cio) return NULL; + cio->cinfo = cinfo; + if(buffer && length) { + /* wrap a user buffer containing the encoded image */ + cio->openmode = OPJ_STREAM_READ; + cio->buffer = buffer; + cio->length = length; + } + else if(!buffer && !length && cinfo) { + /* allocate a buffer for the encoded image */ + cio->openmode = OPJ_STREAM_WRITE; + switch(cinfo->codec_format) { + case CODEC_J2K: + cp = ((opj_j2k_t*)cinfo->j2k_handle)->cp; + break; + case CODEC_JP2: + cp = ((opj_jp2_t*)cinfo->jp2_handle)->j2k->cp; + break; + default: + opj_free(cio); + return NULL; + } + cio->length = (unsigned int) (0.1625 * cp->img_size + 2000); /* 0.1625 = 1.3/8 and 2000 bytes as a minimum for headers */ + cio->buffer = (unsigned char *)opj_malloc(cio->length); + if(!cio->buffer) { + opj_event_msg(cio->cinfo, EVT_ERROR, "Error allocating memory for compressed bitstream\n"); + opj_free(cio); + return NULL; + } + } + else { + opj_free(cio); + return NULL; + } + + /* Initialize byte IO */ + cio->start = cio->buffer; + cio->end = cio->buffer + cio->length; + cio->bp = cio->buffer; + + return cio; +} + +void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio) { + if(cio) { + if(cio->openmode == OPJ_STREAM_WRITE) { + /* destroy the allocated buffer */ + opj_free(cio->buffer); + } + /* destroy the cio */ + opj_free(cio); + } +} + + +/* ----------------------------------------------------------------------- */ + +/* + * Get position in byte stream. + */ +int OPJ_CALLCONV cio_tell(opj_cio_t *cio) { + return cio->bp - cio->start; +} + +/* + * Set position in byte stream. + * + * pos : position, in number of bytes, from the beginning of the stream + */ +void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) { + cio->bp = cio->start + pos; +} + +/* + * Number of bytes left before the end of the stream. + */ +int cio_numbytesleft(opj_cio_t *cio) { + return cio->end - cio->bp; +} + +/* + * Get pointer to the current position in the stream. + */ +unsigned char *cio_getbp(opj_cio_t *cio) { + return cio->bp; +} + +/* + * Write a byte. + */ +opj_bool cio_byteout(opj_cio_t *cio, unsigned char v) { + if (cio->bp >= cio->end) { + opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n"); + return OPJ_FALSE; + } + *cio->bp++ = v; + return OPJ_TRUE; +} + +/* + * Read a byte. + */ +unsigned char cio_bytein(opj_cio_t *cio) { + if (cio->bp >= cio->end) { + opj_event_msg(cio->cinfo, EVT_ERROR, "read error: passed the end of the codestream (start = %d, current = %d, end = %d\n", cio->start, cio->bp, cio->end); + return 0; + } + return *cio->bp++; +} + +/* + * Write some bytes. + * + * v : value to write + * n : number of bytes to write + */ +unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n) { + int i; + for (i = n - 1; i >= 0; i--) { + if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) ) + return 0; + } + return n; +} + +/* + * Read some bytes. + * + * n : number of bytes to read + * + * return : value of the n bytes read + */ +unsigned int cio_read(opj_cio_t *cio, int n) { + int i; + unsigned int v; + v = 0; + for (i = n - 1; i >= 0; i--) { + v += cio_bytein(cio) << (i << 3); + } + return v; +} + +/* + * Skip some bytes. + * + * n : number of bytes to skip + */ +void cio_skip(opj_cio_t *cio, int n) { + cio->bp += n; +} + + + diff --git a/src/add-ons/translators/icns/openjpeg/cio.h b/src/add-ons/translators/icns/openjpeg/cio.h new file mode 100644 index 0000000000..e62743141c --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/cio.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __CIO_H +#define __CIO_H + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define int64 __int64 +#else +#define int64 long long +#endif + +/** +@file cio.h +@brief Implementation of a byte input-output process (CIO) + +The functions in CIO.C have for goal to realize a byte input / output process. +*/ + +/** @defgroup CIO CIO - byte input-output stream */ +/*@{*/ + +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Number of bytes left before the end of the stream +@param cio CIO handle +@return Returns the number of bytes before the end of the stream +*/ +int cio_numbytesleft(opj_cio_t *cio); +/** +Get pointer to the current position in the stream +@param cio CIO handle +@return Returns a pointer to the current position +*/ +unsigned char *cio_getbp(opj_cio_t *cio); +/** +Write some bytes +@param cio CIO handle +@param v Value to write +@param n Number of bytes to write +@return Returns the number of bytes written or 0 if an error occured +*/ +unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n); +/** +Read some bytes +@param cio CIO handle +@param n Number of bytes to read +@return Returns the value of the n bytes read +*/ +unsigned int cio_read(opj_cio_t *cio, int n); +/** +Skip some bytes +@param cio CIO handle +@param n Number of bytes to skip +*/ +void cio_skip(opj_cio_t *cio, int n); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __CIO_H */ + diff --git a/src/add-ons/translators/icns/openjpeg/dwt.c b/src/add-ons/translators/icns/openjpeg/dwt.c new file mode 100644 index 0000000000..0fbfc2033f --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/dwt.c @@ -0,0 +1,858 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Jonathan Ballard + * Copyright (c) 2007, Callum Lerwick + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#ifdef __SSE__ +#include +#endif + +#include "opj_includes.h" + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + +#define WS(i) v->mem[(i)*2] +#define WD(i) v->mem[(1+(i)*2)] + +/** @name Local data structures */ +/*@{*/ + +typedef struct dwt_local { + int* mem; + int dn; + int sn; + int cas; +} dwt_t; + +typedef union { + float f[4]; +} v4; + +typedef struct v4dwt_local { + v4* wavelet ; + int dn ; + int sn ; + int cas ; +} v4dwt_t ; + +static const float dwt_alpha = 1.586134342f; /* 12994 */ +static const float dwt_beta = 0.052980118f; /* 434 */ +static const float dwt_gamma = -0.882911075f; /* -7233 */ +static const float dwt_delta = -0.443506852f; /* -3633 */ + +static const float K = 1.230174105f; /* 10078 */ +/* FIXME: What is this constant? */ +static const float c13318 = 1.625732422f; + +/*@}*/ + +/** +Virtual function type for wavelet transform in 1-D +*/ +typedef void (*DWT1DFN)(dwt_t* v); + +/** @name Local static functions */ +/*@{*/ + +/** +Forward lazy transform (horizontal) +*/ +static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas); +/** +Forward lazy transform (vertical) +*/ +static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas); +/** +Inverse lazy transform (horizontal) +*/ +static void dwt_interleave_h(dwt_t* h, int *a); +/** +Inverse lazy transform (vertical) +*/ +static void dwt_interleave_v(dwt_t* v, int *a, int x); +/** +Forward 5-3 wavelet transform in 1-D +*/ +static void dwt_encode_1(int *a, int dn, int sn, int cas); +/** +Inverse 5-3 wavelet transform in 1-D +*/ +static void dwt_decode_1(dwt_t *v); +/** +Forward 9-7 wavelet transform in 1-D +*/ +static void dwt_encode_1_real(int *a, int dn, int sn, int cas); +/** +Explicit calculation of the Quantization Stepsizes +*/ +static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize); +/** +Inverse wavelet transform in 2-D. +*/ +static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int i, DWT1DFN fn); + +/*@}*/ + +/*@}*/ + +#define S(i) a[(i)*2] +#define D(i) a[(1+(i)*2)] +#define S_(i) ((i)<0?S(0):((i)>=sn?S(sn-1):S(i))) +#define D_(i) ((i)<0?D(0):((i)>=dn?D(dn-1):D(i))) +/* new */ +#define SS_(i) ((i)<0?S(0):((i)>=dn?S(dn-1):S(i))) +#define DD_(i) ((i)<0?D(0):((i)>=sn?D(sn-1):D(i))) + +/* */ +/* This table contains the norms of the 5-3 wavelets for different bands. */ +/* */ +static const double dwt_norms[4][10] = { + {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93} +}; + +/* */ +/* This table contains the norms of the 9-7 wavelets for different bands. */ +/* */ +static const double dwt_norms_real[4][10] = { + {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2} +}; + +/* +========================================================== + local functions +========================================================== +*/ + +/* */ +/* Forward lazy transform (horizontal). */ +/* */ +static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas) { + int i; + for (i=0; i */ +/* Forward lazy transform (vertical). */ +/* */ +static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas) { + int i; + for (i=0; i */ +/* Inverse lazy transform (horizontal). */ +/* */ +static void dwt_interleave_h(dwt_t* h, int *a) { + int *ai = a; + int *bi = h->mem + h->cas; + int i = h->sn; + while( i-- ) { + *bi = *(ai++); + bi += 2; + } + ai = a + h->sn; + bi = h->mem + 1 - h->cas; + i = h->dn ; + while( i-- ) { + *bi = *(ai++); + bi += 2; + } +} + +/* */ +/* Inverse lazy transform (vertical). */ +/* */ +static void dwt_interleave_v(dwt_t* v, int *a, int x) { + int *ai = a; + int *bi = v->mem + v->cas; + int i = v->sn; + while( i-- ) { + *bi = *ai; + bi += 2; + ai += x; + } + ai = a + (v->sn * x); + bi = v->mem + 1 - v->cas; + i = v->dn ; + while( i-- ) { + *bi = *ai; + bi += 2; + ai += x; + } +} + + +/* */ +/* Forward 5-3 wavelet transform in 1-D. */ +/* */ +static void dwt_encode_1(int *a, int dn, int sn, int cas) { + int i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) D(i) -= (S_(i) + S_(i + 1)) >> 1; + for (i = 0; i < sn; i++) S(i) += (D_(i - 1) + D_(i) + 2) >> 2; + } + } else { + if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ + S(0) *= 2; + else { + for (i = 0; i < dn; i++) S(i) -= (DD_(i) + DD_(i - 1)) >> 1; + for (i = 0; i < sn; i++) D(i) += (SS_(i) + SS_(i + 1) + 2) >> 2; + } + } +} + +/* */ +/* Inverse 5-3 wavelet transform in 1-D. */ +/* */ +static void dwt_decode_1_(int *a, int dn, int sn, int cas) { + int i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < sn; i++) S(i) -= (D_(i - 1) + D_(i) + 2) >> 2; + for (i = 0; i < dn; i++) D(i) += (S_(i) + S_(i + 1)) >> 1; + } + } else { + if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ + S(0) /= 2; + else { + for (i = 0; i < sn; i++) D(i) -= (SS_(i) + SS_(i + 1) + 2) >> 2; + for (i = 0; i < dn; i++) S(i) += (DD_(i) + DD_(i - 1)) >> 1; + } + } +} + +/* */ +/* Inverse 5-3 wavelet transform in 1-D. */ +/* */ +static void dwt_decode_1(dwt_t *v) { + dwt_decode_1_(v->mem, v->dn, v->sn, v->cas); +} + +/* */ +/* Forward 9-7 wavelet transform in 1-D. */ +/* */ +static void dwt_encode_1_real(int *a, int dn, int sn, int cas) { + int i; + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) + D(i) -= fix_mul(S_(i) + S_(i + 1), 12993); + for (i = 0; i < sn; i++) + S(i) -= fix_mul(D_(i - 1) + D_(i), 434); + for (i = 0; i < dn; i++) + D(i) += fix_mul(S_(i) + S_(i + 1), 7233); + for (i = 0; i < sn; i++) + S(i) += fix_mul(D_(i - 1) + D_(i), 3633); + for (i = 0; i < dn; i++) + D(i) = fix_mul(D(i), 5038); /*5038 */ + for (i = 0; i < sn; i++) + S(i) = fix_mul(S(i), 6659); /*6660 */ + } + } else { + if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) + S(i) -= fix_mul(DD_(i) + DD_(i - 1), 12993); + for (i = 0; i < sn; i++) + D(i) -= fix_mul(SS_(i) + SS_(i + 1), 434); + for (i = 0; i < dn; i++) + S(i) += fix_mul(DD_(i) + DD_(i - 1), 7233); + for (i = 0; i < sn; i++) + D(i) += fix_mul(SS_(i) + SS_(i + 1), 3633); + for (i = 0; i < dn; i++) + S(i) = fix_mul(S(i), 5038); /*5038 */ + for (i = 0; i < sn; i++) + D(i) = fix_mul(D(i), 6659); /*6660 */ + } + } +} + +static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize) { + int p, n; + p = int_floorlog2(stepsize) - 13; + n = 11 - int_floorlog2(stepsize); + bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff; + bandno_stepsize->expn = numbps - p; +} + +/* +========================================================== + DWT interface +========================================================== +*/ + +/* */ +/* Forward 5-3 wavelet transform in 2-D. */ +/* */ +void dwt_encode(opj_tcd_tilecomp_t * tilec) { + int i, j, k; + int *a = NULL; + int *aj = NULL; + int *bj = NULL; + int w, l; + + w = tilec->x1-tilec->x0; + l = tilec->numresolutions-1; + a = tilec->data; + + for (i = 0; i < l; i++) { + int rw; /* width of the resolution level computed */ + int rh; /* height of the resolution level computed */ + int rw1; /* width of the resolution level once lower than computed one */ + int rh1; /* height of the resolution level once lower than computed one */ + int cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + int cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + int dn, sn; + + rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0; + rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0; + rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0; + rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0; + + cas_row = tilec->resolutions[l - i].x0 % 2; + cas_col = tilec->resolutions[l - i].y0 % 2; + + sn = rh1; + dn = rh - rh1; + bj = (int*)opj_malloc(rh * sizeof(int)); + for (j = 0; j < rw; j++) { + aj = a + j; + for (k = 0; k < rh; k++) bj[k] = aj[k*w]; + dwt_encode_1(bj, dn, sn, cas_col); + dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); + } + opj_free(bj); + + sn = rw1; + dn = rw - rw1; + bj = (int*)opj_malloc(rw * sizeof(int)); + for (j = 0; j < rh; j++) { + aj = a + j * w; + for (k = 0; k < rw; k++) bj[k] = aj[k]; + dwt_encode_1(bj, dn, sn, cas_row); + dwt_deinterleave_h(bj, aj, dn, sn, cas_row); + } + opj_free(bj); + } +} + + +/* */ +/* Inverse 5-3 wavelet transform in 2-D. */ +/* */ +void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres) { + dwt_decode_tile(tilec, numres, &dwt_decode_1); +} + + +/* */ +/* Get gain of 5-3 wavelet transform. */ +/* */ +int dwt_getgain(int orient) { + if (orient == 0) + return 0; + if (orient == 1 || orient == 2) + return 1; + return 2; +} + +/* */ +/* Get norm of 5-3 wavelet. */ +/* */ +double dwt_getnorm(int level, int orient) { + return dwt_norms[orient][level]; +} + +/* */ +/* Forward 9-7 wavelet transform in 2-D. */ +/* */ + +void dwt_encode_real(opj_tcd_tilecomp_t * tilec) { + int i, j, k; + int *a = NULL; + int *aj = NULL; + int *bj = NULL; + int w, l; + + w = tilec->x1-tilec->x0; + l = tilec->numresolutions-1; + a = tilec->data; + + for (i = 0; i < l; i++) { + int rw; /* width of the resolution level computed */ + int rh; /* height of the resolution level computed */ + int rw1; /* width of the resolution level once lower than computed one */ + int rh1; /* height of the resolution level once lower than computed one */ + int cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + int cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + int dn, sn; + + rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0; + rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0; + rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0; + rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0; + + cas_row = tilec->resolutions[l - i].x0 % 2; + cas_col = tilec->resolutions[l - i].y0 % 2; + + sn = rh1; + dn = rh - rh1; + bj = (int*)opj_malloc(rh * sizeof(int)); + for (j = 0; j < rw; j++) { + aj = a + j; + for (k = 0; k < rh; k++) bj[k] = aj[k*w]; + dwt_encode_1_real(bj, dn, sn, cas_col); + dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); + } + opj_free(bj); + + sn = rw1; + dn = rw - rw1; + bj = (int*)opj_malloc(rw * sizeof(int)); + for (j = 0; j < rh; j++) { + aj = a + j * w; + for (k = 0; k < rw; k++) bj[k] = aj[k]; + dwt_encode_1_real(bj, dn, sn, cas_row); + dwt_deinterleave_h(bj, aj, dn, sn, cas_row); + } + opj_free(bj); + } +} + + +/* */ +/* Get gain of 9-7 wavelet transform. */ +/* */ +int dwt_getgain_real(int orient) { + (void)orient; + return 0; +} + +/* */ +/* Get norm of 9-7 wavelet. */ +/* */ +double dwt_getnorm_real(int level, int orient) { + return dwt_norms_real[orient][level]; +} + +void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec) { + int numbands, bandno; + numbands = 3 * tccp->numresolutions - 2; + for (bandno = 0; bandno < numbands; bandno++) { + double stepsize; + int resno, level, orient, gain; + + resno = (bandno == 0) ? 0 : ((bandno - 1) / 3 + 1); + orient = (bandno == 0) ? 0 : ((bandno - 1) % 3 + 1); + level = tccp->numresolutions - 1 - resno; + gain = (tccp->qmfbid == 0) ? 0 : ((orient == 0) ? 0 : (((orient == 1) || (orient == 2)) ? 1 : 2)); + if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + stepsize = 1.0; + } else { + double norm = dwt_norms_real[orient][level]; + stepsize = (1 << (gain)) / norm; + } + dwt_encode_stepsize((int) floor(stepsize * 8192.0), prec + gain, &tccp->stepsizes[bandno]); + } +} + + +/* */ +/* Determine maximum computed resolution level for inverse wavelet transform */ +/* */ +static int dwt_decode_max_resolution(opj_tcd_resolution_t* restrict r, int i) { + int mr = 1; + int w; + while( --i ) { + r++; + if( mr < ( w = r->x1 - r->x0 ) ) + mr = w ; + if( mr < ( w = r->y1 - r->y0 ) ) + mr = w ; + } + return mr ; +} + + +/* */ +/* Inverse wavelet transform in 2-D. */ +/* */ +static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1D) { + dwt_t h; + dwt_t v; + + opj_tcd_resolution_t* tr = tilec->resolutions; + + int rw = tr->x1 - tr->x0; /* width of the resolution level computed */ + int rh = tr->y1 - tr->y0; /* height of the resolution level computed */ + + int w = tilec->x1 - tilec->x0; + + h.mem = (int*)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int)); + v.mem = h.mem; + + while( --numres) { + int * restrict tiledp = tilec->data; + int j; + + ++tr; + h.sn = rw; + v.sn = rh; + + rw = tr->x1 - tr->x0; + rh = tr->y1 - tr->y0; + + h.dn = rw - h.sn; + h.cas = tr->x0 % 2; + + for(j = 0; j < rh; ++j) { + dwt_interleave_h(&h, &tiledp[j*w]); + (dwt_1D)(&h); + memcpy(&tiledp[j*w], h.mem, rw * sizeof(int)); + } + + v.dn = rh - v.sn; + v.cas = tr->y0 % 2; + + for(j = 0; j < rw; ++j){ + int k; + dwt_interleave_v(&v, &tiledp[j], w); + (dwt_1D)(&v); + for(k = 0; k < rh; ++k) { + tiledp[k * w + j] = v.mem[k]; + } + } + } + opj_aligned_free(h.mem); +} + +static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, int size){ + float* restrict bi = (float*) (w->wavelet + w->cas); + int count = w->sn; + int i, k; + for(k = 0; k < 2; ++k){ + if (count + 3 * x < size && ((size_t) a & 0x0f) == 0 && ((size_t) bi & 0x0f) == 0 && (x & 0x0f) == 0) { + /* Fast code path */ + for(i = 0; i < count; ++i){ + int j = i; + bi[i*8 ] = a[j]; + j += x; + bi[i*8 + 1] = a[j]; + j += x; + bi[i*8 + 2] = a[j]; + j += x; + bi[i*8 + 3] = a[j]; + } + } else { + /* Slow code path */ + for(i = 0; i < count; ++i){ + int j = i; + bi[i*8 ] = a[j]; + j += x; + if(j > size) continue; + bi[i*8 + 1] = a[j]; + j += x; + if(j > size) continue; + bi[i*8 + 2] = a[j]; + j += x; + if(j > size) continue; + bi[i*8 + 3] = a[j]; + } + } + bi = (float*) (w->wavelet + 1 - w->cas); + a += w->sn; + size -= w->sn; + count = w->dn; + } +} + +static void v4dwt_interleave_v(v4dwt_t* restrict v , float* restrict a , int x){ + v4* restrict bi = v->wavelet + v->cas; + int i; + for(i = 0; i < v->sn; ++i){ + memcpy(&bi[i*2], &a[i*x], 4 * sizeof(float)); + } + a += v->sn * x; + bi = v->wavelet + 1 - v->cas; + for(i = 0; i < v->dn; ++i){ + memcpy(&bi[i*2], &a[i*x], 4 * sizeof(float)); + } +} + +#ifdef __SSE__ + +static void v4dwt_decode_step1_sse(v4* w, int count, const __m128 c){ + __m128* restrict vw = (__m128*) w; + int i; + /* 4x unrolled loop */ + for(i = 0; i < count >> 2; ++i){ + *vw = _mm_mul_ps(*vw, c); + vw += 2; + *vw = _mm_mul_ps(*vw, c); + vw += 2; + *vw = _mm_mul_ps(*vw, c); + vw += 2; + *vw = _mm_mul_ps(*vw, c); + vw += 2; + } + count &= 3; + for(i = 0; i < count; ++i){ + *vw = _mm_mul_ps(*vw, c); + vw += 2; + } +} + +static void v4dwt_decode_step2_sse(v4* l, v4* w, int k, int m, __m128 c){ + __m128* restrict vl = (__m128*) l; + __m128* restrict vw = (__m128*) w; + int i; + __m128 tmp1, tmp2, tmp3; + tmp1 = vl[0]; + for(i = 0; i < m; ++i){ + tmp2 = vw[-1]; + tmp3 = vw[ 0]; + vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c)); + tmp1 = tmp3; + vw += 2; + } + vl = vw - 2; + if(m >= k){ + return; + } + c = _mm_add_ps(c, c); + c = _mm_mul_ps(c, vl[0]); + for(; m < k; ++m){ + __m128 tmp = vw[-1]; + vw[-1] = _mm_add_ps(tmp, c); + vw += 2; + } +} + +#else + +static void v4dwt_decode_step1(v4* w, int count, const float c){ + float* restrict fw = (float*) w; + int i; + for(i = 0; i < count; ++i){ + float tmp1 = fw[i*8 ]; + float tmp2 = fw[i*8 + 1]; + float tmp3 = fw[i*8 + 2]; + float tmp4 = fw[i*8 + 3]; + fw[i*8 ] = tmp1 * c; + fw[i*8 + 1] = tmp2 * c; + fw[i*8 + 2] = tmp3 * c; + fw[i*8 + 3] = tmp4 * c; + } +} + +static void v4dwt_decode_step2(v4* l, v4* w, int k, int m, float c){ + float* restrict fl = (float*) l; + float* restrict fw = (float*) w; + int i; + for(i = 0; i < m; ++i){ + float tmp1_1 = fl[0]; + float tmp1_2 = fl[1]; + float tmp1_3 = fl[2]; + float tmp1_4 = fl[3]; + float tmp2_1 = fw[-4]; + float tmp2_2 = fw[-3]; + float tmp2_3 = fw[-2]; + float tmp2_4 = fw[-1]; + float tmp3_1 = fw[0]; + float tmp3_2 = fw[1]; + float tmp3_3 = fw[2]; + float tmp3_4 = fw[3]; + fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c); + fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c); + fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c); + fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c); + fl = fw; + fw += 8; + } + if(m < k){ + float c1; + float c2; + float c3; + float c4; + c += c; + c1 = fl[0] * c; + c2 = fl[1] * c; + c3 = fl[2] * c; + c4 = fl[3] * c; + for(; m < k; ++m){ + float tmp1 = fw[-4]; + float tmp2 = fw[-3]; + float tmp3 = fw[-2]; + float tmp4 = fw[-1]; + fw[-4] = tmp1 + c1; + fw[-3] = tmp2 + c2; + fw[-2] = tmp3 + c3; + fw[-1] = tmp4 + c4; + fw += 8; + } + } +} + +#endif + +/* */ +/* Inverse 9-7 wavelet transform in 1-D. */ +/* */ +static void v4dwt_decode(v4dwt_t* restrict dwt){ + int a, b; + if(dwt->cas == 0) { + if(!((dwt->dn > 0) || (dwt->sn > 1))){ + return; + } + a = 0; + b = 1; + }else{ + if(!((dwt->sn > 0) || (dwt->dn > 1))) { + return; + } + a = 1; + b = 0; + } +#ifdef __SSE__ + v4dwt_decode_step1_sse(dwt->wavelet+a, dwt->sn, _mm_set1_ps(K)); + v4dwt_decode_step1_sse(dwt->wavelet+b, dwt->dn, _mm_set1_ps(c13318)); + v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_delta)); + v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_gamma)); + v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_beta)); + v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_alpha)); +#else + v4dwt_decode_step1(dwt->wavelet+a, dwt->sn, K); + v4dwt_decode_step1(dwt->wavelet+b, dwt->dn, c13318); + v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_delta); + v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_gamma); + v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_beta); + v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_alpha); +#endif +} + +/* */ +/* Inverse 9-7 wavelet transform in 2-D. */ +/* */ +void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ + v4dwt_t h; + v4dwt_t v; + + opj_tcd_resolution_t* res = tilec->resolutions; + + int rw = res->x1 - res->x0; /* width of the resolution level computed */ + int rh = res->y1 - res->y0; /* height of the resolution level computed */ + + int w = tilec->x1 - tilec->x0; + + h.wavelet = (v4*) opj_aligned_malloc((dwt_decode_max_resolution(res, numres)+5) * sizeof(v4)); + v.wavelet = h.wavelet; + + while( --numres) { + float * restrict aj = (float*) tilec->data; + int bufsize = (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0); + int j; + + h.sn = rw; + v.sn = rh; + + ++res; + + rw = res->x1 - res->x0; /* width of the resolution level computed */ + rh = res->y1 - res->y0; /* height of the resolution level computed */ + + h.dn = rw - h.sn; + h.cas = res->x0 % 2; + + for(j = rh; j > 3; j -= 4){ + int k; + v4dwt_interleave_h(&h, aj, w, bufsize); + v4dwt_decode(&h); + for(k = rw; --k >= 0;){ + aj[k ] = h.wavelet[k].f[0]; + aj[k+w ] = h.wavelet[k].f[1]; + aj[k+w*2] = h.wavelet[k].f[2]; + aj[k+w*3] = h.wavelet[k].f[3]; + } + aj += w*4; + bufsize -= w*4; + } + if (rh & 0x03) { + int k; + j = rh & 0x03; + v4dwt_interleave_h(&h, aj, w, bufsize); + v4dwt_decode(&h); + for(k = rw; --k >= 0;){ + switch(j) { + case 3: aj[k+w*2] = h.wavelet[k].f[2]; + case 2: aj[k+w ] = h.wavelet[k].f[1]; + case 1: aj[k ] = h.wavelet[k].f[0]; + } + } + } + + v.dn = rh - v.sn; + v.cas = res->y0 % 2; + + aj = (float*) tilec->data; + for(j = rw; j > 3; j -= 4){ + int k; + v4dwt_interleave_v(&v, aj, w); + v4dwt_decode(&v); + for(k = 0; k < rh; ++k){ + memcpy(&aj[k*w], &v.wavelet[k], 4 * sizeof(float)); + } + aj += 4; + } + if (rw & 0x03){ + int k; + j = rw & 0x03; + v4dwt_interleave_v(&v, aj, w); + v4dwt_decode(&v); + for(k = 0; k < rh; ++k){ + memcpy(&aj[k*w], &v.wavelet[k], j * sizeof(float)); + } + } + } + + opj_aligned_free(h.wavelet); +} + diff --git a/src/add-ons/translators/icns/openjpeg/dwt.h b/src/add-ons/translators/icns/openjpeg/dwt.h new file mode 100644 index 0000000000..adf73e5440 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/dwt.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __DWT_H +#define __DWT_H +/** +@file dwt.h +@brief Implementation of a discrete wavelet transform (DWT) + +The functions in DWT.C have for goal to realize forward and inverse discret wavelet +transform with filter 5-3 (reversible) and filter 9-7 (irreversible). The functions in +DWT.C are used by some function in TCD.C. +*/ + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Forward 5-3 wavelet tranform in 2-D. +Apply a reversible DWT transform to a component of an image. +@param tilec Tile component information (current tile) +*/ +void dwt_encode(opj_tcd_tilecomp_t * tilec); +/** +Inverse 5-3 wavelet tranform in 2-D. +Apply a reversible inverse DWT transform to a component of an image. +@param tilec Tile component information (current tile) +@param numres Number of resolution levels to decode +*/ +void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres); +/** +Get the gain of a subband for the reversible 5-3 DWT. +@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) +@return Returns 0 if orient = 0, returns 1 if orient = 1 or 2, returns 2 otherwise +*/ +int dwt_getgain(int orient); +/** +Get the norm of a wavelet function of a subband at a specified level for the reversible 5-3 DWT. +@param level Level of the wavelet function +@param orient Band of the wavelet function +@return Returns the norm of the wavelet function +*/ +double dwt_getnorm(int level, int orient); +/** +Forward 9-7 wavelet transform in 2-D. +Apply an irreversible DWT transform to a component of an image. +@param tilec Tile component information (current tile) +*/ +void dwt_encode_real(opj_tcd_tilecomp_t * tilec); +/** +Inverse 9-7 wavelet transform in 2-D. +Apply an irreversible inverse DWT transform to a component of an image. +@param tilec Tile component information (current tile) +@param numres Number of resolution levels to decode +*/ +void dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres); +/** +Get the gain of a subband for the irreversible 9-7 DWT. +@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) +@return Returns the gain of the 9-7 wavelet transform +*/ +int dwt_getgain_real(int orient); +/** +Get the norm of a wavelet function of a subband at a specified level for the irreversible 9-7 DWT +@param level Level of the wavelet function +@param orient Band of the wavelet function +@return Returns the norm of the 9-7 wavelet +*/ +double dwt_getnorm_real(int level, int orient); +/** +Explicit calculation of the Quantization Stepsizes +@param tccp Tile-component coding parameters +@param prec Precint analyzed +*/ +void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __DWT_H */ diff --git a/src/add-ons/translators/icns/openjpeg/event.c b/src/add-ons/translators/icns/openjpeg/event.c new file mode 100644 index 0000000000..38db33a943 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/event.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/* ========================================================== + Utility functions + ==========================================================*/ + +#ifdef OPJ_CODE_NOT_USED +#ifndef _WIN32 +static char* +i2a(unsigned i, char *a, unsigned r) { + if (i/r > 0) a = i2a(i/r,a,r); + *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r]; + return a+1; +} + +/** + Transforms integer i into an ascii string and stores the result in a; + string is encoded in the base indicated by r. + @param i Number to be converted + @param a String result + @param r Base of value; must be in the range 2 - 36 + @return Returns a +*/ +static char * +_itoa(int i, char *a, int r) { + r = ((r < 2) || (r > 36)) ? 10 : r; + if(i < 0) { + *a = '-'; + *i2a(-i, a+1, r) = 0; + } + else *i2a(i, a, r) = 0; + return a; +} + +#endif /* !_WIN32 */ +#endif +/* ----------------------------------------------------------------------- */ + +opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) { + if(cinfo) { + opj_event_mgr_t *previous = cinfo->event_mgr; + cinfo->event_mgr = event_mgr; + cinfo->client_data = context; + return previous; + } + + return NULL; +} + +opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) { +#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */ + opj_msg_callback msg_handler = NULL; + + opj_event_mgr_t *event_mgr = cinfo->event_mgr; + if(event_mgr != NULL) { + switch(event_type) { + case EVT_ERROR: + msg_handler = event_mgr->error_handler; + break; + case EVT_WARNING: + msg_handler = event_mgr->warning_handler; + break; + case EVT_INFO: + msg_handler = event_mgr->info_handler; + break; + default: + break; + } + if(msg_handler == NULL) { + return OPJ_FALSE; + } + } else { + return OPJ_FALSE; + } + + if ((fmt != NULL) && (event_mgr != NULL)) { + va_list arg; + int str_length/*, i, j*/; /* UniPG */ + char message[MSG_SIZE]; + /* initialize the optional parameter list */ + va_start(arg, fmt); + /* parse the format string and put the result in 'message' */ + str_length = vsnprintf(message, MSG_SIZE, fmt, arg); /* UniPG */ + /* deinitialize the optional parameter list */ + va_end(arg); + + /* output the message to the user program */ + if( str_length > -1 && str_length < MSG_SIZE ) + msg_handler(message, cinfo->client_data); + else return OPJ_FALSE; + } + + return OPJ_TRUE; +} + diff --git a/src/add-ons/translators/icns/openjpeg/event.h b/src/add-ons/translators/icns/openjpeg/event.h new file mode 100644 index 0000000000..9c59787caf --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/event.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __EVENT_H +#define __EVENT_H +/** +@file event.h +@brief Implementation of a event callback system + +The functions in EVENT.C have for goal to send output messages (errors, warnings, debug) to the user. +*/ + +#define EVT_ERROR 1 /**< Error event type */ +#define EVT_WARNING 2 /**< Warning event type */ +#define EVT_INFO 4 /**< Debug event type */ + +/** @defgroup EVENT EVENT - Implementation of a event callback system */ +/*@{*/ + +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Write formatted data to a string and send the string to a user callback. +@param cinfo Codec context info +@param event_type Event type or callback to use to send the message +@param fmt Format-control string (plus optionnal arguments) +@return Returns true if successful, returns false otherwise +*/ +opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __EVENT_H */ diff --git a/src/add-ons/translators/icns/openjpeg/fix.h b/src/add-ons/translators/icns/openjpeg/fix.h new file mode 100644 index 0000000000..bcb2acb54c --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/fix.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __FIX_H +#define __FIX_H + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define int64 __int64 +#else +#define int64 long long +#endif + +/** +@file fix.h +@brief Implementation of operations of specific multiplication (FIX) + +The functions in FIX.H have for goal to realize specific multiplication. +*/ + +/** @defgroup FIX FIX - Implementation of operations of specific multiplication */ +/*@{*/ + +/** +Multiply two fixed-precision rational numbers. +@param a +@param b +@return Returns a * b +*/ +static INLINE int fix_mul(int a, int b) { + int64 temp = (int64) a * (int64) b ; + temp += temp & 4096; + return (int) (temp >> 13) ; +} + +/*@}*/ + +#endif /* __FIX_H */ diff --git a/src/add-ons/translators/icns/openjpeg/image.c b/src/add-ons/translators/icns/openjpeg/image.c new file mode 100644 index 0000000000..a4d2c010a5 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/image.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +opj_image_t* opj_image_create0(void) { + opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t)); + return image; +} + +opj_image_t* OPJ_CALLCONV opj_image_create(int numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) { + int compno; + opj_image_t *image = NULL; + + image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t)); + if(image) { + image->color_space = clrspc; + image->numcomps = numcmpts; + /* allocate memory for the per-component information */ + image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t)); + if(!image->comps) { + fprintf(stderr,"Unable to allocate memory for image.\n"); + opj_image_destroy(image); + return NULL; + } + /* create the individual image components */ + for(compno = 0; compno < numcmpts; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->prec = cmptparms[compno].prec; + comp->bpp = cmptparms[compno].bpp; + comp->sgnd = cmptparms[compno].sgnd; + comp->data = (int*) opj_calloc(comp->w * comp->h, sizeof(int)); + if(!comp->data) { + fprintf(stderr,"Unable to allocate memory for image.\n"); + opj_image_destroy(image); + return NULL; + } + } + } + + return image; +} + +void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) { + int i; + if(image) { + if(image->comps) { + /* image components */ + for(i = 0; i < image->numcomps; i++) { + opj_image_comp_t *image_comp = &image->comps[i]; + if(image_comp->data) { + opj_free(image_comp->data); + } + } + opj_free(image->comps); + } + opj_free(image); + } +} + diff --git a/src/add-ons/translators/icns/openjpeg/indexbox_manager.h b/src/add-ons/translators/icns/openjpeg/indexbox_manager.h new file mode 100644 index 0000000000..7364df62c2 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/indexbox_manager.h @@ -0,0 +1,118 @@ +/* + * $Id: indexbox_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#ifndef INDEXBOX_MANAGER_H_ +# define INDEXBOX_MANAGER_H_ + +#include "openjpeg.h" +#include "j2k.h" /* needed to use jp2.h */ +#include "jp2.h" + +#define JPIP_CIDX 0x63696478 /* Codestream index */ +#define JPIP_CPTR 0x63707472 /* Codestream Finder Box */ +#define JPIP_MANF 0x6d616e66 /* Manifest Box */ +#define JPIP_FAIX 0x66616978 /* Fragment array Index box */ +#define JPIP_MHIX 0x6d686978 /* Main Header Index Table */ +#define JPIP_TPIX 0x74706978 /* Tile-part Index Table box */ +#define JPIP_THIX 0x74686978 /* Tile header Index Table box */ +#define JPIP_PPIX 0x70706978 /* Precinct Packet Index Table box */ +#define JPIP_PHIX 0x70686978 /* Packet Header index Table */ +#define JPIP_FIDX 0x66696478 /* File Index */ +#define JPIP_FPTR 0x66707472 /* File Finder */ +#define JPIP_PRXY 0x70727879 /* Proxy boxes */ +#define JPIP_IPTR 0x69707472 /* Index finder box */ +#define JPIP_PHLD 0x70686c64 /* Place holder */ + + +/* + * Write tile-part Index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of tpix box + */ +int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio); + + +/* + * Write tile header index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information pointer + * @param[in] cio file output handle + * @return length of thix box + */ +int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio); + + +/* + * Write precinct packet index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] EPHused true if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of ppix box + */ +int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + + +/* + * Write packet header index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] EPHused true if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of ppix box + */ +int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + +/* + * Wriet manifest box (box) + * + * @param[in] second number to be visited + * @param[in] v number of boxes + * @param[in] box box to be manifested + * @param[in] cio file output handle + */ +void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio); + + +#endif /* !INDEXBOX_MANAGER_H_ */ diff --git a/src/add-ons/translators/icns/openjpeg/int.h b/src/add-ons/translators/icns/openjpeg/int.h new file mode 100644 index 0000000000..4e5fe08eb7 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/int.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __INT_H +#define __INT_H +/** +@file int.h +@brief Implementation of operations on integers (INT) + +The functions in INT.H have for goal to realize operations on integers. +*/ + +/** @defgroup INT INT - Implementation of operations on integers */ +/*@{*/ + +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Get the minimum of two integers +@return Returns a if a < b else b +*/ +static INLINE int int_min(int a, int b) { + return a < b ? a : b; +} +/** +Get the maximum of two integers +@return Returns a if a > b else b +*/ +static INLINE int int_max(int a, int b) { + return (a > b) ? a : b; +} +/** +Clamp an integer inside an interval +@return +
    +
  • Returns a if (min < a < max) +
  • Returns max if (a > max) +
  • Returns min if (a < min) +
+*/ +static INLINE int int_clamp(int a, int min, int max) { + if (a < min) + return min; + if (a > max) + return max; + return a; +} +/** +@return Get absolute value of integer +*/ +static INLINE int int_abs(int a) { + return a < 0 ? -a : a; +} +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static INLINE int int_ceildiv(int a, int b) { + return (a + b - 1) / b; +} +/** +Divide an integer by a power of 2 and round upwards +@return Returns a divided by 2^b +*/ +static INLINE int int_ceildivpow2(int a, int b) { + return (a + (1 << b) - 1) >> b; +} +/** +Divide an integer by a power of 2 and round downwards +@return Returns a divided by 2^b +*/ +static INLINE int int_floordivpow2(int a, int b) { + return a >> b; +} +/** +Get logarithm of an integer and round downwards +@return Returns log2(a) +*/ +static INLINE int int_floorlog2(int a) { + int l; + for (l = 0; a > 1; l++) { + a >>= 1; + } + return l; +} +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif diff --git a/src/add-ons/translators/icns/openjpeg/j2k.c b/src/add-ons/translators/icns/openjpeg/j2k.c new file mode 100644 index 0000000000..3f8e27909a --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/j2k.c @@ -0,0 +1,2616 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Write the SOC marker (Start Of Codestream) +@param j2k J2K handle +*/ +static void j2k_write_soc(opj_j2k_t *j2k); +/** +Read the SOC marker (Start of Codestream) +@param j2k J2K handle +*/ +static void j2k_read_soc(opj_j2k_t *j2k); +/** +Write the SIZ marker (image and tile size) +@param j2k J2K handle +*/ +static void j2k_write_siz(opj_j2k_t *j2k); +/** +Read the SIZ marker (image and tile size) +@param j2k J2K handle +*/ +static void j2k_read_siz(opj_j2k_t *j2k); +/** +Write the COM marker (comment) +@param j2k J2K handle +*/ +static void j2k_write_com(opj_j2k_t *j2k); +/** +Read the COM marker (comment) +@param j2k J2K handle +*/ +static void j2k_read_com(opj_j2k_t *j2k); +/** +Write the value concerning the specified component in the marker COD and COC +@param j2k J2K handle +@param compno Number of the component concerned by the information written +*/ +static void j2k_write_cox(opj_j2k_t *j2k, int compno); +/** +Read the value concerning the specified component in the marker COD and COC +@param j2k J2K handle +@param compno Number of the component concerned by the information read +*/ +static void j2k_read_cox(opj_j2k_t *j2k, int compno); +/** +Write the COD marker (coding style default) +@param j2k J2K handle +*/ +static void j2k_write_cod(opj_j2k_t *j2k); +/** +Read the COD marker (coding style default) +@param j2k J2K handle +*/ +static void j2k_read_cod(opj_j2k_t *j2k); +/** +Write the COC marker (coding style component) +@param j2k J2K handle +@param compno Number of the component concerned by the information written +*/ +static void j2k_write_coc(opj_j2k_t *j2k, int compno); +/** +Read the COC marker (coding style component) +@param j2k J2K handle +*/ +static void j2k_read_coc(opj_j2k_t *j2k); +/** +Write the value concerning the specified component in the marker QCD and QCC +@param j2k J2K handle +@param compno Number of the component concerned by the information written +*/ +static void j2k_write_qcx(opj_j2k_t *j2k, int compno); +/** +Read the value concerning the specified component in the marker QCD and QCC +@param j2k J2K handle +@param compno Number of the component concern by the information read +@param len Length of the information in the QCX part of the marker QCD/QCC +*/ +static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len); +/** +Write the QCD marker (quantization default) +@param j2k J2K handle +*/ +static void j2k_write_qcd(opj_j2k_t *j2k); +/** +Read the QCD marker (quantization default) +@param j2k J2K handle +*/ +static void j2k_read_qcd(opj_j2k_t *j2k); +/** +Write the QCC marker (quantization component) +@param j2k J2K handle +@param compno Number of the component concerned by the information written +*/ +static void j2k_write_qcc(opj_j2k_t *j2k, int compno); +/** +Read the QCC marker (quantization component) +@param j2k J2K handle +*/ +static void j2k_read_qcc(opj_j2k_t *j2k); +/** +Write the POC marker (progression order change) +@param j2k J2K handle +*/ +static void j2k_write_poc(opj_j2k_t *j2k); +/** +Read the POC marker (progression order change) +@param j2k J2K handle +*/ +static void j2k_read_poc(opj_j2k_t *j2k); +/** +Read the CRG marker (component registration) +@param j2k J2K handle +*/ +static void j2k_read_crg(opj_j2k_t *j2k); +/** +Read the TLM marker (tile-part lengths) +@param j2k J2K handle +*/ +static void j2k_read_tlm(opj_j2k_t *j2k); +/** +Read the PLM marker (packet length, main header) +@param j2k J2K handle +*/ +static void j2k_read_plm(opj_j2k_t *j2k); +/** +Read the PLT marker (packet length, tile-part header) +@param j2k J2K handle +*/ +static void j2k_read_plt(opj_j2k_t *j2k); +/** +Read the PPM marker (packet packet headers, main header) +@param j2k J2K handle +*/ +static void j2k_read_ppm(opj_j2k_t *j2k); +/** +Read the PPT marker (packet packet headers, tile-part header) +@param j2k J2K handle +*/ +static void j2k_read_ppt(opj_j2k_t *j2k); +/** +Write the TLM marker (Mainheader) +@param j2k J2K handle +*/ +static void j2k_write_tlm(opj_j2k_t *j2k); +/** +Write the SOT marker (start of tile-part) +@param j2k J2K handle +*/ +static void j2k_write_sot(opj_j2k_t *j2k); +/** +Read the SOT marker (start of tile-part) +@param j2k J2K handle +*/ +static void j2k_read_sot(opj_j2k_t *j2k); +/** +Write the SOD marker (start of data) +@param j2k J2K handle +@param tile_coder Pointer to a TCD handle +*/ +static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder); +/** +Read the SOD marker (start of data) +@param j2k J2K handle +*/ +static void j2k_read_sod(opj_j2k_t *j2k); +/** +Write the RGN marker (region-of-interest) +@param j2k J2K handle +@param compno Number of the component concerned by the information written +@param tileno Number of the tile concerned by the information written +*/ +static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno); +/** +Read the RGN marker (region-of-interest) +@param j2k J2K handle +*/ +static void j2k_read_rgn(opj_j2k_t *j2k); +/** +Write the EOC marker (end of codestream) +@param j2k J2K handle +*/ +static void j2k_write_eoc(opj_j2k_t *j2k); +/** +Read the EOC marker (end of codestream) +@param j2k J2K handle +*/ +static void j2k_read_eoc(opj_j2k_t *j2k); +/** +Read an unknown marker +@param j2k J2K handle +*/ +static void j2k_read_unk(opj_j2k_t *j2k); +/** +Add main header marker information +@param cstr_info Codestream information structure +@param type marker type +@param pos byte offset of marker segment +@param len length of marker segment + */ +static void j2k_add_mhmarker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len); +/** +Add tile header marker information +@param tileno tile index number +@param cstr_info Codestream information structure +@param type marker type +@param pos byte offset of marker segment +@param len length of marker segment + */ +static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ +typedef struct j2k_prog_order{ + OPJ_PROG_ORDER enum_prog; + char str_prog[5]; +}j2k_prog_order_t; + +j2k_prog_order_t j2k_prog_order_list[] = { + {CPRL, "CPRL"}, + {LRCP, "LRCP"}, + {PCRL, "PCRL"}, + {RLCP, "RLCP"}, + {RPCL, "RPCL"}, + {(OPJ_PROG_ORDER)-1, ""} +}; + +char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){ + j2k_prog_order_t *po; + for(po = j2k_prog_order_list; po->enum_prog != -1; po++ ){ + if(po->enum_prog == prg_order){ + break; + } + } + return po->str_prog; +} + +/* ----------------------------------------------------------------------- */ +static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){ + char *prog; + int i; + int tpnum=1,tpend=0; + opj_tcp_t *tcp = &cp->tcps[tileno]; + prog = j2k_convert_progression_order(tcp->prg); + + if(cp->tp_on == 1){ + for(i=0;i<4;i++){ + if(tpend!=1){ + if( cp->tp_flag == prog[i] ){ + tpend=1;cp->tp_pos=i; + } + switch(prog[i]){ + case 'C': + tpnum= tpnum * tcp->pocs[pino].compE; + break; + case 'R': + tpnum= tpnum * tcp->pocs[pino].resE; + break; + case 'P': + tpnum= tpnum * tcp->pocs[pino].prcE; + break; + case 'L': + tpnum= tpnum * tcp->pocs[pino].layE; + break; + } + } + } + }else{ + tpnum=1; + } + return tpnum; +} + +/** mem allocation for TLM marker*/ +int j2k_calculate_tp(opj_cp_t *cp,int img_numcomp,opj_image_t *image,opj_j2k_t *j2k ){ + int pino,tileno,totnum_tp=0; + + OPJ_ARG_NOT_USED(img_numcomp); + + j2k->cur_totnum_tp = (int *) opj_malloc(cp->tw * cp->th * sizeof(int)); + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + int cur_totnum_tp = 0; + opj_tcp_t *tcp = &cp->tcps[tileno]; + for(pino = 0; pino <= tcp->numpocs; pino++) { + int tp_num=0; + opj_pi_iterator_t *pi = pi_initialise_encode(image, cp, tileno,FINAL_PASS); + if(!pi) { return -1;} + tp_num = j2k_get_num_tp(cp,pino,tileno); + totnum_tp = totnum_tp + tp_num; + cur_totnum_tp = cur_totnum_tp + tp_num; + pi_destroy(pi, cp, tileno); + } + j2k->cur_totnum_tp[tileno] = cur_totnum_tp; + /* INDEX >> */ + if (j2k->cstr_info) { + j2k->cstr_info->tile[tileno].num_tps = cur_totnum_tp; + j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(cur_totnum_tp * sizeof(opj_tp_info_t)); + } + /* << INDEX */ + } + return totnum_tp; +} + +static void j2k_write_soc(opj_j2k_t *j2k) { + opj_cio_t *cio = j2k->cio; + cio_write(cio, J2K_MS_SOC, 2); + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_SOC, cio_tell(cio), 0); + +/* UniPG>> */ +#ifdef USE_JPWL + + /* update markers struct */ + j2k_add_marker(j2k->cstr_info, J2K_MS_SOC, cio_tell(cio) - 2, 2); +#endif /* USE_JPWL */ +/* <state = J2K_STATE_MHSIZ; + /* Index */ + if (j2k->cstr_info) { + j2k->cstr_info->main_head_start = cio_tell(j2k->cio) - 2; + j2k->cstr_info->codestream_size = cio_numbytesleft(j2k->cio) + 2 - j2k->cstr_info->main_head_start; + } +} + +static void j2k_write_siz(opj_j2k_t *j2k) { + int i; + int lenp, len; + + opj_cio_t *cio = j2k->cio; + opj_image_t *image = j2k->image; + opj_cp_t *cp = j2k->cp; + + cio_write(cio, J2K_MS_SIZ, 2); /* SIZ */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, cp->rsiz, 2); /* Rsiz (capabilities) */ + cio_write(cio, image->x1, 4); /* Xsiz */ + cio_write(cio, image->y1, 4); /* Ysiz */ + cio_write(cio, image->x0, 4); /* X0siz */ + cio_write(cio, image->y0, 4); /* Y0siz */ + cio_write(cio, cp->tdx, 4); /* XTsiz */ + cio_write(cio, cp->tdy, 4); /* YTsiz */ + cio_write(cio, cp->tx0, 4); /* XT0siz */ + cio_write(cio, cp->ty0, 4); /* YT0siz */ + cio_write(cio, image->numcomps, 2); /* Csiz */ + for (i = 0; i < image->numcomps; i++) { + cio_write(cio, image->comps[i].prec - 1 + (image->comps[i].sgnd << 7), 1); /* Ssiz_i */ + cio_write(cio, image->comps[i].dx, 1); /* XRsiz_i */ + cio_write(cio, image->comps[i].dy, 1); /* YRsiz_i */ + } + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lsiz */ + cio_seek(cio, lenp + len); + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_SIZ, lenp, len); +} + +static void j2k_read_siz(opj_j2k_t *j2k) { + int len, i; + + opj_cio_t *cio = j2k->cio; + opj_image_t *image = j2k->image; + opj_cp_t *cp = j2k->cp; + + len = cio_read(cio, 2); /* Lsiz */ + cio_read(cio, 2); /* Rsiz (capabilities) */ + image->x1 = cio_read(cio, 4); /* Xsiz */ + image->y1 = cio_read(cio, 4); /* Ysiz */ + image->x0 = cio_read(cio, 4); /* X0siz */ + image->y0 = cio_read(cio, 4); /* Y0siz */ + cp->tdx = cio_read(cio, 4); /* XTsiz */ + cp->tdy = cio_read(cio, 4); /* YTsiz */ + cp->tx0 = cio_read(cio, 4); /* XT0siz */ + cp->ty0 = cio_read(cio, 4); /* YT0siz */ + + if ((image->x0<0)||(image->x1<0)||(image->y0<0)||(image->y1<0)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "%s: invalid image size (x0:%d, x1:%d, y0:%d, y1:%d)\n", + image->x0,image->x1,image->y0,image->y1); + return; + } + + image->numcomps = cio_read(cio, 2); /* Csiz */ + +#ifdef USE_JPWL + if (j2k->cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if (!(image->x1 * image->y1)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad image size (%d x %d)\n", + image->x1, image->y1); + if (!JPWL_ASSUME || JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + } + if (image->numcomps != ((len - 38) / 3)) { + opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: Csiz is %d => space in SIZ only for %d comps.!!!\n", + image->numcomps, ((len - 38) / 3)); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n"); + if (image->numcomps < ((len - 38) / 3)) { + len = 38 + 3 * image->numcomps; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting Lsiz to %d => HYPOTHESIS!!!\n", + len); + } else { + image->numcomps = ((len - 38) / 3); + opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting Csiz to %d => HYPOTHESIS!!!\n", + image->numcomps); + } + } + + /* update components number in the jpwl_exp_comps filed */ + cp->exp_comps = image->numcomps; + } +#endif /* USE_JPWL */ + + image->comps = (opj_image_comp_t*) opj_calloc(image->numcomps, sizeof(opj_image_comp_t)); + for (i = 0; i < image->numcomps; i++) { + int tmp, w, h; + tmp = cio_read(cio, 1); /* Ssiz_i */ + image->comps[i].prec = (tmp & 0x7f) + 1; + image->comps[i].sgnd = tmp >> 7; + image->comps[i].dx = cio_read(cio, 1); /* XRsiz_i */ + image->comps[i].dy = cio_read(cio, 1); /* YRsiz_i */ + +#ifdef USE_JPWL + if (j2k->cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters, again */ + if (!(image->comps[i].dx * image->comps[i].dy)) { + opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n", + i, i, image->comps[i].dx, image->comps[i].dy); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust them\n"); + if (!image->comps[i].dx) { + image->comps[i].dx = 1; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n", + i, image->comps[i].dx); + } + if (!image->comps[i].dy) { + image->comps[i].dy = 1; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n", + i, image->comps[i].dy); + } + } + + } +#endif /* USE_JPWL */ + + /* TODO: unused ? */ + w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx); + h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy); + + image->comps[i].resno_decoded = 0; /* number of resolution decoded */ + image->comps[i].factor = cp->reduce; /* reducing factor per component */ + } + + cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx); + cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy); + +#ifdef USE_JPWL + if (j2k->cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if ((cp->tw < 1) || (cp->th < 1) || (cp->tw > cp->max_tiles) || (cp->th > cp->max_tiles)) { + opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of tiles (%d x %d)\n", + cp->tw, cp->th); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust them\n"); + if (cp->tw < 1) { + cp->tw= 1; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting %d tiles in x => HYPOTHESIS!!!\n", + cp->tw); + } + if (cp->tw > cp->max_tiles) { + cp->tw= 1; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- too large x, increase expectance of %d\n" + "- setting %d tiles in x => HYPOTHESIS!!!\n", + cp->max_tiles, cp->tw); + } + if (cp->th < 1) { + cp->th= 1; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting %d tiles in y => HYPOTHESIS!!!\n", + cp->th); + } + if (cp->th > cp->max_tiles) { + cp->th= 1; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- too large y, increase expectance of %d to continue\n", + "- setting %d tiles in y => HYPOTHESIS!!!\n", + cp->max_tiles, cp->th); + } + } + } +#endif /* USE_JPWL */ + + cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); + if (cp->tcps == NULL) + { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n"); + return; + } + cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int)); + if (cp->tileno == NULL) + { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n"); + return; + } + cp->tileno_size = 0; + +#ifdef USE_JPWL + if (j2k->cp->correct) { + if (!cp->tcps) { + opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: could not alloc tcps field of cp\n"); + if (!JPWL_ASSUME || JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + } + } +#endif /* USE_JPWL */ + + for (i = 0; i < cp->tw * cp->th; i++) { + cp->tcps[i].POC = 0; + cp->tcps[i].numpocs = 0; + cp->tcps[i].first = 1; + } + + /* Initialization for PPM marker */ + cp->ppm = 0; + cp->ppm_data = NULL; + cp->ppm_data_first = NULL; + cp->ppm_previous = 0; + cp->ppm_store = 0; + + j2k->default_tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); + for (i = 0; i < cp->tw * cp->th; i++) { + cp->tcps[i].tccps = (opj_tccp_t*) opj_malloc(image->numcomps * sizeof(opj_tccp_t)); + } + j2k->tile_data = (unsigned char**) opj_calloc(cp->tw * cp->th, sizeof(unsigned char*)); + j2k->tile_len = (int*) opj_calloc(cp->tw * cp->th, sizeof(int)); + j2k->state = J2K_STATE_MH; + + /* Index */ + if (j2k->cstr_info) { + opj_codestream_info_t *cstr_info = j2k->cstr_info; + cstr_info->image_w = image->x1 - image->x0; + cstr_info->image_h = image->y1 - image->y0; + cstr_info->numcomps = image->numcomps; + cstr_info->tw = cp->tw; + cstr_info->th = cp->th; + cstr_info->tile_x = cp->tdx; + cstr_info->tile_y = cp->tdy; + cstr_info->tile_Ox = cp->tx0; + cstr_info->tile_Oy = cp->ty0; + cstr_info->tile = (opj_tile_info_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tile_info_t)); + } +} + +static void j2k_write_com(opj_j2k_t *j2k) { + unsigned int i; + int lenp, len; + + if(j2k->cp->comment) { + opj_cio_t *cio = j2k->cio; + char *comment = j2k->cp->comment; + + cio_write(cio, J2K_MS_COM, 2); + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, 1, 2); /* General use (IS 8859-15:1999 (Latin) values) */ + for (i = 0; i < strlen(comment); i++) { + cio_write(cio, comment[i], 1); + } + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); + cio_seek(cio, lenp + len); + + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_COM, lenp, len); + + } +} + +static void j2k_read_com(opj_j2k_t *j2k) { + int len; + + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); + cio_skip(cio, len - 2); +} + +static void j2k_write_cox(opj_j2k_t *j2k, int compno) { + int i; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = &cp->tcps[j2k->curtileno]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j2k->cio; + + cio_write(cio, tccp->numresolutions - 1, 1); /* SPcox (D) */ + cio_write(cio, tccp->cblkw - 2, 1); /* SPcox (E) */ + cio_write(cio, tccp->cblkh - 2, 1); /* SPcox (F) */ + cio_write(cio, tccp->cblksty, 1); /* SPcox (G) */ + cio_write(cio, tccp->qmfbid, 1); /* SPcox (H) */ + + if (tccp->csty & J2K_CCP_CSTY_PRT) { + for (i = 0; i < tccp->numresolutions; i++) { + cio_write(cio, tccp->prcw[i] + (tccp->prch[i] << 4), 1); /* SPcox (I_i) */ + } + } +} + +static void j2k_read_cox(opj_j2k_t *j2k, int compno) { + int i; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j2k->cio; + + tccp->numresolutions = cio_read(cio, 1) + 1; /* SPcox (D) */ + + /* If user wants to remove more resolutions than the codestream contains, return error*/ + if (cp->reduce >= tccp->numresolutions) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions to remove is higher than the number " + "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno); + j2k->state |= J2K_STATE_ERR; + } + if( tccp->numresolutions > J2K_MAXRLVLS ) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions is too big: %d vs max= %d. Truncating.\n\n", + compno, tccp->numresolutions, J2K_MAXRLVLS); + j2k->state |= J2K_STATE_ERR; + tccp->numresolutions = J2K_MAXRLVLS; + } + + tccp->cblkw = cio_read(cio, 1) + 2; /* SPcox (E) */ + tccp->cblkh = cio_read(cio, 1) + 2; /* SPcox (F) */ + tccp->cblksty = cio_read(cio, 1); /* SPcox (G) */ + tccp->qmfbid = cio_read(cio, 1); /* SPcox (H) */ + if (tccp->csty & J2K_CP_CSTY_PRT) { + for (i = 0; i < tccp->numresolutions; i++) { + int tmp = cio_read(cio, 1); /* SPcox (I_i) */ + tccp->prcw[i] = tmp & 0xf; + tccp->prch[i] = tmp >> 4; + } + } + + /* INDEX >> */ + if(j2k->cstr_info && compno == 0) { + for (i = 0; i < tccp->numresolutions; i++) { + if (tccp->csty & J2K_CP_CSTY_PRT) { + j2k->cstr_info->tile[j2k->curtileno].pdx[i] = tccp->prcw[i]; + j2k->cstr_info->tile[j2k->curtileno].pdy[i] = tccp->prch[i]; + } + else { + j2k->cstr_info->tile[j2k->curtileno].pdx[i] = 15; + j2k->cstr_info->tile[j2k->curtileno].pdx[i] = 15; + } + } + } + /* << INDEX */ +} + +static void j2k_write_cod(opj_j2k_t *j2k) { + opj_cp_t *cp = NULL; + opj_tcp_t *tcp = NULL; + int lenp, len; + + opj_cio_t *cio = j2k->cio; + + cio_write(cio, J2K_MS_COD, 2); /* COD */ + + lenp = cio_tell(cio); + cio_skip(cio, 2); + + cp = j2k->cp; + tcp = &cp->tcps[j2k->curtileno]; + + cio_write(cio, tcp->csty, 1); /* Scod */ + cio_write(cio, tcp->prg, 1); /* SGcod (A) */ + cio_write(cio, tcp->numlayers, 2); /* SGcod (B) */ + cio_write(cio, tcp->mct, 1); /* SGcod (C) */ + + j2k_write_cox(j2k, 0); + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lcod */ + cio_seek(cio, lenp + len); + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_COD, lenp, len); + +} + +static void j2k_read_cod(opj_j2k_t *j2k) { + int len, i, pos; + + opj_cio_t *cio = j2k->cio; + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp; + opj_image_t *image = j2k->image; + + len = cio_read(cio, 2); /* Lcod */ + tcp->csty = cio_read(cio, 1); /* Scod */ + tcp->prg = (OPJ_PROG_ORDER)cio_read(cio, 1); /* SGcod (A) */ + tcp->numlayers = cio_read(cio, 2); /* SGcod (B) */ + tcp->mct = cio_read(cio, 1); /* SGcod (C) */ + + pos = cio_tell(cio); + for (i = 0; i < image->numcomps; i++) { + tcp->tccps[i].csty = tcp->csty & J2K_CP_CSTY_PRT; + cio_seek(cio, pos); + j2k_read_cox(j2k, i); + } + + /* Index */ + if (j2k->cstr_info) { + opj_codestream_info_t *cstr_info = j2k->cstr_info; + cstr_info->prog = tcp->prg; + cstr_info->numlayers = tcp->numlayers; + cstr_info->numdecompos = (int*) opj_malloc(image->numcomps * sizeof(int)); + for (i = 0; i < image->numcomps; i++) { + cstr_info->numdecompos[i] = tcp->tccps[i].numresolutions - 1; + } + } +} + +static void j2k_write_coc(opj_j2k_t *j2k, int compno) { + int lenp, len; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = &cp->tcps[j2k->curtileno]; + opj_image_t *image = j2k->image; + opj_cio_t *cio = j2k->cio; + + cio_write(cio, J2K_MS_COC, 2); /* COC */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, compno, image->numcomps <= 256 ? 1 : 2); /* Ccoc */ + cio_write(cio, tcp->tccps[compno].csty, 1); /* Scoc */ + j2k_write_cox(j2k, compno); + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lcoc */ + cio_seek(cio, lenp + len); +} + +static void j2k_read_coc(opj_j2k_t *j2k) { + int len, compno; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp; + opj_image_t *image = j2k->image; + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); /* Lcoc */ + compno = cio_read(cio, image->numcomps <= 256 ? 1 : 2); /* Ccoc */ + tcp->tccps[compno].csty = cio_read(cio, 1); /* Scoc */ + j2k_read_cox(j2k, compno); +} + +static void j2k_write_qcx(opj_j2k_t *j2k, int compno) { + int bandno, numbands; + int expn, mant; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = &cp->tcps[j2k->curtileno]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j2k->cio; + + cio_write(cio, tccp->qntsty + (tccp->numgbits << 5), 1); /* Sqcx */ + numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2; + + for (bandno = 0; bandno < numbands; bandno++) { + expn = tccp->stepsizes[bandno].expn; + mant = tccp->stepsizes[bandno].mant; + + if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + cio_write(cio, expn << 3, 1); /* SPqcx_i */ + } else { + cio_write(cio, (expn << 11) + mant, 2); /* SPqcx_i */ + } + } +} + +static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) { + int tmp; + int bandno, numbands; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j2k->cio; + + tmp = cio_read(cio, 1); /* Sqcx */ + tccp->qntsty = tmp & 0x1f; + tccp->numgbits = tmp >> 5; + numbands = (tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? + 1 : ((tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) ? len - 1 : (len - 1) / 2); + +#ifdef USE_JPWL + if (j2k->cp->correct) { + + /* if JPWL is on, we check whether there are too many subbands */ + if ((numbands < 0) || (numbands >= J2K_MAXBANDS)) { + opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of subbands in Sqcx (%d)\n", + numbands); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + numbands = 1; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust them\n" + "- setting number of bands to %d => HYPOTHESIS!!!\n", + numbands); + }; + + }; + +#else + /* We check whether there are too many subbands */ + if ((numbands < 0) || (numbands >= J2K_MAXBANDS)) { + opj_event_msg(j2k->cinfo, EVT_WARNING , + "bad number of subbands in Sqcx (%d) regarding to J2K_MAXBANDS (%d) \n" + "- limiting number of bands to J2K_MAXBANDS and try to move to the next markers\n", numbands, J2K_MAXBANDS); + } + +#endif /* USE_JPWL */ + + for (bandno = 0; bandno < numbands; bandno++) { + int expn, mant; + if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + expn = cio_read(cio, 1) >> 3; /* SPqcx_i */ + mant = 0; + } else { + tmp = cio_read(cio, 2); /* SPqcx_i */ + expn = tmp >> 11; + mant = tmp & 0x7ff; + } + if (bandno < J2K_MAXBANDS){ + tccp->stepsizes[bandno].expn = expn; + tccp->stepsizes[bandno].mant = mant; + } + } + + /* Add Antonin : if scalar_derived -> compute other stepsizes */ + if (tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) { + for (bandno = 1; bandno < J2K_MAXBANDS; bandno++) { + tccp->stepsizes[bandno].expn = + ((tccp->stepsizes[0].expn) - ((bandno - 1) / 3) > 0) ? + (tccp->stepsizes[0].expn) - ((bandno - 1) / 3) : 0; + tccp->stepsizes[bandno].mant = tccp->stepsizes[0].mant; + } + } + /* ddA */ +} + +static void j2k_write_qcd(opj_j2k_t *j2k) { + int lenp, len; + + opj_cio_t *cio = j2k->cio; + + cio_write(cio, J2K_MS_QCD, 2); /* QCD */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + j2k_write_qcx(j2k, 0); + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lqcd */ + cio_seek(cio, lenp + len); + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_QCD, lenp, len); +} + +static void j2k_read_qcd(opj_j2k_t *j2k) { + int len, i, pos; + + opj_cio_t *cio = j2k->cio; + opj_image_t *image = j2k->image; + + len = cio_read(cio, 2); /* Lqcd */ + pos = cio_tell(cio); + for (i = 0; i < image->numcomps; i++) { + cio_seek(cio, pos); + j2k_read_qcx(j2k, i, len - 2); + } +} + +static void j2k_write_qcc(opj_j2k_t *j2k, int compno) { + int lenp, len; + + opj_cio_t *cio = j2k->cio; + + cio_write(cio, J2K_MS_QCC, 2); /* QCC */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, compno, j2k->image->numcomps <= 256 ? 1 : 2); /* Cqcc */ + j2k_write_qcx(j2k, compno); + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lqcc */ + cio_seek(cio, lenp + len); +} + +static void j2k_read_qcc(opj_j2k_t *j2k) { + int len, compno; + int numcomp = j2k->image->numcomps; + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); /* Lqcc */ + compno = cio_read(cio, numcomp <= 256 ? 1 : 2); /* Cqcc */ + +#ifdef USE_JPWL + if (j2k->cp->correct) { + + static int backup_compno = 0; + + /* compno is negative or larger than the number of components!!! */ + if ((compno < 0) || (compno >= numcomp)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad component number in QCC (%d out of a maximum of %d)\n", + compno, numcomp); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + compno = backup_compno % numcomp; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" + "- setting component number to %d\n", + compno); + } + + /* keep your private count of tiles */ + backup_compno++; + }; +#endif /* USE_JPWL */ + + j2k_read_qcx(j2k, compno, len - 2 - (numcomp <= 256 ? 1 : 2)); +} + +static void j2k_write_poc(opj_j2k_t *j2k) { + int len, numpchgs, i; + + int numcomps = j2k->image->numcomps; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = &cp->tcps[j2k->curtileno]; + opj_tccp_t *tccp = &tcp->tccps[0]; + opj_cio_t *cio = j2k->cio; + + numpchgs = 1 + tcp->numpocs; + cio_write(cio, J2K_MS_POC, 2); /* POC */ + len = 2 + (5 + 2 * (numcomps <= 256 ? 1 : 2)) * numpchgs; + cio_write(cio, len, 2); /* Lpoc */ + for (i = 0; i < numpchgs; i++) { + opj_poc_t *poc = &tcp->pocs[i]; + cio_write(cio, poc->resno0, 1); /* RSpoc_i */ + cio_write(cio, poc->compno0, (numcomps <= 256 ? 1 : 2)); /* CSpoc_i */ + cio_write(cio, poc->layno1, 2); /* LYEpoc_i */ + poc->layno1 = int_min(poc->layno1, tcp->numlayers); + cio_write(cio, poc->resno1, 1); /* REpoc_i */ + poc->resno1 = int_min(poc->resno1, tccp->numresolutions); + cio_write(cio, poc->compno1, (numcomps <= 256 ? 1 : 2)); /* CEpoc_i */ + poc->compno1 = int_min(poc->compno1, numcomps); + cio_write(cio, poc->prg, 1); /* Ppoc_i */ + } +} + +static void j2k_read_poc(opj_j2k_t *j2k) { + int len, numpchgs, i, old_poc; + + int numcomps = j2k->image->numcomps; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp; + opj_cio_t *cio = j2k->cio; + + old_poc = tcp->POC ? tcp->numpocs + 1 : 0; + tcp->POC = 1; + len = cio_read(cio, 2); /* Lpoc */ + numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2)); + + for (i = old_poc; i < numpchgs + old_poc; i++) { + opj_poc_t *poc; + poc = &tcp->pocs[i]; + poc->resno0 = cio_read(cio, 1); /* RSpoc_i */ + poc->compno0 = cio_read(cio, numcomps <= 256 ? 1 : 2); /* CSpoc_i */ + poc->layno1 = cio_read(cio, 2); /* LYEpoc_i */ + poc->resno1 = cio_read(cio, 1); /* REpoc_i */ + poc->compno1 = int_min( + cio_read(cio, numcomps <= 256 ? 1 : 2), (unsigned int) numcomps); /* CEpoc_i */ + poc->prg = (OPJ_PROG_ORDER)cio_read(cio, 1); /* Ppoc_i */ + } + + tcp->numpocs = numpchgs + old_poc - 1; +} + +static void j2k_read_crg(opj_j2k_t *j2k) { + int len, i, Xcrg_i, Ycrg_i; + + opj_cio_t *cio = j2k->cio; + int numcomps = j2k->image->numcomps; + + len = cio_read(cio, 2); /* Lcrg */ + for (i = 0; i < numcomps; i++) { + Xcrg_i = cio_read(cio, 2); /* Xcrg_i */ + Ycrg_i = cio_read(cio, 2); /* Ycrg_i */ + } +} + +static void j2k_read_tlm(opj_j2k_t *j2k) { + int len, Ztlm, Stlm, ST, SP, tile_tlm, i; + long int Ttlm_i, Ptlm_i; + + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); /* Ltlm */ + Ztlm = cio_read(cio, 1); /* Ztlm */ + Stlm = cio_read(cio, 1); /* Stlm */ + ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02); + SP = (Stlm >> 6) & 0x01; + tile_tlm = (len - 4) / ((SP + 1) * 2 + ST); + for (i = 0; i < tile_tlm; i++) { + Ttlm_i = cio_read(cio, ST); /* Ttlm_i */ + Ptlm_i = cio_read(cio, SP ? 4 : 2); /* Ptlm_i */ + } +} + +static void j2k_read_plm(opj_j2k_t *j2k) { + int len, i, Zplm, Nplm, add, packet_len = 0; + + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); /* Lplm */ + Zplm = cio_read(cio, 1); /* Zplm */ + len -= 3; + while (len > 0) { + Nplm = cio_read(cio, 4); /* Nplm */ + len -= 4; + for (i = Nplm; i > 0; i--) { + add = cio_read(cio, 1); + len--; + packet_len = (packet_len << 7) + add; /* Iplm_ij */ + if ((add & 0x80) == 0) { + /* New packet */ + packet_len = 0; + } + if (len <= 0) + break; + } + } +} + +static void j2k_read_plt(opj_j2k_t *j2k) { + int len, i, Zplt, packet_len = 0, add; + + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); /* Lplt */ + Zplt = cio_read(cio, 1); /* Zplt */ + for (i = len - 3; i > 0; i--) { + add = cio_read(cio, 1); + packet_len = (packet_len << 7) + add; /* Iplt_i */ + if ((add & 0x80) == 0) { + /* New packet */ + packet_len = 0; + } + } +} + +static void j2k_read_ppm(opj_j2k_t *j2k) { + int len, Z_ppm, i, j; + int N_ppm; + + opj_cp_t *cp = j2k->cp; + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); + cp->ppm = 1; + + Z_ppm = cio_read(cio, 1); /* Z_ppm */ + len -= 3; + while (len > 0) { + if (cp->ppm_previous == 0) { + N_ppm = cio_read(cio, 4); /* N_ppm */ + len -= 4; + } else { + N_ppm = cp->ppm_previous; + } + j = cp->ppm_store; + if (Z_ppm == 0) { /* First PPM marker */ + cp->ppm_data = (unsigned char *) opj_malloc(N_ppm * sizeof(unsigned char)); + cp->ppm_data_first = cp->ppm_data; + cp->ppm_len = N_ppm; + } else { /* NON-first PPM marker */ + cp->ppm_data = (unsigned char *) opj_realloc(cp->ppm_data, (N_ppm + cp->ppm_store) * sizeof(unsigned char)); + +#ifdef USE_JPWL + /* this memory allocation check could be done even in non-JPWL cases */ + if (cp->correct) { + if (!cp->ppm_data) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: failed memory allocation during PPM marker parsing (pos. %x)\n", + cio_tell(cio)); + if (!JPWL_ASSUME || JPWL_ASSUME) { + opj_free(cp->ppm_data); + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + } + } +#endif + + cp->ppm_data_first = cp->ppm_data; + cp->ppm_len = N_ppm + cp->ppm_store; + } + for (i = N_ppm; i > 0; i--) { /* Read packet header */ + cp->ppm_data[j] = cio_read(cio, 1); + j++; + len--; + if (len == 0) + break; /* Case of non-finished packet header in present marker but finished in next one */ + } + cp->ppm_previous = i - 1; + cp->ppm_store = j; + } +} + +static void j2k_read_ppt(opj_j2k_t *j2k) { + int len, Z_ppt, i, j = 0; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = cp->tcps + j2k->curtileno; + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); + Z_ppt = cio_read(cio, 1); + tcp->ppt = 1; + if (Z_ppt == 0) { /* First PPT marker */ + tcp->ppt_data = (unsigned char *) opj_malloc((len - 3) * sizeof(unsigned char)); + tcp->ppt_data_first = tcp->ppt_data; + tcp->ppt_store = 0; + tcp->ppt_len = len - 3; + } else { /* NON-first PPT marker */ + tcp->ppt_data = (unsigned char *) opj_realloc(tcp->ppt_data, (len - 3 + tcp->ppt_store) * sizeof(unsigned char)); + tcp->ppt_data_first = tcp->ppt_data; + tcp->ppt_len = len - 3 + tcp->ppt_store; + } + j = tcp->ppt_store; + for (i = len - 3; i > 0; i--) { + tcp->ppt_data[j] = cio_read(cio, 1); + j++; + } + tcp->ppt_store = j; +} + +static void j2k_write_tlm(opj_j2k_t *j2k){ + int lenp; + opj_cio_t *cio = j2k->cio; + j2k->tlm_start = cio_tell(cio); + cio_write(cio, J2K_MS_TLM, 2);/* TLM */ + lenp = 4 + (5*j2k->totnum_tp); + cio_write(cio,lenp,2); /* Ltlm */ + cio_write(cio, 0,1); /* Ztlm=0*/ + cio_write(cio,80,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ + cio_skip(cio,5*j2k->totnum_tp); +} + +static void j2k_write_sot(opj_j2k_t *j2k) { + int lenp, len; + + opj_cio_t *cio = j2k->cio; + + j2k->sot_start = cio_tell(cio); + cio_write(cio, J2K_MS_SOT, 2); /* SOT */ + lenp = cio_tell(cio); + cio_skip(cio, 2); /* Lsot (further) */ + cio_write(cio, j2k->curtileno, 2); /* Isot */ + cio_skip(cio, 4); /* Psot (further in j2k_write_sod) */ + cio_write(cio, j2k->cur_tp_num , 1); /* TPsot */ + cio_write(cio, j2k->cur_totnum_tp[j2k->curtileno], 1); /* TNsot */ + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lsot */ + cio_seek(cio, lenp + len); + + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + j2k_add_marker(j2k->cstr_info, J2K_MS_SOT, j2k->sot_start, len + 2); +#endif /* USE_JPWL */ + /* <cstr_info && j2k->cur_tp_num==0){ + j2k_add_tlmarker( j2k->curtileno, j2k->cstr_info, J2K_MS_SOT, lenp, len); + } +} + +static void j2k_read_sot(opj_j2k_t *j2k) { + int len, tileno, totlen, partno, numparts, i; + opj_tcp_t *tcp = NULL; + char status = 0; + + opj_cp_t *cp = j2k->cp; + opj_cio_t *cio = j2k->cio; + + len = cio_read(cio, 2); + tileno = cio_read(cio, 2); + +#ifdef USE_JPWL + if (j2k->cp->correct) { + + static int backup_tileno = 0; + + /* tileno is negative or larger than the number of tiles!!! */ + if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile number (%d out of a maximum of %d)\n", + tileno, (cp->tw * cp->th)); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + tileno = backup_tileno; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" + "- setting tile number to %d\n", + tileno); + } + + /* keep your private count of tiles */ + backup_tileno++; + } + else +#endif /* USE_JPWL */ + { + /* tileno is negative or larger than the number of tiles!!! */ + if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile number (%d out of a maximum of %d)\n", + tileno, (cp->tw * cp->th)); + return; + } + } + + if (cp->tileno_size == 0) { + cp->tileno[cp->tileno_size] = tileno; + cp->tileno_size++; + } else { + i = 0; + while (i < cp->tileno_size && status == 0) { + status = cp->tileno[i] == tileno ? 1 : 0; + i++; + } + if (status == 0) { + cp->tileno[cp->tileno_size] = tileno; + cp->tileno_size++; + } + } + + totlen = cio_read(cio, 4); + +#ifdef USE_JPWL + if (j2k->cp->correct) { + + /* totlen is negative or larger than the bytes left!!! */ + if ((totlen < 0) || (totlen > (cio_numbytesleft(cio) + 8))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", + totlen, cio_numbytesleft(cio) + 8); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + totlen = 0; + opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" + "- setting Psot to %d => assuming it is the last tile\n", + totlen); + } + + } + else +#endif /* USE_JPWL */ + { + /* totlen is negative or larger than the bytes left!!! */ + if ((totlen < 0) || (totlen > (cio_numbytesleft(cio) + 8))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", + totlen, cio_numbytesleft(cio) + 8); + return; + } + } + + if (!totlen) + totlen = cio_numbytesleft(cio) + 8; + + partno = cio_read(cio, 1); + numparts = cio_read(cio, 1); + + if (partno >= numparts) { + opj_event_msg(j2k->cinfo, EVT_WARNING, "SOT marker inconsistency in tile %d: tile-part index greater (%d) than number of tile-parts (%d)\n", tileno, partno, numparts); + numparts = partno+1; + } + + j2k->curtileno = tileno; + j2k->cur_tp_num = partno; + j2k->eot = cio_getbp(cio) - 12 + totlen; + j2k->state = J2K_STATE_TPH; + tcp = &cp->tcps[j2k->curtileno]; + + /* Index */ + if (j2k->cstr_info) { + if (tcp->first) { + if (tileno == 0) + j2k->cstr_info->main_head_end = cio_tell(cio) - 13; + j2k->cstr_info->tile[tileno].tileno = tileno; + j2k->cstr_info->tile[tileno].start_pos = cio_tell(cio) - 12; + j2k->cstr_info->tile[tileno].end_pos = j2k->cstr_info->tile[tileno].start_pos + totlen - 1; + } else { + j2k->cstr_info->tile[tileno].end_pos += totlen; + } + j2k->cstr_info->tile[tileno].num_tps = numparts; + if (numparts) + j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_realloc(j2k->cstr_info->tile[tileno].tp, numparts * sizeof(opj_tp_info_t)); + else + j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_realloc(j2k->cstr_info->tile[tileno].tp, 10 * sizeof(opj_tp_info_t)); /* Fixme (10)*/ + j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = cio_tell(cio) - 12; + j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = + j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; + } + + if (tcp->first == 1) { + /* Initialization PPT */ + opj_tccp_t *tmp = tcp->tccps; + memcpy(tcp, j2k->default_tcp, sizeof(opj_tcp_t)); + tcp->ppt = 0; + tcp->ppt_data = NULL; + tcp->ppt_data_first = NULL; + tcp->tccps = tmp; + + for (i = 0; i < j2k->image->numcomps; i++) { + tcp->tccps[i] = j2k->default_tcp->tccps[i]; + } + cp->tcps[j2k->curtileno].first = 0; + } +} + +static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder) { + int l, layno; + int totlen; + opj_tcp_t *tcp = NULL; + opj_codestream_info_t *cstr_info = NULL; + + opj_tcd_t *tcd = (opj_tcd_t*)tile_coder; /* cast is needed because of conflicts in header inclusions */ + opj_cp_t *cp = j2k->cp; + opj_cio_t *cio = j2k->cio; + + tcd->tp_num = j2k->tp_num ; + tcd->cur_tp_num = j2k->cur_tp_num; + + cio_write(cio, J2K_MS_SOD, 2); + + if( j2k->cstr_info && j2k->cur_tp_num==0){ + j2k_add_tlmarker( j2k->curtileno, j2k->cstr_info, J2K_MS_SOD, cio_tell(cio), 0); + } + + if (j2k->curtileno == 0) { + j2k->sod_start = cio_tell(cio) + j2k->pos_correction; + } + + /* INDEX >> */ + cstr_info = j2k->cstr_info; + if (cstr_info) { + if (!j2k->cur_tp_num ) { + cstr_info->tile[j2k->curtileno].end_header = cio_tell(cio) + j2k->pos_correction - 1; + j2k->cstr_info->tile[j2k->curtileno].tileno = j2k->curtileno; + } + else{ + if(cstr_info->tile[j2k->curtileno].packet[cstr_info->packno - 1].end_pos < cio_tell(cio)) + cstr_info->tile[j2k->curtileno].packet[cstr_info->packno].start_pos = cio_tell(cio); + } + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + j2k_add_marker(j2k->cstr_info, J2K_MS_SOD, j2k->sod_start, 2); +#endif /* USE_JPWL */ + /* <tcps[j2k->curtileno]; + for (layno = 0; layno < tcp->numlayers; layno++) { + if (tcp->rates[layno]>(j2k->sod_start / (cp->th * cp->tw))) { + tcp->rates[layno]-=(j2k->sod_start / (cp->th * cp->tw)); + } else if (tcp->rates[layno]) { + tcp->rates[layno]=1; + } + } + if(j2k->cur_tp_num == 0){ + tcd->tcd_image->tiles->packno = 0; + if(cstr_info) + cstr_info->packno = 0; + } + + l = tcd_encode_tile(tcd, j2k->curtileno, cio_getbp(cio), cio_numbytesleft(cio) - 2, cstr_info); + + /* Writing Psot in SOT marker */ + totlen = cio_tell(cio) + l - j2k->sot_start; + cio_seek(cio, j2k->sot_start + 6); + cio_write(cio, totlen, 4); + cio_seek(cio, j2k->sot_start + totlen); + /* Writing Ttlm and Ptlm in TLM marker */ + if(cp->cinema){ + cio_seek(cio, j2k->tlm_start + 6 + (5*j2k->cur_tp_num)); + cio_write(cio, j2k->curtileno, 1); + cio_write(cio, totlen, 4); + } + cio_seek(cio, j2k->sot_start + totlen); +} + +static void j2k_read_sod(opj_j2k_t *j2k) { + int len, truncate = 0, i; + unsigned char *data = NULL, *data_ptr = NULL; + + opj_cio_t *cio = j2k->cio; + int curtileno = j2k->curtileno; + + /* Index */ + if (j2k->cstr_info) { + j2k->cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_header = + cio_tell(cio) + j2k->pos_correction - 1; + if (j2k->cur_tp_num == 0) + j2k->cstr_info->tile[j2k->curtileno].end_header = cio_tell(cio) + j2k->pos_correction - 1; + j2k->cstr_info->packno = 0; + } + + len = int_min(j2k->eot - cio_getbp(cio), cio_numbytesleft(cio) + 1); + + if (len == cio_numbytesleft(cio) + 1) { + truncate = 1; /* Case of a truncate codestream */ + } + + {/* chop padding bytes: */ + unsigned char *s, *e; + + s = cio_getbp(cio); + e = s + len; + + if(len > 8) s = e - 8; + + if(e[-2] == 0x00 && e[-1] == 0x00) /* padding bytes */ + { + while(e > s) + { + if(e[-2] == 0xff && e[-1] == 0xd9) break; + --len; --e; truncate = 1; + } + } + } + + data = j2k->tile_data[curtileno]; + data = (unsigned char*) opj_realloc(data, (j2k->tile_len[curtileno] + len) * sizeof(unsigned char)); + + data_ptr = data + j2k->tile_len[curtileno]; + for (i = 0; i < len; i++) { + data_ptr[i] = cio_read(cio, 1); + } + + j2k->tile_len[curtileno] += len; + j2k->tile_data[curtileno] = data; + + if (!truncate) { + j2k->state = J2K_STATE_TPHSOT; + } else { + j2k->state = J2K_STATE_NEOC; /* RAJOUTE !! */ + } + j2k->cur_tp_num++; +} + +static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno) { + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = &cp->tcps[tileno]; + opj_cio_t *cio = j2k->cio; + int numcomps = j2k->image->numcomps; + + cio_write(cio, J2K_MS_RGN, 2); /* RGN */ + cio_write(cio, numcomps <= 256 ? 5 : 6, 2); /* Lrgn */ + cio_write(cio, compno, numcomps <= 256 ? 1 : 2); /* Crgn */ + cio_write(cio, 0, 1); /* Srgn */ + cio_write(cio, tcp->tccps[compno].roishift, 1); /* SPrgn */ +} + +static void j2k_read_rgn(opj_j2k_t *j2k) { + int len, compno, roisty; + + opj_cp_t *cp = j2k->cp; + opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp; + opj_cio_t *cio = j2k->cio; + int numcomps = j2k->image->numcomps; + + len = cio_read(cio, 2); /* Lrgn */ + compno = cio_read(cio, numcomps <= 256 ? 1 : 2); /* Crgn */ + roisty = cio_read(cio, 1); /* Srgn */ + +#ifdef USE_JPWL + if (j2k->cp->correct) { + /* totlen is negative or larger than the bytes left!!! */ + if (compno >= numcomps) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad component number in RGN (%d when there are only %d)\n", + compno, numcomps); + if (!JPWL_ASSUME || JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + } + }; +#endif /* USE_JPWL */ + + tcp->tccps[compno].roishift = cio_read(cio, 1); /* SPrgn */ +} + +static void j2k_write_eoc(opj_j2k_t *j2k) { + opj_cio_t *cio = j2k->cio; + /* opj_event_msg(j2k->cinfo, "%.8x: EOC\n", cio_tell(cio) + j2k->pos_correction); */ + cio_write(cio, J2K_MS_EOC, 2); + +/* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + j2k_add_marker(j2k->cstr_info, J2K_MS_EOC, cio_tell(cio) - 2, 2); +#endif /* USE_JPWL */ +/* <cp->limit_decoding != DECODE_ALL_BUT_PACKETS) { + opj_tcd_t *tcd = tcd_create(j2k->cinfo); + tcd_malloc_decode(tcd, j2k->image, j2k->cp); + for (i = 0; i < j2k->cp->tileno_size; i++) { + tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info); + if (j2k->cp->tileno[i] != -1) + { + tileno = j2k->cp->tileno[i]; + success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info); + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + tcd_free_decode_tile(tcd, i); + } + else + success = OPJ_FALSE; + if (success == OPJ_FALSE) { + j2k->state |= J2K_STATE_ERR; + break; + } + } + tcd_free_decode(tcd); + tcd_destroy(tcd); + } + /* if packets should not be decoded */ + else { + for (i = 0; i < j2k->cp->tileno_size; i++) { + tileno = j2k->cp->tileno[i]; + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + } + } + if (j2k->state & J2K_STATE_ERR) + j2k->state = J2K_STATE_MT + J2K_STATE_ERR; + else + j2k->state = J2K_STATE_MT; +} + +typedef struct opj_dec_mstabent { + /** marker value */ + int id; + /** value of the state when the marker can appear */ + int states; + /** action linked to the marker */ + void (*handler) (opj_j2k_t *j2k); +} opj_dec_mstabent_t; + +opj_dec_mstabent_t j2k_dec_mstab[] = { + {J2K_MS_SOC, J2K_STATE_MHSOC, j2k_read_soc}, + {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, j2k_read_sot}, + {J2K_MS_SOD, J2K_STATE_TPH, j2k_read_sod}, + {J2K_MS_EOC, J2K_STATE_TPHSOT, j2k_read_eoc}, + {J2K_MS_SIZ, J2K_STATE_MHSIZ, j2k_read_siz}, + {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_cod}, + {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_coc}, + {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_rgn}, + {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcd}, + {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcc}, + {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_poc}, + {J2K_MS_TLM, J2K_STATE_MH, j2k_read_tlm}, + {J2K_MS_PLM, J2K_STATE_MH, j2k_read_plm}, + {J2K_MS_PLT, J2K_STATE_TPH, j2k_read_plt}, + {J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm}, + {J2K_MS_PPT, J2K_STATE_TPH, j2k_read_ppt}, + {J2K_MS_SOP, 0, 0}, + {J2K_MS_CRG, J2K_STATE_MH, j2k_read_crg}, + {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_com}, + +#ifdef USE_JPWL + {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc}, + {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb}, + {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd}, + {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red}, +#endif /* USE_JPWL */ +#ifdef USE_JPSEC + {J2K_MS_SEC, J2K_STATE_MH, j2k_read_sec}, + {J2K_MS_INSEC, 0, j2k_read_insec}, +#endif /* USE_JPSEC */ + + {0, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_unk} +}; + +static void j2k_read_unk(opj_j2k_t *j2k) { + opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown marker\n"); + +#ifdef USE_JPWL + if (j2k->cp->correct) { + int m = 0, id, i; + int min_id = 0, min_dist = 17, cur_dist = 0, tmp_id; + cio_seek(j2k->cio, cio_tell(j2k->cio) - 2); + id = cio_read(j2k->cio, 2); + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: really don't know this marker %x\n", + id); + if (!JPWL_ASSUME) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "- possible synch loss due to uncorrectable codestream errors => giving up\n"); + return; + } + /* OK, activate this at your own risk!!! */ + /* we look for the marker at the minimum hamming distance from this */ + while (j2k_dec_mstab[m].id) { + + /* 1's where they differ */ + tmp_id = j2k_dec_mstab[m].id ^ id; + + /* compute the hamming distance between our id and the current */ + cur_dist = 0; + for (i = 0; i < 16; i++) { + if ((tmp_id >> i) & 0x0001) { + cur_dist++; + } + } + + /* if current distance is smaller, set the minimum */ + if (cur_dist < min_dist) { + min_dist = cur_dist; + min_id = j2k_dec_mstab[m].id; + } + + /* jump to the next marker */ + m++; + } + + /* do we substitute the marker? */ + if (min_dist < JPWL_MAXIMUM_HAMMING) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "- marker %x is at distance %d from the read %x\n", + min_id, min_dist, id); + opj_event_msg(j2k->cinfo, EVT_ERROR, + "- trying to substitute in place and crossing fingers!\n"); + cio_seek(j2k->cio, cio_tell(j2k->cio) - 2); + cio_write(j2k->cio, min_id, 2); + + /* rewind */ + cio_seek(j2k->cio, cio_tell(j2k->cio) - 2); + + } + + }; +#endif /* USE_JPWL */ + +} + +/** +Read the lookup table containing all the marker, status and action +@param id Marker value +*/ +static opj_dec_mstabent_t *j2k_dec_mstab_lookup(int id) { + opj_dec_mstabent_t *e; + for (e = j2k_dec_mstab; e->id != 0; e++) { + if (e->id == id) { + break; + } + } + return e; +} + +/* ----------------------------------------------------------------------- */ +/* J2K / JPT decoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_j2k_t* j2k_create_decompress(opj_common_ptr cinfo) { + opj_j2k_t *j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t)); + if(!j2k) + return NULL; + + j2k->default_tcp = (opj_tcp_t*) opj_calloc(1, sizeof(opj_tcp_t)); + if(!j2k->default_tcp) { + opj_free(j2k); + return NULL; + } + + j2k->cinfo = cinfo; + j2k->tile_data = NULL; + + return j2k; +} + +void j2k_destroy_decompress(opj_j2k_t *j2k) { + int i = 0; + + if(j2k->tile_len != NULL) { + opj_free(j2k->tile_len); + } + if(j2k->tile_data != NULL) { + if(j2k->cp != NULL) { + for (i = 0; i < j2k->cp->tileno_size; i++) { + int tileno = j2k->cp->tileno[i]; + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + } + } + + opj_free(j2k->tile_data); + } + if(j2k->default_tcp != NULL) { + opj_tcp_t *default_tcp = j2k->default_tcp; + if(default_tcp->ppt_data_first != NULL) { + opj_free(default_tcp->ppt_data_first); + } + if(j2k->default_tcp->tccps != NULL) { + opj_free(j2k->default_tcp->tccps); + } + opj_free(j2k->default_tcp); + } + if(j2k->cp != NULL) { + opj_cp_t *cp = j2k->cp; + if(cp->tcps != NULL) { + for(i = 0; i < cp->tw * cp->th; i++) { + if(cp->tcps[i].ppt_data_first != NULL) { + opj_free(cp->tcps[i].ppt_data_first); + } + if(cp->tcps[i].tccps != NULL) { + opj_free(cp->tcps[i].tccps); + } + } + opj_free(cp->tcps); + } + if(cp->ppm_data_first != NULL) { + opj_free(cp->ppm_data_first); + } + if(cp->tileno != NULL) { + opj_free(cp->tileno); + } + if(cp->comment != NULL) { + opj_free(cp->comment); + } + + opj_free(cp); + } + opj_free(j2k); +} + +void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) { + if(j2k && parameters) { + /* create and initialize the coding parameters structure */ + opj_cp_t *cp = (opj_cp_t*) opj_calloc(1, sizeof(opj_cp_t)); + cp->reduce = parameters->cp_reduce; + cp->layer = parameters->cp_layer; + cp->limit_decoding = parameters->cp_limit_decoding; + +#ifdef USE_JPWL + cp->correct = parameters->jpwl_correct; + cp->exp_comps = parameters->jpwl_exp_comps; + cp->max_tiles = parameters->jpwl_max_tiles; +#endif /* USE_JPWL */ + + + /* keep a link to cp so that we can destroy it later in j2k_destroy_decompress */ + j2k->cp = cp; + } +} + +opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info) { + opj_image_t *image = NULL; + + opj_common_ptr cinfo = j2k->cinfo; + + j2k->cio = cio; + j2k->cstr_info = cstr_info; + if (cstr_info) + memset(cstr_info, 0, sizeof(opj_codestream_info_t)); + + /* create an empty image */ + image = opj_image_create0(); + j2k->image = image; + + j2k->state = J2K_STATE_MHSOC; + + for (;;) { + opj_dec_mstabent_t *e; + int id = cio_read(cio, 2); + +#ifdef USE_JPWL + /* we try to honor JPWL correction power */ + if (j2k->cp->correct) { + + int orig_pos = cio_tell(cio); + opj_bool status; + + /* call the corrector */ + status = jpwl_correct(j2k); + + /* go back to where you were */ + cio_seek(cio, orig_pos - 2); + + /* re-read the marker */ + id = cio_read(cio, 2); + + /* check whether it begins with ff */ + if (id >> 8 != 0xff) { + opj_event_msg(cinfo, EVT_ERROR, + "JPWL: possible bad marker %x at %d\n", + id, cio_tell(cio) - 2); + if (!JPWL_ASSUME) { + opj_image_destroy(image); + opj_event_msg(cinfo, EVT_ERROR, "JPWL: giving up\n"); + return 0; + } + /* we try to correct */ + id = id | 0xff00; + cio_seek(cio, cio_tell(cio) - 2); + cio_write(cio, id, 2); + opj_event_msg(cinfo, EVT_WARNING, "- trying to adjust this\n" + "- setting marker to %x\n", + id); + } + + } +#endif /* USE_JPWL */ + + if (id >> 8 != 0xff) { + if(cio_numbytesleft(cio) != 0) /* not end of file reached and no EOC */ + { + opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + opj_image_destroy(image); + return 0; + } + opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + j2k->state = J2K_STATE_NEOC; + break; + } + e = j2k_dec_mstab_lookup(id); + /* Check if the marker is known*/ + if (!(j2k->state & e->states)) { + opj_image_destroy(image); + opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id); + return 0; + } + /* Check if the decoding is limited to the main header*/ + if (e->id == J2K_MS_SOT && j2k->cp->limit_decoding == LIMIT_TO_MAIN_HEADER) { + opj_event_msg(cinfo, EVT_INFO, "Main Header decoded.\n"); + return image; + } + + if (e->handler) { + (*e->handler)(j2k); + } + if (j2k->state & J2K_STATE_ERR) + { + opj_image_destroy(image); + return NULL; + } + + if (j2k->state == J2K_STATE_MT) { + break; + } + if (j2k->state == J2K_STATE_NEOC) { + break; + } + } + if (j2k->state == J2K_STATE_NEOC) { + j2k_read_eoc(j2k); + } + + if (j2k->state != J2K_STATE_MT) { + opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n"); + } + return image; +} + +/* +* Read a JPT-stream and decode file +* +*/ +opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info) { + opj_image_t *image = NULL; + opj_jpt_msg_header_t header; + int position; + opj_common_ptr cinfo = j2k->cinfo; + + OPJ_ARG_NOT_USED(cstr_info); + + j2k->cio = cio; + + /* create an empty image */ + image = opj_image_create0(); + j2k->image = image; + + j2k->state = J2K_STATE_MHSOC; + + /* Initialize the header */ + jpt_init_msg_header(&header); + /* Read the first header of the message */ + jpt_read_msg_header(cinfo, cio, &header); + + position = cio_tell(cio); + if (header.Class_Id != 6) { /* 6 : Main header data-bin message */ + opj_image_destroy(image); + opj_event_msg(cinfo, EVT_ERROR, "[JPT-stream] : Expecting Main header first [class_Id %d] !\n", header.Class_Id); + return 0; + } + + for (;;) { + opj_dec_mstabent_t *e = NULL; + int id; + + if (!cio_numbytesleft(cio)) { + j2k_read_eoc(j2k); + return image; + } + /* data-bin read -> need to read a new header */ + if ((unsigned int) (cio_tell(cio) - position) == header.Msg_length) { + jpt_read_msg_header(cinfo, cio, &header); + position = cio_tell(cio); + if (header.Class_Id != 4) { /* 4 : Tile data-bin message */ + opj_image_destroy(image); + opj_event_msg(cinfo, EVT_ERROR, "[JPT-stream] : Expecting Tile info !\n"); + return 0; + } + } + + id = cio_read(cio, 2); + if (id >> 8 != 0xff) { + if(cio_numbytesleft(cio) != 0) /* no end of file reached and no EOC */ + { + opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + opj_image_destroy(image); + return 0; + } + opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + j2k->state = J2K_STATE_NEOC; + break; + } + e = j2k_dec_mstab_lookup(id); + if (!(j2k->state & e->states)) { + opj_image_destroy(image); + opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id); + return 0; + } + if (e->handler) { + (*e->handler)(j2k); + } + if (j2k->state == J2K_STATE_MT) { + break; + } + if (j2k->state == J2K_STATE_NEOC) { + break; + } + } + if (j2k->state == J2K_STATE_NEOC) { + j2k_read_eoc(j2k); + } + + if (j2k->state != J2K_STATE_MT) { + opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n"); + } + + return image; +} + +/* ----------------------------------------------------------------------- */ +/* J2K encoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_j2k_t* j2k_create_compress(opj_common_ptr cinfo) { + opj_j2k_t *j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t)); + if(j2k) { + j2k->cinfo = cinfo; + } + return j2k; +} + +void j2k_destroy_compress(opj_j2k_t *j2k) { + int tileno; + + if(!j2k) return; + if(j2k->cp != NULL) { + opj_cp_t *cp = j2k->cp; + + if(cp->comment) { + opj_free(cp->comment); + } + if(cp->matrice) { + opj_free(cp->matrice); + } + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_free(cp->tcps[tileno].tccps); + } + opj_free(cp->tcps); + opj_free(cp); + } + + opj_free(j2k); +} + +void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image) { + int i, j, tileno, numpocs_tile; + opj_cp_t *cp = NULL; + + if(!j2k || !parameters || ! image) { + return; + } + + /* create and initialize the coding parameters structure */ + cp = (opj_cp_t*) opj_calloc(1, sizeof(opj_cp_t)); + + /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */ + j2k->cp = cp; + + /* set default values for cp */ + cp->tw = 1; + cp->th = 1; + + /* + copy user encoding parameters + */ + cp->cinema = parameters->cp_cinema; + cp->max_comp_size = parameters->max_comp_size; + cp->rsiz = parameters->cp_rsiz; + cp->disto_alloc = parameters->cp_disto_alloc; + cp->fixed_alloc = parameters->cp_fixed_alloc; + cp->fixed_quality = parameters->cp_fixed_quality; + + /* mod fixed_quality */ + if(parameters->cp_matrice) { + size_t array_size = parameters->tcp_numlayers * parameters->numresolution * 3 * sizeof(int); + cp->matrice = (int *) opj_malloc(array_size); + memcpy(cp->matrice, parameters->cp_matrice, array_size); + } + + /* tiles */ + cp->tdx = parameters->cp_tdx; + cp->tdy = parameters->cp_tdy; + + /* tile offset */ + cp->tx0 = parameters->cp_tx0; + cp->ty0 = parameters->cp_ty0; + + /* comment string */ + if(parameters->cp_comment) { + cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1); + if(cp->comment) { + strcpy(cp->comment, parameters->cp_comment); + } + } + + /* + calculate other encoding parameters + */ + + if (parameters->tile_size_on) { + cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx); + cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy); + } else { + cp->tdx = image->x1 - cp->tx0; + cp->tdy = image->y1 - cp->ty0; + } + + if(parameters->tp_on){ + cp->tp_flag = parameters->tp_flag; + cp->tp_on = 1; + } + + cp->img_size = 0; + for(i=0;inumcomps ;i++){ + cp->img_size += (image->comps[i].w *image->comps[i].h * image->comps[i].prec); + } + + +#ifdef USE_JPWL + /* + calculate JPWL encoding parameters + */ + + if (parameters->jpwl_epc_on) { + int i; + + /* set JPWL on */ + cp->epc_on = OPJ_TRUE; + cp->info_on = OPJ_FALSE; /* no informative technique */ + + /* set EPB on */ + if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { + cp->epb_on = OPJ_TRUE; + + cp->hprot_MH = parameters->jpwl_hprot_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->hprot_TPH_tileno[i] = parameters->jpwl_hprot_TPH_tileno[i]; + cp->hprot_TPH[i] = parameters->jpwl_hprot_TPH[i]; + } + /* if tile specs are not specified, copy MH specs */ + if (cp->hprot_TPH[0] == -1) { + cp->hprot_TPH_tileno[0] = 0; + cp->hprot_TPH[0] = parameters->jpwl_hprot_MH; + } + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + cp->pprot_tileno[i] = parameters->jpwl_pprot_tileno[i]; + cp->pprot_packno[i] = parameters->jpwl_pprot_packno[i]; + cp->pprot[i] = parameters->jpwl_pprot[i]; + } + } + + /* set ESD writing */ + if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) { + cp->esd_on = OPJ_TRUE; + + cp->sens_size = parameters->jpwl_sens_size; + cp->sens_addr = parameters->jpwl_sens_addr; + cp->sens_range = parameters->jpwl_sens_range; + + cp->sens_MH = parameters->jpwl_sens_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->sens_TPH_tileno[i] = parameters->jpwl_sens_TPH_tileno[i]; + cp->sens_TPH[i] = parameters->jpwl_sens_TPH[i]; + } + } + + /* always set RED writing to false: we are at the encoder */ + cp->red_on = OPJ_FALSE; + + } else { + cp->epc_on = OPJ_FALSE; + } +#endif /* USE_JPWL */ + + + /* initialize the mutiple tiles */ + /* ---------------------------- */ + cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); + + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_tcp_t *tcp = &cp->tcps[tileno]; + tcp->numlayers = parameters->tcp_numlayers; + for (j = 0; j < tcp->numlayers; j++) { + if(cp->cinema){ + if (cp->fixed_quality) { + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } + tcp->rates[j] = parameters->tcp_rates[j]; + }else{ + if (cp->fixed_quality) { /* add fixed_quality */ + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } else { + tcp->rates[j] = parameters->tcp_rates[j]; + } + } + } + tcp->csty = parameters->csty; + tcp->prg = parameters->prog_order; + tcp->mct = parameters->tcp_mct; + + numpocs_tile = 0; + tcp->POC = 0; + if (parameters->numpocs) { + /* initialisation of POC */ + tcp->POC = 1; + for (i = 0; i < parameters->numpocs; i++) { + if((tileno == parameters->POC[i].tile - 1) || (parameters->POC[i].tile == -1)) { + opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile]; + tcp_poc->resno0 = parameters->POC[numpocs_tile].resno0; + tcp_poc->compno0 = parameters->POC[numpocs_tile].compno0; + tcp_poc->layno1 = parameters->POC[numpocs_tile].layno1; + tcp_poc->resno1 = parameters->POC[numpocs_tile].resno1; + tcp_poc->compno1 = parameters->POC[numpocs_tile].compno1; + tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1; + tcp_poc->tile = parameters->POC[numpocs_tile].tile; + numpocs_tile++; + } + } + tcp->numpocs = numpocs_tile -1 ; + }else{ + tcp->numpocs = 0; + } + + tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); + + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->csty = parameters->csty & 0x01; /* 0 => one precinct || 1 => custom precinct */ + tccp->numresolutions = parameters->numresolution; + tccp->cblkw = int_floorlog2(parameters->cblockw_init); + tccp->cblkh = int_floorlog2(parameters->cblockh_init); + tccp->cblksty = parameters->mode; + tccp->qmfbid = parameters->irreversible ? 0 : 1; + tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT; + tccp->numgbits = 2; + if (i == parameters->roi_compno) { + tccp->roishift = parameters->roi_shift; + } else { + tccp->roishift = 0; + } + + if(parameters->cp_cinema) + { + /*Precinct size for lowest frequency subband=128*/ + tccp->prcw[0] = 7; + tccp->prch[0] = 7; + /*Precinct size at all other resolutions = 256*/ + for (j = 1; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 8; + tccp->prch[j] = 8; + } + }else{ + if (parameters->csty & J2K_CCP_CSTY_PRT) { + int p = 0; + for (j = tccp->numresolutions - 1; j >= 0; j--) { + if (p < parameters->res_spec) { + + if (parameters->prcw_init[p] < 1) { + tccp->prcw[j] = 1; + } else { + tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]); + } + + if (parameters->prch_init[p] < 1) { + tccp->prch[j] = 1; + }else { + tccp->prch[j] = int_floorlog2(parameters->prch_init[p]); + } + + } else { + int res_spec = parameters->res_spec; + int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); + int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); + + if (size_prcw < 1) { + tccp->prcw[j] = 1; + } else { + tccp->prcw[j] = int_floorlog2(size_prcw); + } + + if (size_prch < 1) { + tccp->prch[j] = 1; + } else { + tccp->prch[j] = int_floorlog2(size_prch); + } + } + p++; + /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */ + } /*end for*/ + } else { + for (j = 0; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 15; + tccp->prch[j] = 15; + } + } + } + + dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec); + } + } +} + +opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { + int tileno, compno; + opj_cp_t *cp = NULL; + + opj_tcd_t *tcd = NULL; /* TCD component */ + + j2k->cio = cio; + j2k->image = image; + + cp = j2k->cp; + + /* INDEX >> */ + j2k->cstr_info = cstr_info; + if (cstr_info) { + int compno; + cstr_info->tile = (opj_tile_info_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tile_info_t)); + cstr_info->image_w = image->x1 - image->x0; + cstr_info->image_h = image->y1 - image->y0; + cstr_info->prog = (&cp->tcps[0])->prg; + cstr_info->tw = cp->tw; + cstr_info->th = cp->th; + cstr_info->tile_x = cp->tdx; /* new version parser */ + cstr_info->tile_y = cp->tdy; /* new version parser */ + cstr_info->tile_Ox = cp->tx0; /* new version parser */ + cstr_info->tile_Oy = cp->ty0; /* new version parser */ + cstr_info->numcomps = image->numcomps; + cstr_info->numlayers = (&cp->tcps[0])->numlayers; + cstr_info->numdecompos = (int*) opj_malloc(image->numcomps * sizeof(int)); + for (compno=0; compno < image->numcomps; compno++) { + cstr_info->numdecompos[compno] = (&cp->tcps[0])->tccps->numresolutions - 1; + } + cstr_info->D_max = 0.0; /* ADD Marcela */ + cstr_info->main_head_start = cio_tell(cio); /* position of SOC */ + cstr_info->maxmarknum = 100; + cstr_info->marker = (opj_marker_info_t *) opj_malloc(cstr_info->maxmarknum * sizeof(opj_marker_info_t)); + cstr_info->marknum = 0; + } + /* << INDEX */ + + j2k_write_soc(j2k); + j2k_write_siz(j2k); + j2k_write_cod(j2k); + j2k_write_qcd(j2k); + + if(cp->cinema){ + for (compno = 1; compno < image->numcomps; compno++) { + j2k_write_coc(j2k, compno); + j2k_write_qcc(j2k, compno); + } + } + + for (compno = 0; compno < image->numcomps; compno++) { + opj_tcp_t *tcp = &cp->tcps[0]; + if (tcp->tccps[compno].roishift) + j2k_write_rgn(j2k, compno, 0); + } + if (cp->comment != NULL) { + j2k_write_com(j2k); + } + + j2k->totnum_tp = j2k_calculate_tp(cp,image->numcomps,image,j2k); + /* TLM Marker*/ + if(cp->cinema){ + j2k_write_tlm(j2k); + if (cp->cinema == CINEMA4K_24) { + j2k_write_poc(j2k); + } + } + + /* uncomment only for testing JPSEC marker writing */ + /* j2k_write_sec(j2k); */ + + /* INDEX >> */ + if(cstr_info) { + cstr_info->main_head_end = cio_tell(cio) - 1; + } + /* << INDEX */ + /**** Main Header ENDS here ***/ + + /* create the tile encoder */ + tcd = tcd_create(j2k->cinfo); + + /* encode each tile */ + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + int pino; + int tilepartno=0; + /* UniPG>> */ + int acc_pack_num = 0; + /* <tcps[tileno]; + opj_event_msg(j2k->cinfo, EVT_INFO, "tile number %d / %d\n", tileno + 1, cp->tw * cp->th); + + j2k->curtileno = tileno; + j2k->cur_tp_num = 0; + tcd->cur_totnum_tp = j2k->cur_totnum_tp[j2k->curtileno]; + /* initialisation before tile encoding */ + if (tileno == 0) { + tcd_malloc_encode(tcd, image, cp, j2k->curtileno); + } else { + tcd_init_encode(tcd, image, cp, j2k->curtileno); + } + + /* INDEX >> */ + if(cstr_info) { + cstr_info->tile[j2k->curtileno].start_pos = cio_tell(cio) + j2k->pos_correction; + cstr_info->tile[j2k->curtileno].maxmarknum = 10; + cstr_info->tile[j2k->curtileno].marker = (opj_marker_info_t *) opj_malloc(cstr_info->tile[j2k->curtileno].maxmarknum * sizeof(opj_marker_info_t)); + cstr_info->tile[j2k->curtileno].marknum = 0; + } + /* << INDEX */ + + for(pino = 0; pino <= tcp->numpocs; pino++) { + int tot_num_tp; + tcd->cur_pino=pino; + + /*Get number of tile parts*/ + tot_num_tp = j2k_get_num_tp(cp,pino,tileno); + tcd->tp_pos = cp->tp_pos; + + for(tilepartno = 0; tilepartno < tot_num_tp ; tilepartno++){ + j2k->tp_num = tilepartno; + /* INDEX >> */ + if(cstr_info) + cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_start_pos = + cio_tell(cio) + j2k->pos_correction; + /* << INDEX */ + j2k_write_sot(j2k); + + if(j2k->cur_tp_num == 0 && cp->cinema == 0){ + for (compno = 1; compno < image->numcomps; compno++) { + j2k_write_coc(j2k, compno); + j2k_write_qcc(j2k, compno); + } + if (cp->tcps[tileno].numpocs) { + j2k_write_poc(j2k); + } + } + + /* INDEX >> */ + if(cstr_info) + cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_header = + cio_tell(cio) + j2k->pos_correction + 1; + /* << INDEX */ + + j2k_write_sod(j2k, tcd); + + /* INDEX >> */ + if(cstr_info) { + cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_pos = + cio_tell(cio) + j2k->pos_correction - 1; + cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_start_pack = + acc_pack_num; + cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_numpacks = + cstr_info->packno - acc_pack_num; + acc_pack_num = cstr_info->packno; + } + /* << INDEX */ + + j2k->cur_tp_num++; + } + } + if(cstr_info) { + cstr_info->tile[j2k->curtileno].end_pos = cio_tell(cio) + j2k->pos_correction - 1; + } + + + /* + if (tile->PPT) { // BAD PPT !!! + FILE *PPT_file; + int i; + PPT_file=fopen("PPT","rb"); + fprintf(stderr,"%c%c%c%c",255,97,tile->len_ppt/256,tile->len_ppt%256); + for (i=0;ilen_ppt;i++) { + unsigned char elmt; + fread(&elmt, 1, 1, PPT_file); + fwrite(&elmt,1,1,f); + } + fclose(PPT_file); + unlink("PPT"); + } + */ + + } + + /* destroy the tile encoder */ + tcd_free_encode(tcd); + tcd_destroy(tcd); + + opj_free(j2k->cur_totnum_tp); + + j2k_write_eoc(j2k); + + if(cstr_info) { + cstr_info->codestream_size = cio_tell(cio) + j2k->pos_correction; + /* UniPG>> */ + /* The following adjustment is done to adjust the codestream size */ + /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */ + /* the first bunch of bytes is not in the codestream */ + cstr_info->codestream_size -= cstr_info->main_head_start; + /* <epc_on) { + + /* encode according to JPWL */ + jpwl_encode(j2k, cio, image); + + } +#endif /* USE_JPWL */ + + return OPJ_TRUE; +} + +static void j2k_add_mhmarker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) { + + if (!cstr_info) + return; + + /* expand the list? */ + if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) { + cstr_info->maxmarknum = 100 + (int) ((float) cstr_info->maxmarknum * 1.0F); + cstr_info->marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum); + } + + /* add the marker */ + cstr_info->marker[cstr_info->marknum].type = type; + cstr_info->marker[cstr_info->marknum].pos = pos; + cstr_info->marker[cstr_info->marknum].len = len; + cstr_info->marknum++; + +} + +static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) { + + opj_marker_info_t *marker; + + if (!cstr_info) + return; + + /* expand the list? */ + if ((cstr_info->tile[tileno].marknum + 1) > cstr_info->tile[tileno].maxmarknum) { + cstr_info->tile[tileno].maxmarknum = 100 + (int) ((float) cstr_info->tile[tileno].maxmarknum * 1.0F); + cstr_info->tile[tileno].marker = (opj_marker_info_t*)opj_realloc(cstr_info->tile[tileno].marker, cstr_info->maxmarknum); + } + + marker = &(cstr_info->tile[tileno].marker[cstr_info->tile[tileno].marknum]); + + /* add the marker */ + marker->type = type; + marker->pos = pos; + marker->len = len; + cstr_info->tile[tileno].marknum++; +} diff --git a/src/add-ons/translators/icns/openjpeg/j2k.h b/src/add-ons/translators/icns/openjpeg/j2k.h new file mode 100644 index 0000000000..6338c290df --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/j2k.h @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __J2K_H +#define __J2K_H +/** +@file j2k.h +@brief The JPEG-2000 Codestream Reader/Writer (J2K) + +The functions in J2K.C have for goal to read/write the several parts of the codestream: markers and data. +*/ + +/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ +/*@{*/ + +#define J2K_CP_CSTY_PRT 0x01 +#define J2K_CP_CSTY_SOP 0x02 +#define J2K_CP_CSTY_EPH 0x04 +#define J2K_CCP_CSTY_PRT 0x01 +#define J2K_CCP_CBLKSTY_LAZY 0x01 /**< Selective arithmetic coding bypass */ +#define J2K_CCP_CBLKSTY_RESET 0x02 /**< Reset context probabilities on coding pass boundaries */ +#define J2K_CCP_CBLKSTY_TERMALL 0x04 /**< Termination on each coding pass */ +#define J2K_CCP_CBLKSTY_VSC 0x08 /**< Vertically stripe causal context */ +#define J2K_CCP_CBLKSTY_PTERM 0x10 /**< Predictable termination */ +#define J2K_CCP_CBLKSTY_SEGSYM 0x20 /**< Segmentation symbols are used */ +#define J2K_CCP_QNTSTY_NOQNT 0 +#define J2K_CCP_QNTSTY_SIQNT 1 +#define J2K_CCP_QNTSTY_SEQNT 2 + +/* ----------------------------------------------------------------------- */ + +#define J2K_MS_SOC 0xff4f /**< SOC marker value */ +#define J2K_MS_SOT 0xff90 /**< SOT marker value */ +#define J2K_MS_SOD 0xff93 /**< SOD marker value */ +#define J2K_MS_EOC 0xffd9 /**< EOC marker value */ +#define J2K_MS_SIZ 0xff51 /**< SIZ marker value */ +#define J2K_MS_COD 0xff52 /**< COD marker value */ +#define J2K_MS_COC 0xff53 /**< COC marker value */ +#define J2K_MS_RGN 0xff5e /**< RGN marker value */ +#define J2K_MS_QCD 0xff5c /**< QCD marker value */ +#define J2K_MS_QCC 0xff5d /**< QCC marker value */ +#define J2K_MS_POC 0xff5f /**< POC marker value */ +#define J2K_MS_TLM 0xff55 /**< TLM marker value */ +#define J2K_MS_PLM 0xff57 /**< PLM marker value */ +#define J2K_MS_PLT 0xff58 /**< PLT marker value */ +#define J2K_MS_PPM 0xff60 /**< PPM marker value */ +#define J2K_MS_PPT 0xff61 /**< PPT marker value */ +#define J2K_MS_SOP 0xff91 /**< SOP marker value */ +#define J2K_MS_EPH 0xff92 /**< EPH marker value */ +#define J2K_MS_CRG 0xff63 /**< CRG marker value */ +#define J2K_MS_COM 0xff64 /**< COM marker value */ +/* UniPG>> */ +#ifdef USE_JPWL +#define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_EPB 0xff66 /**< EPB marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_ESD 0xff67 /**< ESD marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_RED 0xff69 /**< RED marker value (Part 11: JPEG 2000 for Wireless) */ +#endif /* USE_JPWL */ +#ifdef USE_JPSEC +#define J2K_MS_SEC 0xff65 /**< SEC marker value (Part 8: Secure JPEG 2000) */ +#define J2K_MS_INSEC 0xff94 /**< INSEC marker value (Part 8: Secure JPEG 2000) */ +#endif /* USE_JPSEC */ +/* < there was a PPT marker for the present tile */ + int ppt; + /** used in case of multiple marker PPT (number of info already stored) */ + int ppt_store; + /** ppmbug1 */ + int ppt_len; + /** add fixed_quality */ + float distoratio[100]; + /** tile-component coding parameters */ + opj_tccp_t *tccps; +} opj_tcp_t; + +/** +Coding parameters +*/ +typedef struct opj_cp { + /** Digital cinema profile*/ + OPJ_CINEMA_MODE cinema; + /** Maximum rate for each component. If == 0, component size limitation is not considered */ + int max_comp_size; + /** Size of the image in bits*/ + int img_size; + /** Rsiz*/ + OPJ_RSIZ_CAPABILITIES rsiz; + /** Enabling Tile part generation*/ + char tp_on; + /** Flag determining tile part generation*/ + char tp_flag; + /** Position of tile part flag in progression order*/ + int tp_pos; + /** allocation by rate/distortion */ + int disto_alloc; + /** allocation by fixed layer */ + int fixed_alloc; + /** add fixed_quality */ + int fixed_quality; + /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */ + int reduce; + /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ + int layer; + /** if == NO_LIMITATION, decode entire codestream; if == LIMIT_TO_MAIN_HEADER then only decode the main header */ + OPJ_LIMIT_DECODING limit_decoding; + /** XTOsiz */ + int tx0; + /** YTOsiz */ + int ty0; + /** XTsiz */ + int tdx; + /** YTsiz */ + int tdy; + /** comment for coding */ + char *comment; + /** number of tiles in width */ + int tw; + /** number of tiles in heigth */ + int th; + /** ID number of the tiles present in the codestream */ + int *tileno; + /** size of the vector tileno */ + int tileno_size; + /** packet header store there for futur use in t2_decode_packet */ + unsigned char *ppm_data; + /** pointer remaining on the first byte of the first header if ppm is used */ + unsigned char *ppm_data_first; + /** if ppm == 1 --> there was a PPM marker for the present tile */ + int ppm; + /** use in case of multiple marker PPM (number of info already store) */ + int ppm_store; + /** use in case of multiple marker PPM (case on non-finished previous info) */ + int ppm_previous; + /** ppmbug1 */ + int ppm_len; + /** tile coding parameters */ + opj_tcp_t *tcps; + /** fixed layer */ + int *matrice; +/* UniPG>> */ +#ifdef USE_JPWL + /** enables writing of EPC in MH, thus activating JPWL */ + opj_bool epc_on; + /** enables writing of EPB, in case of activated JPWL */ + opj_bool epb_on; + /** enables writing of ESD, in case of activated JPWL */ + opj_bool esd_on; + /** enables writing of informative techniques of ESD, in case of activated JPWL */ + opj_bool info_on; + /** enables writing of RED, in case of activated JPWL */ + opj_bool red_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int hprot_MH; + /** tile number of header protection specification (>=0) */ + int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0/2/4 bytes) */ + int sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int sens_addr; + /** sensitivity range (0-3) */ + int sens_range; + /** sensitivity method for MH (-1,0-7) */ + int sens_MH; + /** tile number of sensitivity specification (>=0) */ + int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1,0-7) */ + int sens_TPH[JPWL_MAX_NO_TILESPECS]; + /** enables JPWL correction at the decoder */ + opj_bool correct; + /** expected number of components at the decoder */ + int exp_comps; + /** maximum number of tiles at the decoder */ + int max_tiles; +#endif /* USE_JPWL */ +/* <cp. +@param j2k J2K decompressor handle +@param parameters decompression parameters +*/ +void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters); +/** +Decode an image from a JPEG-2000 codestream +@param j2k J2K decompressor handle +@param cio Input buffer stream +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns a decoded image if successful, returns NULL otherwise +*/ +opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info); +/** +Decode an image form a JPT-stream (JPEG 2000, JPIP) +@param j2k J2K decompressor handle +@param cio Input buffer stream +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns a decoded image if successful, returns NULL otherwise +*/ +opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info); +/** +Creates a J2K compression structure +@param cinfo Codec context info +@return Returns a handle to a J2K compressor if successful, returns NULL otherwise +*/ +opj_j2k_t* j2k_create_compress(opj_common_ptr cinfo); +/** +Destroy a J2K compressor handle +@param j2k J2K compressor handle to destroy +*/ +void j2k_destroy_compress(opj_j2k_t *j2k); +/** +Setup the encoder parameters using the current image and using user parameters. +Coding parameters are returned in j2k->cp. +@param j2k J2K compressor handle +@param parameters compression parameters +@param image input filled image +*/ +void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image); +/** +Converts an enum type progression order to string type +*/ +char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); +/** +Encode an image into a JPEG-2000 codestream +@param j2k J2K compressor handle +@param cio Output buffer stream +@param image Image to encode +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __J2K_H */ diff --git a/src/add-ons/translators/icns/openjpeg/j2k_lib.c b/src/add-ons/translators/icns/openjpeg/j2k_lib.c new file mode 100644 index 0000000000..a66e31e9af --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/j2k_lib.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif /* _WIN32 */ +#include "opj_includes.h" + +double opj_clock(void) { +#ifdef _WIN32 + /* _WIN32: use QueryPerformance (very accurate) */ + LARGE_INTEGER freq , t ; + /* freq is the clock speed of the CPU */ + QueryPerformanceFrequency(&freq) ; + /* cout << "freq = " << ((double) freq.QuadPart) << endl; */ + /* t is the high resolution performance counter (see MSDN) */ + QueryPerformanceCounter ( & t ) ; + return ( t.QuadPart /(double) freq.QuadPart ) ; +#else + /* Unix or Linux: use resource usage */ + struct rusage t; + double procTime; + /* (1) Get the rusage data structure at this moment (man getrusage) */ + getrusage(0,&t); + /* (2) What is the elapsed time ? - CPU time = User time + System time */ + /* (2a) Get the seconds */ + procTime = t.ru_utime.tv_sec + t.ru_stime.tv_sec; + /* (2b) More precisely! Get the microseconds part ! */ + return ( procTime + (t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ; +#endif +} + diff --git a/src/add-ons/translators/icns/openjpeg/j2k_lib.h b/src/add-ons/translators/icns/openjpeg/j2k_lib.h new file mode 100644 index 0000000000..5f3406e510 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/j2k_lib.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __J2K_LIB_H +#define __J2K_LIB_H +/** +@file j2k_lib.h +@brief Internal functions + +The functions in J2K_LIB.C are internal utilities mainly used for timing. +*/ + +/** @defgroup MISC MISC - Miscellaneous internal functions */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Difference in successive opj_clock() calls tells you the elapsed time +@return Returns time in seconds +*/ +double opj_clock(void); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __J2K_LIB_H */ + diff --git a/src/add-ons/translators/icns/openjpeg/jp2.c b/src/add-ons/translators/icns/openjpeg/jp2.c new file mode 100644 index 0000000000..d43e70c560 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/jp2.c @@ -0,0 +1,1223 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ +#include "opj_includes.h" + +/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Read box headers +@param cinfo Codec context info +@param cio Input stream +@param box +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box); +/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/ +/** +Read the IHDR box - Image Header box +@param jp2 JP2 handle +@param cio Input buffer stream +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); +static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); +static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); +static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); +static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio); +/** +Write the FTYP box - File type box +@param jp2 JP2 handle +@param cio Output buffer stream +*/ +static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); +/** +Read the FTYP box - File type box +@param jp2 JP2 handle +@param cio Input buffer stream +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); +static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); +static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset); +static void jp2_write_jp(opj_cio_t *cio); +/** +Read the JP box - JPEG 2000 signature +@param jp2 JP2 handle +@param cio Input buffer stream +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio); +/** +Decode the structure of a JP2 file +@param jp2 JP2 handle +@param cio Input buffer stream +@param color Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_color_t *color); +/** +Apply collected palette data +@param color Collector for profile, cdef and pclr data +@param image +*/ +static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo); +/** +Collect palette data +@param jp2 JP2 handle +@param cio Input buffer stream +@param box +@param color Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color); +/** +Collect component mapping data +@param jp2 JP2 handle +@param cio Input buffer stream +@param box +@param color Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color); +/** +Collect colour specification data +@param jp2 JP2 handle +@param cio Input buffer stream +@param box +@param color Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color); +/** +Write file Index (superbox) +@param[in] offset_jp2c offset of jp2c box +@param[in] length_jp2c length of jp2c box +@param[in] offset_idx offset of cidx box +@param[in] length_idx length of cidx box +@param[in] cio file output handle +@return length of fidx box +*/ +static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); +/** +Write index Finder box +@param[in] offset offset of fidx box +@param[in] length length of fidx box +@param[in] cio file output handle +*/ +static void write_iptr( int offset, int length, opj_cio_t *cio); +/** +Write proxy box +@param[in] offset_jp2c offset of jp2c box +@param[in] length_jp2c length of jp2c box +@param[in] offset_idx offset of cidx box +@param[in] length_idx length of cidx box +@param[in] cio file output handle +*/ +static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box) { + box->init_pos = cio_tell(cio); + box->length = cio_read(cio, 4); + box->type = cio_read(cio, 4); + if (box->length == 1) { + if (cio_read(cio, 4) != 0) { + opj_event_msg(cinfo, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); + return OPJ_FALSE; + } + box->length = cio_read(cio, 4); + if (box->length == 0) + box->length = cio_numbytesleft(cio) + 12; + } + else if (box->length == 0) { + box->length = cio_numbytesleft(cio) + 8; + } + + return OPJ_TRUE; +} + +#if 0 +static void jp2_write_url(opj_cio_t *cio, char *Idx_file) { + unsigned int i; + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_URL, 4); /* DBTL */ + cio_write(cio, 0, 1); /* VERS */ + cio_write(cio, 0, 3); /* FLAG */ + + if(Idx_file) { + for (i = 0; i < strlen(Idx_file); i++) { + cio_write(cio, Idx_file[i], 1); + } + } + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} +#endif + +static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { + opj_jp2_box_t box; + + opj_common_ptr cinfo = jp2->cinfo; + + if(jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } + if (JP2_IHDR != box.type) { + opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n"); + return OPJ_FALSE; + } + + jp2->h = cio_read(cio, 4); /* HEIGHT */ + jp2->w = cio_read(cio, 4); /* WIDTH */ + jp2->numcomps = cio_read(cio, 2); /* NC */ + jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); + + jp2->bpc = cio_read(cio, 1); /* BPC */ + + jp2->C = cio_read(cio, 1); /* C */ + jp2->UnkC = cio_read(cio, 1); /* UnkC */ + jp2->IPR = cio_read(cio, 1); /* IPR */ + + if (cio_tell(cio) - box.init_pos != box.length) { + opj_event_msg(cinfo, EVT_ERROR, "Error with IHDR Box\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_IHDR, 4); /* IHDR */ + + cio_write(cio, jp2->h, 4); /* HEIGHT */ + cio_write(cio, jp2->w, 4); /* WIDTH */ + cio_write(cio, jp2->numcomps, 2); /* NC */ + + cio_write(cio, jp2->bpc, 1); /* BPC */ + + cio_write(cio, jp2->C, 1); /* C : Always 7 */ + cio_write(cio, jp2->UnkC, 1); /* UnkC, colorspace unknown */ + cio_write(cio, jp2->IPR, 1); /* IPR, no intellectual property */ + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} + +static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { + unsigned int i; + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_BPCC, 4); /* BPCC */ + + for (i = 0; i < jp2->numcomps; i++) { + cio_write(cio, jp2->comps[i].bpcc, 1); + } + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} + + +static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { + unsigned int i; + opj_jp2_box_t box; + + opj_common_ptr cinfo = jp2->cinfo; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } + if (JP2_BPCC != box.type) { + opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n"); + return OPJ_FALSE; + } + + for (i = 0; i < jp2->numcomps; i++) { + jp2->comps[i].bpcc = cio_read(cio, 1); + } + + if (cio_tell(cio) - box.init_pos != box.length) { + opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) { + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_COLR, 4); /* COLR */ + + cio_write(cio, jp2->meth, 1); /* METH */ + cio_write(cio, jp2->precedence, 1); /* PRECEDENCE */ + cio_write(cio, jp2->approx, 1); /* APPROX */ + + if(jp2->meth == 2) + jp2->enumcs = 0; + + cio_write(cio, jp2->enumcs, 4); /* EnumCS */ + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} + +static void jp2_free_pclr(opj_jp2_color_t *color) +{ + opj_free(color->jp2_pclr->channel_sign); + opj_free(color->jp2_pclr->channel_size); + opj_free(color->jp2_pclr->entries); + + if(color->jp2_pclr->cmap) opj_free(color->jp2_pclr->cmap); + + opj_free(color->jp2_pclr); color->jp2_pclr = NULL; +} + +static void free_color_data(opj_jp2_color_t *color) +{ + if(color->jp2_pclr) + { + jp2_free_pclr(color); + } + if(color->jp2_cdef) + { + if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); + opj_free(color->jp2_cdef); + } + if(color->icc_profile_buf) opj_free(color->icc_profile_buf); +} + +static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo) +{ + opj_image_comp_t *old_comps, *new_comps; + unsigned char *channel_size, *channel_sign; + unsigned int *entries; + opj_jp2_cmap_comp_t *cmap; + int *src, *dst; + unsigned int j, max; + unsigned short i, nr_channels, cmp, pcol; + int k, top_k; + + channel_size = color->jp2_pclr->channel_size; + channel_sign = color->jp2_pclr->channel_sign; + entries = color->jp2_pclr->entries; + cmap = color->jp2_pclr->cmap; + nr_channels = color->jp2_pclr->nr_channels; + + old_comps = image->comps; + new_comps = (opj_image_comp_t*) + opj_malloc(nr_channels * sizeof(opj_image_comp_t)); + + for(i = 0; i < nr_channels; ++i) + { + pcol = cmap[i].pcol; cmp = cmap[i].cmp; + + if( pcol < nr_channels ) + new_comps[pcol] = old_comps[cmp]; + else + { + opj_event_msg(cinfo, EVT_ERROR, "Error with pcol value %d (max: %d). skipping\n", pcol, nr_channels); + continue; + } + + if(cmap[i].mtyp == 0) /* Direct use */ + { + old_comps[cmp].data = NULL; continue; + } +/* Palette mapping: */ + new_comps[pcol].data = (int*) + opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int)); + new_comps[pcol].prec = channel_size[i]; + new_comps[pcol].sgnd = channel_sign[i]; + } + top_k = color->jp2_pclr->nr_entries - 1; + + for(i = 0; i < nr_channels; ++i) + { +/* Direct use: */ + if(cmap[i].mtyp == 0) continue; + +/* Palette mapping: */ + cmp = cmap[i].cmp; pcol = cmap[i].pcol; + src = old_comps[cmp].data; + dst = new_comps[pcol].data; + max = new_comps[pcol].w * new_comps[pcol].h; + + for(j = 0; j < max; ++j) + { +/* The index */ + if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; +/* The colour */ + dst[j] = entries[k * nr_channels + pcol]; + } + } + max = image->numcomps; + for(i = 0; i < max; ++i) + { + if(old_comps[i].data) opj_free(old_comps[i].data); + } + opj_free(old_comps); + image->comps = new_comps; + image->numcomps = nr_channels; + + jp2_free_pclr(color); + +}/* apply_pclr() */ + +static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ + opj_jp2_pclr_t *jp2_pclr; + unsigned char *channel_size, *channel_sign; + unsigned int *entries; + unsigned short nr_entries, nr_channels; + unsigned short i, j; + unsigned char uc; + + OPJ_ARG_NOT_USED(box); + OPJ_ARG_NOT_USED(jp2); + +/* Part 1, I.5.3.4: 'There shall be at most one Palette box inside + * a JP2 Header box' : +*/ + if(color->jp2_pclr) return OPJ_FALSE; + + nr_entries = (unsigned short)cio_read(cio, 2); /* NE */ + nr_channels = (unsigned short)cio_read(cio, 1);/* NPC */ + + entries = (unsigned int*) + opj_malloc(nr_channels * nr_entries * sizeof(unsigned int)); + channel_size = (unsigned char*)opj_malloc(nr_channels); + channel_sign = (unsigned char*)opj_malloc(nr_channels); + + jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); + jp2_pclr->channel_sign = channel_sign; + jp2_pclr->channel_size = channel_size; + jp2_pclr->entries = entries; + jp2_pclr->nr_entries = nr_entries; + jp2_pclr->nr_channels = nr_channels; + jp2_pclr->cmap = NULL; + + color->jp2_pclr = jp2_pclr; + + for(i = 0; i < nr_channels; ++i) + { + uc = cio_read(cio, 1); /* Bi */ + channel_size[i] = (uc & 0x7f) + 1; + channel_sign[i] = (uc & 0x80)?1:0; + } + + for(j = 0; j < nr_entries; ++j) + { + for(i = 0; i < nr_channels; ++i) + { +/* Cji */ + *entries++ = cio_read(cio, (channel_size[i]+7)>>3); + } + } + + return OPJ_TRUE; +}/* jp2_read_pclr() */ + +static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ + opj_jp2_cmap_comp_t *cmap; + unsigned short i, nr_channels; + + OPJ_ARG_NOT_USED(box); + OPJ_ARG_NOT_USED(jp2); + +/* Need nr_channels: */ + if(color->jp2_pclr == NULL) return OPJ_FALSE; + +/* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box + * inside a JP2 Header box' : +*/ + if(color->jp2_pclr->cmap) return OPJ_FALSE; + + nr_channels = color->jp2_pclr->nr_channels; + cmap = (opj_jp2_cmap_comp_t*) + opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t)); + + for(i = 0; i < nr_channels; ++i) + { + cmap[i].cmp = (unsigned short)cio_read(cio, 2); + cmap[i].mtyp = cio_read(cio, 1); + cmap[i].pcol = cio_read(cio, 1); + + } + color->jp2_pclr->cmap = cmap; + + return OPJ_TRUE; +}/* jp2_read_cmap() */ + +static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) +{ + opj_jp2_cdef_info_t *info; + int color_space; + unsigned short i, n, cn, typ, asoc, acn; + + color_space = image->color_space; + info = color->jp2_cdef->info; + n = color->jp2_cdef->n; + + for(i = 0; i < n; ++i) + { +/* WATCH: acn = asoc - 1 ! */ + if((asoc = info[i].asoc) == 0) continue; + + cn = info[i].cn; typ = info[i].typ; acn = asoc - 1; + + if(cn != acn) + { + opj_image_comp_t saved; + + memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); + + info[i].asoc = cn + 1; + info[acn].asoc = info[acn].cn + 1; + } + } + if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); + + opj_free(color->jp2_cdef); color->jp2_cdef = NULL; + +}/* jp2_apply_cdef() */ + +static opj_bool jp2_read_cdef(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ + opj_jp2_cdef_info_t *info; + unsigned short i, n; + + OPJ_ARG_NOT_USED(box); + OPJ_ARG_NOT_USED(jp2); + +/* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box + * inside a JP2 Header box.' +*/ + if(color->jp2_cdef) return OPJ_FALSE; + + if((n = (unsigned short)cio_read(cio, 2)) == 0) return OPJ_FALSE; /* szukw000: FIXME */ + + info = (opj_jp2_cdef_info_t*) + opj_malloc(n * sizeof(opj_jp2_cdef_info_t)); + + color->jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); + color->jp2_cdef->info = info; + color->jp2_cdef->n = n; + + for(i = 0; i < n; ++i) + { + info[i].cn = (unsigned short)cio_read(cio, 2); + info[i].typ = (unsigned short)cio_read(cio, 2); + info[i].asoc = (unsigned short)cio_read(cio, 2); + + } + return OPJ_TRUE; +}/* jp2_read_cdef() */ + +static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ + int skip_len; + opj_common_ptr cinfo; + +/* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour + * Specification boxes after the first.' +*/ + if(color->jp2_has_colr) return OPJ_FALSE; + + cinfo = jp2->cinfo; + + jp2->meth = cio_read(cio, 1); /* METH */ + jp2->precedence = cio_read(cio, 1); /* PRECEDENCE */ + jp2->approx = cio_read(cio, 1); /* APPROX */ + + if (jp2->meth == 1) + { + jp2->enumcs = cio_read(cio, 4); /* EnumCS */ + } + else + if (jp2->meth == 2) + { +/* skip PROFILE */ + skip_len = box->init_pos + box->length - cio_tell(cio); + if (skip_len < 0) + { + opj_event_msg(cinfo, EVT_ERROR, "Error with COLR box size\n"); + return OPJ_FALSE; + } + if(skip_len > 0) + { + unsigned char *start; + + start = cio_getbp(cio); + color->icc_profile_buf = (unsigned char*)opj_malloc(skip_len); + color->icc_profile_len = skip_len; + + cio_skip(cio, box->init_pos + box->length - cio_tell(cio)); + + memcpy(color->icc_profile_buf, start, skip_len); + } + } + + if (cio_tell(cio) - box->init_pos != box->length) + { + opj_event_msg(cinfo, EVT_ERROR, "Error with COLR Box\n"); + return OPJ_FALSE; + } + color->jp2_has_colr = 1; + + return OPJ_TRUE; +}/* jp2_read_colr() */ + +opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color) +{ + opj_jp2_box_t box; + int jp2h_end; + + opj_common_ptr cinfo = jp2->cinfo; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + do { + if (JP2_JP2H != box.type) + { + if (box.type == JP2_JP2C) + { + opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n"); + return OPJ_FALSE; + } + cio_skip(cio, box.length - 8); + + if(cio->bp >= cio->end) return OPJ_FALSE; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + } + } while(JP2_JP2H != box.type); + + if (!jp2_read_ihdr(jp2, cio)) + return OPJ_FALSE; + jp2h_end = box.init_pos + box.length; + + if (jp2->bpc == 255) + { + if (!jp2_read_bpcc(jp2, cio)) + return OPJ_FALSE; + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + + while(cio_tell(cio) < jp2h_end) + { + if(box.type == JP2_COLR) + { + if( !jp2_read_colr(jp2, cio, &box, color)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + if(box.type == JP2_CDEF && !jp2->ignore_pclr_cmap_cdef) + { + if( !jp2_read_cdef(jp2, cio, &box, color)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + if(box.type == JP2_PCLR && !jp2->ignore_pclr_cmap_cdef) + { + if( !jp2_read_pclr(jp2, cio, &box, color)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + if(box.type == JP2_CMAP && !jp2->ignore_pclr_cmap_cdef) + { + if( !jp2_read_cmap(jp2, cio, &box, color)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + + }/* while(cio_tell(cio) < box_end) */ + + cio_seek(cio, jp2h_end); + + /* Part 1, I.5.3.3 : 'must contain at least one' */ + return (color->jp2_has_colr == 1); + +}/* jp2_read_jp2h() */ + +opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, + opj_codestream_info_t *cstr_info) +{ + opj_common_ptr cinfo; + opj_image_t *image = NULL; + opj_jp2_color_t color; + + if(!jp2 || !cio) + { + return NULL; + } + memset(&color, 0, sizeof(opj_jp2_color_t)); + cinfo = jp2->cinfo; + +/* JP2 decoding */ + if(!jp2_read_struct(jp2, cio, &color)) + { + free_color_data(&color); + opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n"); + return NULL; + } + +/* J2K decoding */ + image = j2k_decode(jp2->j2k, cio, cstr_info); + + if(!image) + { + free_color_data(&color); + opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n"); + return NULL; + } + + if (!jp2->ignore_pclr_cmap_cdef){ + + /* Set Image Color Space */ + if (jp2->enumcs == 16) + image->color_space = CLRSPC_SRGB; + else if (jp2->enumcs == 17) + image->color_space = CLRSPC_GRAY; + else if (jp2->enumcs == 18) + image->color_space = CLRSPC_SYCC; + else + image->color_space = CLRSPC_UNKNOWN; + + if(color.jp2_cdef) + { + jp2_apply_cdef(image, &color); + } + if(color.jp2_pclr) + { +/* Part 1, I.5.3.4: Either both or none : */ + if( !color.jp2_pclr->cmap) + jp2_free_pclr(&color); + else + jp2_apply_pclr(&color, image, cinfo); + } + if(color.icc_profile_buf) + { + image->icc_profile_buf = color.icc_profile_buf; + color.icc_profile_buf = NULL; + image->icc_profile_len = color.icc_profile_len; + } + } + + return image; + +}/* opj_jp2_decode() */ + + +void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_JP2H, 4); /* JP2H */ + + jp2_write_ihdr(jp2, cio); + + if (jp2->bpc == 255) { + jp2_write_bpcc(jp2, cio); + } + jp2_write_colr(jp2, cio); + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} + +static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { + unsigned int i; + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_FTYP, 4); /* FTYP */ + + cio_write(cio, jp2->brand, 4); /* BR */ + cio_write(cio, jp2->minversion, 4); /* MinV */ + + for (i = 0; i < jp2->numcl; i++) { + cio_write(cio, jp2->cl[i], 4); /* CL */ + } + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} + +static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { + int i; + opj_jp2_box_t box; + + opj_common_ptr cinfo = jp2->cinfo; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } + if (JP2_FTYP != box.type) { + opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n"); + return OPJ_FALSE; + } + + jp2->brand = cio_read(cio, 4); /* BR */ + jp2->minversion = cio_read(cio, 4); /* MinV */ + jp2->numcl = (box.length - 16) / 4; + jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int)); + + for (i = 0; i < (int)jp2->numcl; i++) { + jp2->cl[i] = cio_read(cio, 4); /* CLi */ + } + + if (cio_tell(cio) - box.init_pos != box.length) { + opj_event_msg(cinfo, EVT_ERROR, "Error with FTYP Box\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { + unsigned int j2k_codestream_offset, j2k_codestream_length; + opj_jp2_box_t box; + + opj_j2k_t *j2k = jp2->j2k; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_JP2C, 4); /* JP2C */ + + /* J2K encoding */ + j2k_codestream_offset = cio_tell(cio); + if(!j2k_encode(j2k, cio, image, cstr_info)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Failed to encode image\n"); + return 0; + } + j2k_codestream_length = cio_tell(cio) - j2k_codestream_offset; + + jp2->j2k_codestream_offset = j2k_codestream_offset; + jp2->j2k_codestream_length = j2k_codestream_length; + + box.length = 8 + jp2->j2k_codestream_length; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); + + return box.length; +} + +static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) { + opj_jp2_box_t box; + + opj_common_ptr cinfo = jp2->cinfo; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } + do { + if(JP2_JP2C != box.type) { + cio_skip(cio, box.length - 8); + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + } + } while(JP2_JP2C != box.type); + + *j2k_codestream_offset = cio_tell(cio); + *j2k_codestream_length = box.length - 8; + + return OPJ_TRUE; +} + +static void jp2_write_jp(opj_cio_t *cio) { + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_JP, 4); /* JP2 signature */ + cio_write(cio, 0x0d0a870a, 4); + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} + +static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) { + opj_jp2_box_t box; + + opj_common_ptr cinfo = jp2->cinfo; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } + if (JP2_JP != box.type) { + opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n"); + return OPJ_FALSE; + } + if (0x0d0a870a != cio_read(cio, 4)) { + opj_event_msg(cinfo, EVT_ERROR, "Error with JP Marker\n"); + return OPJ_FALSE; + } + if (cio_tell(cio) - box.init_pos != box.length) { + opj_event_msg(cinfo, EVT_ERROR, "Error with JP Box size\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + + +static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_color_t *color) { + if (!jp2_read_jp(jp2, cio)) + return OPJ_FALSE; + if (!jp2_read_ftyp(jp2, cio)) + return OPJ_FALSE; + if (!jp2_read_jp2h(jp2, cio, color)) + return OPJ_FALSE; + if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset)) + return OPJ_FALSE; + + return OPJ_TRUE; +} + + +static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FIDX, 4); /* IPTR */ + + write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio); + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} + +static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_PRXY, 4); /* IPTR */ + + cio_write( cio, offset_jp2c, 8); /* OOFF */ + cio_write( cio, length_jp2c, 4); /* OBH part 1 */ + cio_write( cio, JP2_JP2C, 4); /* OBH part 2 */ + + cio_write( cio, 1,1); /* NI */ + + cio_write( cio, offset_idx, 8); /* IOFF */ + cio_write( cio, length_idx, 4); /* IBH part 1 */ + cio_write( cio, JPIP_CIDX, 4); /* IBH part 2 */ + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); +} + +static void write_iptr( int offset, int length, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_IPTR, 4); /* IPTR */ + + cio_write( cio, offset, 8); + cio_write( cio, length, 8); + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); +} + + +/* ----------------------------------------------------------------------- */ +/* JP2 decoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo) { + opj_jp2_t *jp2 = (opj_jp2_t*) opj_calloc(1, sizeof(opj_jp2_t)); + if(jp2) { + jp2->cinfo = cinfo; + /* create the J2K codec */ + jp2->j2k = j2k_create_decompress(cinfo); + if(jp2->j2k == NULL) { + jp2_destroy_decompress(jp2); + return NULL; + } + } + return jp2; +} + +void jp2_destroy_decompress(opj_jp2_t *jp2) { + if(jp2) { + /* destroy the J2K codec */ + j2k_destroy_decompress(jp2->j2k); + + if(jp2->comps) { + opj_free(jp2->comps); + } + if(jp2->cl) { + opj_free(jp2->cl); + } + opj_free(jp2); + } +} + +void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) { + /* setup the J2K codec */ + j2k_setup_decoder(jp2->j2k, parameters); + /* further JP2 initializations go here */ + jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; +} + +/* ----------------------------------------------------------------------- */ +/* JP2 encoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo) { + opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t)); + if(jp2) { + jp2->cinfo = cinfo; + /* create the J2K codec */ + jp2->j2k = j2k_create_compress(cinfo); + if(jp2->j2k == NULL) { + jp2_destroy_compress(jp2); + return NULL; + } + } + return jp2; +} + +void jp2_destroy_compress(opj_jp2_t *jp2) { + if(jp2) { + /* destroy the J2K codec */ + j2k_destroy_compress(jp2->j2k); + + if(jp2->comps) { + opj_free(jp2->comps); + } + if(jp2->cl) { + opj_free(jp2->cl); + } + opj_free(jp2); + } +} + +void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image) { + int i; + int depth_0, sign; + + if(!jp2 || !parameters || !image) + return; + + /* setup the J2K codec */ + /* ------------------- */ + + /* Check if number of components respects standard */ + if (image->numcomps < 1 || image->numcomps > 16384) { + opj_event_msg(jp2->cinfo, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n"); + return; + } + + j2k_setup_encoder(jp2->j2k, parameters, image); + + /* setup the JP2 codec */ + /* ------------------- */ + + /* Profile box */ + + jp2->brand = JP2_JP2; /* BR */ + jp2->minversion = 0; /* MinV */ + jp2->numcl = 1; + jp2->cl = (unsigned int*) opj_malloc(jp2->numcl * sizeof(unsigned int)); + jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */ + + /* Image Header box */ + + jp2->numcomps = image->numcomps; /* NC */ + jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); + jp2->h = image->y1 - image->y0; /* HEIGHT */ + jp2->w = image->x1 - image->x0; /* WIDTH */ + /* BPC */ + depth_0 = image->comps[0].prec - 1; + sign = image->comps[0].sgnd; + jp2->bpc = depth_0 + (sign << 7); + for (i = 1; i < image->numcomps; i++) { + int depth = image->comps[i].prec - 1; + sign = image->comps[i].sgnd; + if (depth_0 != depth) + jp2->bpc = 255; + } + jp2->C = 7; /* C : Always 7 */ + jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */ + jp2->IPR = 0; /* IPR, no intellectual property */ + + /* BitsPerComponent box */ + + for (i = 0; i < image->numcomps; i++) { + jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); + } + jp2->meth = 1; + if (image->color_space == 1) + jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2.1 */ + else if (image->color_space == 2) + jp2->enumcs = 17; /* greyscale */ + else if (image->color_space == 3) + jp2->enumcs = 18; /* YUV */ + jp2->precedence = 0; /* PRECEDENCE */ + jp2->approx = 0; /* APPROX */ + + jp2->jpip_on = parameters->jpip_on; +} + +opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { + + int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, len_cidx, end_pos, pos_fidx, len_fidx; + pos_jp2c = pos_iptr = -1; /* remove a warning */ + + /* JP2 encoding */ + + /* JPEG 2000 Signature box */ + jp2_write_jp(cio); + /* File Type box */ + jp2_write_ftyp(jp2, cio); + /* JP2 Header box */ + jp2_write_jp2h(jp2, cio); + + if( jp2->jpip_on){ + pos_iptr = cio_tell( cio); + cio_skip( cio, 24); /* IPTR further ! */ + + pos_jp2c = cio_tell( cio); + } + + /* J2K encoding */ + if(!(len_jp2c = jp2_write_jp2c( jp2, cio, image, cstr_info))){ + opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n"); + return OPJ_FALSE; + } + + if( jp2->jpip_on){ + pos_cidx = cio_tell( cio); + + len_cidx = write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8); + + pos_fidx = cio_tell( cio); + len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, len_cidx, cio); + + end_pos = cio_tell( cio); + + cio_seek( cio, pos_iptr); + write_iptr( pos_fidx, len_fidx, cio); + + cio_seek( cio, end_pos); + } + + return OPJ_TRUE; +} diff --git a/src/add-ons/translators/icns/openjpeg/jp2.h b/src/add-ons/translators/icns/openjpeg/jp2.h new file mode 100644 index 0000000000..acb643cad7 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/jp2.h @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __JP2_H +#define __JP2_H +/** +@file jp2.h +@brief The JPEG-2000 file format Reader/Writer (JP2) + +*/ + +/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ +/*@{*/ + +#define JPIP_JPIP 0x6a706970 + +#define JP2_JP 0x6a502020 /**< JPEG 2000 signature box */ +#define JP2_FTYP 0x66747970 /**< File type box */ +#define JP2_JP2H 0x6a703268 /**< JP2 header box */ +#define JP2_IHDR 0x69686472 /**< Image header box */ +#define JP2_COLR 0x636f6c72 /**< Colour specification box */ +#define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */ +#define JP2_URL 0x75726c20 /**< URL box */ +#define JP2_DTBL 0x6474626c /**< Data Reference box */ +#define JP2_BPCC 0x62706363 /**< Bits per component box */ +#define JP2_JP2 0x6a703220 /**< File type fields */ +#define JP2_PCLR 0x70636c72 /**< Palette box */ +#define JP2_CMAP 0x636d6170 /**< Component Mapping box */ +#define JP2_CDEF 0x63646566 /**< Channel Definition box */ + +/* ----------------------------------------------------------------------- */ +/** +Channel description: channel index, type, assocation +*/ +typedef struct opj_jp2_cdef_info +{ + unsigned short cn, typ, asoc; +} opj_jp2_cdef_info_t; + +/** +Channel descriptions and number of descriptions +*/ +typedef struct opj_jp2_cdef +{ + opj_jp2_cdef_info_t *info; + unsigned short n; +} opj_jp2_cdef_t; + +/** +Component mappings: channel index, mapping type, palette index +*/ +typedef struct opj_jp2_cmap_comp +{ + unsigned short cmp; + unsigned char mtyp, pcol; +} opj_jp2_cmap_comp_t; + +/** +Palette data: table entries, palette columns +*/ +typedef struct opj_jp2_pclr +{ + unsigned int *entries; + unsigned char *channel_sign; + unsigned char *channel_size; + opj_jp2_cmap_comp_t *cmap; + unsigned short nr_entries, nr_channels; +} opj_jp2_pclr_t; + +/** +Collector for ICC profile, palette, component mapping, channel description +*/ +typedef struct opj_jp2_color +{ + unsigned char *icc_profile_buf; + int icc_profile_len; + + opj_jp2_cdef_t *jp2_cdef; + opj_jp2_pclr_t *jp2_pclr; + unsigned char jp2_has_colr; +} opj_jp2_color_t; + +/** +JP2 component +*/ +typedef struct opj_jp2_comps { + int depth; + int sgnd; + int bpcc; +} opj_jp2_comps_t; + +/** +JPEG-2000 file format reader/writer +*/ +typedef struct opj_jp2 { + /** codec context */ + opj_common_ptr cinfo; + /** handle to the J2K codec */ + opj_j2k_t *j2k; + unsigned int w; + unsigned int h; + unsigned int numcomps; + unsigned int bpc; + unsigned int C; + unsigned int UnkC; + unsigned int IPR; + unsigned int meth; + unsigned int approx; + unsigned int enumcs; + unsigned int precedence; + unsigned int brand; + unsigned int minversion; + unsigned int numcl; + unsigned int *cl; + opj_jp2_comps_t *comps; + unsigned int j2k_codestream_offset; + unsigned int j2k_codestream_length; + opj_bool jpip_on; + opj_bool ignore_pclr_cmap_cdef; +} opj_jp2_t; + +/** +JP2 Box +*/ +typedef struct opj_jp2_box { + int length; + int type; + int init_pos; +} opj_jp2_box_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Write the JP2H box - JP2 Header box (used in MJ2) +@param jp2 JP2 handle +@param cio Output buffer stream +*/ +void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio); +/** +Read the JP2H box - JP2 Header box (used in MJ2) +@param jp2 JP2 handle +@param cio Input buffer stream +@param ext Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color); +/** +Creates a JP2 decompression structure +@param cinfo Codec context info +@return Returns a handle to a JP2 decompressor if successful, returns NULL otherwise +*/ +opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo); +/** +Destroy a JP2 decompressor handle +@param jp2 JP2 decompressor handle to destroy +*/ +void jp2_destroy_decompress(opj_jp2_t *jp2); +/** +Setup the decoder decoding parameters using user parameters. +Decoding parameters are returned in jp2->j2k->cp. +@param jp2 JP2 decompressor handle +@param parameters decompression parameters +*/ +void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters); +/** +Decode an image from a JPEG-2000 file stream +@param jp2 JP2 decompressor handle +@param cio Input buffer stream +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns a decoded image if successful, returns NULL otherwise +*/ +opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info); +/** +Creates a JP2 compression structure +@param cinfo Codec context info +@return Returns a handle to a JP2 compressor if successful, returns NULL otherwise +*/ +opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo); +/** +Destroy a JP2 compressor handle +@param jp2 JP2 compressor handle to destroy +*/ +void jp2_destroy_compress(opj_jp2_t *jp2); +/** +Setup the encoder parameters using the current image and using user parameters. +Coding parameters are returned in jp2->j2k->cp. +@param jp2 JP2 compressor handle +@param parameters compression parameters +@param image input filled image +*/ +void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image); +/** +Encode an image into a JPEG-2000 file stream +@param jp2 JP2 compressor handle +@param cio Output buffer stream +@param image Image to encode +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __JP2_H */ + diff --git a/src/add-ons/translators/icns/openjpeg/jpt.c b/src/add-ons/translators/icns/openjpeg/jpt.c new file mode 100644 index 0000000000..a2566ea887 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/jpt.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/* + * Read the information contains in VBAS [JPP/JPT stream message header] + * Store information (7 bits) in value + * + */ +unsigned int jpt_read_VBAS_info(opj_cio_t *cio, unsigned int value) { + unsigned char elmt; + + elmt = cio_read(cio, 1); + while ((elmt >> 7) == 1) { + value = (value << 7); + value |= (elmt & 0x7f); + elmt = cio_read(cio, 1); + } + value = (value << 7); + value |= (elmt & 0x7f); + + return value; +} + +/* + * Initialize the value of the message header structure + * + */ +void jpt_init_msg_header(opj_jpt_msg_header_t * header) { + header->Id = 0; /* In-class Identifier */ + header->last_byte = 0; /* Last byte information */ + header->Class_Id = 0; /* Class Identifier */ + header->CSn_Id = 0; /* CSn : index identifier */ + header->Msg_offset = 0; /* Message offset */ + header->Msg_length = 0; /* Message length */ + header->Layer_nb = 0; /* Auxiliary for JPP case */ +} + +/* + * Re-initialize the value of the message header structure + * + * Only parameters always present in message header + * + */ +void jpt_reinit_msg_header(opj_jpt_msg_header_t * header) { + header->Id = 0; /* In-class Identifier */ + header->last_byte = 0; /* Last byte information */ + header->Msg_offset = 0; /* Message offset */ + header->Msg_length = 0; /* Message length */ +} + +/* + * Read the message header for a JPP/JPT - stream + * + */ +void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header) { + unsigned char elmt, Class = 0, CSn = 0; + jpt_reinit_msg_header(header); + + /* ------------- */ + /* VBAS : Bin-ID */ + /* ------------- */ + elmt = cio_read(cio, 1); + + /* See for Class and CSn */ + switch ((elmt >> 5) & 0x03) { + case 0: + opj_event_msg(cinfo, EVT_ERROR, "Forbidden value encounter in message header !!\n"); + break; + case 1: + Class = 0; + CSn = 0; + break; + case 2: + Class = 1; + CSn = 0; + break; + case 3: + Class = 1; + CSn = 1; + break; + default: + break; + } + + /* see information on bits 'c' [p 10 : A.2.1 general, ISO/IEC FCD 15444-9] */ + if (((elmt >> 4) & 0x01) == 1) + header->last_byte = 1; + + /* In-class identifier */ + header->Id |= (elmt & 0x0f); + if ((elmt >> 7) == 1) + header->Id = jpt_read_VBAS_info(cio, header->Id); + + /* ------------ */ + /* VBAS : Class */ + /* ------------ */ + if (Class == 1) { + header->Class_Id = 0; + header->Class_Id = jpt_read_VBAS_info(cio, header->Class_Id); + } + + /* ---------- */ + /* VBAS : CSn */ + /* ---------- */ + if (CSn == 1) { + header->CSn_Id = 0; + header->CSn_Id = jpt_read_VBAS_info(cio, header->CSn_Id); + } + + /* ----------------- */ + /* VBAS : Msg_offset */ + /* ----------------- */ + header->Msg_offset = jpt_read_VBAS_info(cio, header->Msg_offset); + + /* ----------------- */ + /* VBAS : Msg_length */ + /* ----------------- */ + header->Msg_length = jpt_read_VBAS_info(cio, header->Msg_length); + + /* ---------- */ + /* VBAS : Aux */ + /* ---------- */ + if ((header->Class_Id & 0x01) == 1) { + header->Layer_nb = 0; + header->Layer_nb = jpt_read_VBAS_info(cio, header->Layer_nb); + } +} diff --git a/src/add-ons/translators/icns/openjpeg/jpt.h b/src/add-ons/translators/icns/openjpeg/jpt.h new file mode 100644 index 0000000000..eb01f98eb8 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/jpt.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __JPT_H +#define __JPT_H +/** +@file jpt.h +@brief JPT-stream reader (JPEG 2000, JPIP) + +JPT-stream functions are implemented in J2K.C. +*/ + +/** +Message Header JPT stream structure +*/ +typedef struct opj_jpt_msg_header { + /** In-class Identifier */ + unsigned int Id; + /** Last byte information */ + unsigned int last_byte; + /** Class Identifier */ + unsigned int Class_Id; + /** CSn : index identifier */ + unsigned int CSn_Id; + /** Message offset */ + unsigned int Msg_offset; + /** Message length */ + unsigned int Msg_length; + /** Auxiliary for JPP case */ + unsigned int Layer_nb; +} opj_jpt_msg_header_t; + +/* ----------------------------------------------------------------------- */ + +/** +Initialize the value of the message header structure +@param header Message header structure +*/ +void jpt_init_msg_header(opj_jpt_msg_header_t * header); + +/** +Read the message header for a JPP/JPT - stream +@param cinfo Codec context info +@param cio CIO handle +@param header Message header structure +*/ +void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header); + +#endif diff --git a/src/add-ons/translators/icns/openjpeg/mct.c b/src/add-ons/translators/icns/openjpeg/mct.c new file mode 100644 index 0000000000..870993b06d --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/mct.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#ifdef __SSE__ +#include +#endif + +#include "opj_includes.h" + +/* */ +/* This table contains the norms of the basis function of the reversible MCT. */ +/* */ +static const double mct_norms[3] = { 1.732, .8292, .8292 }; + +/* */ +/* This table contains the norms of the basis function of the irreversible MCT. */ +/* */ +static const double mct_norms_real[3] = { 1.732, 1.805, 1.573 }; + +/* */ +/* Foward reversible MCT. */ +/* */ +void mct_encode( + int* restrict c0, + int* restrict c1, + int* restrict c2, + int n) +{ + int i; + for(i = 0; i < n; ++i) { + int r = c0[i]; + int g = c1[i]; + int b = c2[i]; + int y = (r + (g * 2) + b) >> 2; + int u = b - g; + int v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} + +/* */ +/* Inverse reversible MCT. */ +/* */ +void mct_decode( + int* restrict c0, + int* restrict c1, + int* restrict c2, + int n) +{ + int i; + for (i = 0; i < n; ++i) { + int y = c0[i]; + int u = c1[i]; + int v = c2[i]; + int g = y - ((u + v) >> 2); + int r = v + g; + int b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} + +/* */ +/* Get norm of basis function of reversible MCT. */ +/* */ +double mct_getnorm(int compno) { + return mct_norms[compno]; +} + +/* */ +/* Foward irreversible MCT. */ +/* */ +void mct_encode_real( + int* restrict c0, + int* restrict c1, + int* restrict c2, + int n) +{ + int i; + for(i = 0; i < n; ++i) { + int r = c0[i]; + int g = c1[i]; + int b = c2[i]; + int y = fix_mul(r, 2449) + fix_mul(g, 4809) + fix_mul(b, 934); + int u = -fix_mul(r, 1382) - fix_mul(g, 2714) + fix_mul(b, 4096); + int v = fix_mul(r, 4096) - fix_mul(g, 3430) - fix_mul(b, 666); + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} + +/* */ +/* Inverse irreversible MCT. */ +/* */ +void mct_decode_real( + float* restrict c0, + float* restrict c1, + float* restrict c2, + int n) +{ + int i; +#ifdef __SSE__ + __m128 vrv, vgu, vgv, vbu; + vrv = _mm_set1_ps(1.402f); + vgu = _mm_set1_ps(0.34413f); + vgv = _mm_set1_ps(0.71414f); + vbu = _mm_set1_ps(1.772f); + for (i = 0; i < (n >> 3); ++i) { + __m128 vy, vu, vv; + __m128 vr, vg, vb; + + vy = _mm_load_ps(c0); + vu = _mm_load_ps(c1); + vv = _mm_load_ps(c2); + vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); + vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); + vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); + _mm_store_ps(c0, vr); + _mm_store_ps(c1, vg); + _mm_store_ps(c2, vb); + c0 += 4; + c1 += 4; + c2 += 4; + + vy = _mm_load_ps(c0); + vu = _mm_load_ps(c1); + vv = _mm_load_ps(c2); + vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); + vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); + vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); + _mm_store_ps(c0, vr); + _mm_store_ps(c1, vg); + _mm_store_ps(c2, vb); + c0 += 4; + c1 += 4; + c2 += 4; + } + n &= 7; +#endif + for(i = 0; i < n; ++i) { + float y = c0[i]; + float u = c1[i]; + float v = c2[i]; + float r = y + (v * 1.402f); + float g = y - (u * 0.34413f) - (v * (0.71414f)); + float b = y + (u * 1.772f); + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} + +/* */ +/* Get norm of basis function of irreversible MCT. */ +/* */ +double mct_getnorm_real(int compno) { + return mct_norms_real[compno]; +} diff --git a/src/add-ons/translators/icns/openjpeg/mct.h b/src/add-ons/translators/icns/openjpeg/mct.h new file mode 100644 index 0000000000..84e3f8add1 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/mct.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __MCT_H +#define __MCT_H +/** +@file mct.h +@brief Implementation of a multi-component transforms (MCT) + +The functions in MCT.C have for goal to realize reversible and irreversible multicomponent +transform. The functions in MCT.C are used by some function in TCD.C. +*/ + +/** @defgroup MCT MCT - Implementation of a multi-component transform */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Apply a reversible multi-component transform to an image +@param c0 Samples for red component +@param c1 Samples for green component +@param c2 Samples blue component +@param n Number of samples for each component +*/ +void mct_encode(int *c0, int *c1, int *c2, int n); +/** +Apply a reversible multi-component inverse transform to an image +@param c0 Samples for luminance component +@param c1 Samples for red chrominance component +@param c2 Samples for blue chrominance component +@param n Number of samples for each component +*/ +void mct_decode(int *c0, int *c1, int *c2, int n); +/** +Get norm of the basis function used for the reversible multi-component transform +@param compno Number of the component (0->Y, 1->U, 2->V) +@return +*/ +double mct_getnorm(int compno); + +/** +Apply an irreversible multi-component transform to an image +@param c0 Samples for red component +@param c1 Samples for green component +@param c2 Samples blue component +@param n Number of samples for each component +*/ +void mct_encode_real(int *c0, int *c1, int *c2, int n); +/** +Apply an irreversible multi-component inverse transform to an image +@param c0 Samples for luminance component +@param c1 Samples for red chrominance component +@param c2 Samples for blue chrominance component +@param n Number of samples for each component +*/ +void mct_decode_real(float* c0, float* c1, float* c2, int n); +/** +Get norm of the basis function used for the irreversible multi-component transform +@param compno Number of the component (0->Y, 1->U, 2->V) +@return +*/ +double mct_getnorm_real(int compno); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __MCT_H */ diff --git a/src/add-ons/translators/icns/openjpeg/mqc.c b/src/add-ons/translators/icns/openjpeg/mqc.c new file mode 100644 index 0000000000..14129fbf4e --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/mqc.c @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/** @defgroup MQC MQC - Implementation of an MQ-Coder */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Output a byte, doing bit-stuffing if necessary. +After a 0xff byte, the next byte must be smaller than 0x90. +@param mqc MQC handle +*/ +static void mqc_byteout(opj_mqc_t *mqc); +/** +Renormalize mqc->a and mqc->c while encoding, so that mqc->a stays between 0x8000 and 0x10000 +@param mqc MQC handle +*/ +static void mqc_renorme(opj_mqc_t *mqc); +/** +Encode the most probable symbol +@param mqc MQC handle +*/ +static void mqc_codemps(opj_mqc_t *mqc); +/** +Encode the most least symbol +@param mqc MQC handle +*/ +static void mqc_codelps(opj_mqc_t *mqc); +/** +Fill mqc->c with 1's for flushing +@param mqc MQC handle +*/ +static void mqc_setbits(opj_mqc_t *mqc); +/** +FIXME: documentation ??? +@param mqc MQC handle +@return +*/ +static INLINE int mqc_mpsexchange(opj_mqc_t *const mqc); +/** +FIXME: documentation ??? +@param mqc MQC handle +@return +*/ +static INLINE int mqc_lpsexchange(opj_mqc_t *const mqc); +/** +Input a byte +@param mqc MQC handle +*/ +static INLINE void mqc_bytein(opj_mqc_t *const mqc); +/** +Renormalize mqc->a and mqc->c while decoding +@param mqc MQC handle +*/ +static INLINE void mqc_renormd(opj_mqc_t *const mqc); +/*@}*/ + +/*@}*/ + +/* */ +/* This array defines all the possible states for a context. */ +/* */ +static opj_mqc_state_t mqc_states[47 * 2] = { + {0x5601, 0, &mqc_states[2], &mqc_states[3]}, + {0x5601, 1, &mqc_states[3], &mqc_states[2]}, + {0x3401, 0, &mqc_states[4], &mqc_states[12]}, + {0x3401, 1, &mqc_states[5], &mqc_states[13]}, + {0x1801, 0, &mqc_states[6], &mqc_states[18]}, + {0x1801, 1, &mqc_states[7], &mqc_states[19]}, + {0x0ac1, 0, &mqc_states[8], &mqc_states[24]}, + {0x0ac1, 1, &mqc_states[9], &mqc_states[25]}, + {0x0521, 0, &mqc_states[10], &mqc_states[58]}, + {0x0521, 1, &mqc_states[11], &mqc_states[59]}, + {0x0221, 0, &mqc_states[76], &mqc_states[66]}, + {0x0221, 1, &mqc_states[77], &mqc_states[67]}, + {0x5601, 0, &mqc_states[14], &mqc_states[13]}, + {0x5601, 1, &mqc_states[15], &mqc_states[12]}, + {0x5401, 0, &mqc_states[16], &mqc_states[28]}, + {0x5401, 1, &mqc_states[17], &mqc_states[29]}, + {0x4801, 0, &mqc_states[18], &mqc_states[28]}, + {0x4801, 1, &mqc_states[19], &mqc_states[29]}, + {0x3801, 0, &mqc_states[20], &mqc_states[28]}, + {0x3801, 1, &mqc_states[21], &mqc_states[29]}, + {0x3001, 0, &mqc_states[22], &mqc_states[34]}, + {0x3001, 1, &mqc_states[23], &mqc_states[35]}, + {0x2401, 0, &mqc_states[24], &mqc_states[36]}, + {0x2401, 1, &mqc_states[25], &mqc_states[37]}, + {0x1c01, 0, &mqc_states[26], &mqc_states[40]}, + {0x1c01, 1, &mqc_states[27], &mqc_states[41]}, + {0x1601, 0, &mqc_states[58], &mqc_states[42]}, + {0x1601, 1, &mqc_states[59], &mqc_states[43]}, + {0x5601, 0, &mqc_states[30], &mqc_states[29]}, + {0x5601, 1, &mqc_states[31], &mqc_states[28]}, + {0x5401, 0, &mqc_states[32], &mqc_states[28]}, + {0x5401, 1, &mqc_states[33], &mqc_states[29]}, + {0x5101, 0, &mqc_states[34], &mqc_states[30]}, + {0x5101, 1, &mqc_states[35], &mqc_states[31]}, + {0x4801, 0, &mqc_states[36], &mqc_states[32]}, + {0x4801, 1, &mqc_states[37], &mqc_states[33]}, + {0x3801, 0, &mqc_states[38], &mqc_states[34]}, + {0x3801, 1, &mqc_states[39], &mqc_states[35]}, + {0x3401, 0, &mqc_states[40], &mqc_states[36]}, + {0x3401, 1, &mqc_states[41], &mqc_states[37]}, + {0x3001, 0, &mqc_states[42], &mqc_states[38]}, + {0x3001, 1, &mqc_states[43], &mqc_states[39]}, + {0x2801, 0, &mqc_states[44], &mqc_states[38]}, + {0x2801, 1, &mqc_states[45], &mqc_states[39]}, + {0x2401, 0, &mqc_states[46], &mqc_states[40]}, + {0x2401, 1, &mqc_states[47], &mqc_states[41]}, + {0x2201, 0, &mqc_states[48], &mqc_states[42]}, + {0x2201, 1, &mqc_states[49], &mqc_states[43]}, + {0x1c01, 0, &mqc_states[50], &mqc_states[44]}, + {0x1c01, 1, &mqc_states[51], &mqc_states[45]}, + {0x1801, 0, &mqc_states[52], &mqc_states[46]}, + {0x1801, 1, &mqc_states[53], &mqc_states[47]}, + {0x1601, 0, &mqc_states[54], &mqc_states[48]}, + {0x1601, 1, &mqc_states[55], &mqc_states[49]}, + {0x1401, 0, &mqc_states[56], &mqc_states[50]}, + {0x1401, 1, &mqc_states[57], &mqc_states[51]}, + {0x1201, 0, &mqc_states[58], &mqc_states[52]}, + {0x1201, 1, &mqc_states[59], &mqc_states[53]}, + {0x1101, 0, &mqc_states[60], &mqc_states[54]}, + {0x1101, 1, &mqc_states[61], &mqc_states[55]}, + {0x0ac1, 0, &mqc_states[62], &mqc_states[56]}, + {0x0ac1, 1, &mqc_states[63], &mqc_states[57]}, + {0x09c1, 0, &mqc_states[64], &mqc_states[58]}, + {0x09c1, 1, &mqc_states[65], &mqc_states[59]}, + {0x08a1, 0, &mqc_states[66], &mqc_states[60]}, + {0x08a1, 1, &mqc_states[67], &mqc_states[61]}, + {0x0521, 0, &mqc_states[68], &mqc_states[62]}, + {0x0521, 1, &mqc_states[69], &mqc_states[63]}, + {0x0441, 0, &mqc_states[70], &mqc_states[64]}, + {0x0441, 1, &mqc_states[71], &mqc_states[65]}, + {0x02a1, 0, &mqc_states[72], &mqc_states[66]}, + {0x02a1, 1, &mqc_states[73], &mqc_states[67]}, + {0x0221, 0, &mqc_states[74], &mqc_states[68]}, + {0x0221, 1, &mqc_states[75], &mqc_states[69]}, + {0x0141, 0, &mqc_states[76], &mqc_states[70]}, + {0x0141, 1, &mqc_states[77], &mqc_states[71]}, + {0x0111, 0, &mqc_states[78], &mqc_states[72]}, + {0x0111, 1, &mqc_states[79], &mqc_states[73]}, + {0x0085, 0, &mqc_states[80], &mqc_states[74]}, + {0x0085, 1, &mqc_states[81], &mqc_states[75]}, + {0x0049, 0, &mqc_states[82], &mqc_states[76]}, + {0x0049, 1, &mqc_states[83], &mqc_states[77]}, + {0x0025, 0, &mqc_states[84], &mqc_states[78]}, + {0x0025, 1, &mqc_states[85], &mqc_states[79]}, + {0x0015, 0, &mqc_states[86], &mqc_states[80]}, + {0x0015, 1, &mqc_states[87], &mqc_states[81]}, + {0x0009, 0, &mqc_states[88], &mqc_states[82]}, + {0x0009, 1, &mqc_states[89], &mqc_states[83]}, + {0x0005, 0, &mqc_states[90], &mqc_states[84]}, + {0x0005, 1, &mqc_states[91], &mqc_states[85]}, + {0x0001, 0, &mqc_states[90], &mqc_states[86]}, + {0x0001, 1, &mqc_states[91], &mqc_states[87]}, + {0x5601, 0, &mqc_states[92], &mqc_states[92]}, + {0x5601, 1, &mqc_states[93], &mqc_states[93]}, +}; + +/* +========================================================== + local functions +========================================================== +*/ + +static void mqc_byteout(opj_mqc_t *mqc) { + if (*mqc->bp == 0xff) { + mqc->bp++; + *mqc->bp = mqc->c >> 20; + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + if ((mqc->c & 0x8000000) == 0) { /* ((mqc->c&0x8000000)==0) CHANGE */ + mqc->bp++; + *mqc->bp = mqc->c >> 19; + mqc->c &= 0x7ffff; + mqc->ct = 8; + } else { + (*mqc->bp)++; + if (*mqc->bp == 0xff) { + mqc->c &= 0x7ffffff; + mqc->bp++; + *mqc->bp = mqc->c >> 20; + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + mqc->bp++; + *mqc->bp = mqc->c >> 19; + mqc->c &= 0x7ffff; + mqc->ct = 8; + } + } + } +} + +static void mqc_renorme(opj_mqc_t *mqc) { + do { + mqc->a <<= 1; + mqc->c <<= 1; + mqc->ct--; + if (mqc->ct == 0) { + mqc_byteout(mqc); + } + } while ((mqc->a & 0x8000) == 0); +} + +static void mqc_codemps(opj_mqc_t *mqc) { + mqc->a -= (*mqc->curctx)->qeval; + if ((mqc->a & 0x8000) == 0) { + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->a = (*mqc->curctx)->qeval; + } else { + mqc->c += (*mqc->curctx)->qeval; + } + *mqc->curctx = (*mqc->curctx)->nmps; + mqc_renorme(mqc); + } else { + mqc->c += (*mqc->curctx)->qeval; + } +} + +static void mqc_codelps(opj_mqc_t *mqc) { + mqc->a -= (*mqc->curctx)->qeval; + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->c += (*mqc->curctx)->qeval; + } else { + mqc->a = (*mqc->curctx)->qeval; + } + *mqc->curctx = (*mqc->curctx)->nlps; + mqc_renorme(mqc); +} + +static void mqc_setbits(opj_mqc_t *mqc) { + unsigned int tempc = mqc->c + mqc->a; + mqc->c |= 0xffff; + if (mqc->c >= tempc) { + mqc->c -= 0x8000; + } +} + +static INLINE int mqc_mpsexchange(opj_mqc_t *const mqc) { + int d; + if (mqc->a < (*mqc->curctx)->qeval) { + d = 1 - (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nlps; + } else { + d = (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nmps; + } + + return d; +} + +static INLINE int mqc_lpsexchange(opj_mqc_t *const mqc) { + int d; + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->a = (*mqc->curctx)->qeval; + d = (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nmps; + } else { + mqc->a = (*mqc->curctx)->qeval; + d = 1 - (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nlps; + } + + return d; +} + +#ifdef MQC_PERF_OPT +static INLINE void mqc_bytein(opj_mqc_t *const mqc) { + unsigned int i = *((unsigned int *) mqc->bp); + mqc->c += i & 0xffff00; + mqc->ct = i & 0x0f; + mqc->bp += (i >> 2) & 0x04; +} +#else +static void mqc_bytein(opj_mqc_t *const mqc) { + if (mqc->bp != mqc->end) { + unsigned int c; + if (mqc->bp + 1 != mqc->end) { + c = *(mqc->bp + 1); + } else { + c = 0xff; + } + if (*mqc->bp == 0xff) { + if (c > 0x8f) { + mqc->c += 0xff00; + mqc->ct = 8; + } else { + mqc->bp++; + mqc->c += c << 9; + mqc->ct = 7; + } + } else { + mqc->bp++; + mqc->c += c << 8; + mqc->ct = 8; + } + } else { + mqc->c += 0xff00; + mqc->ct = 8; + } +} +#endif + +static INLINE void mqc_renormd(opj_mqc_t *const mqc) { + do { + if (mqc->ct == 0) { + mqc_bytein(mqc); + } + mqc->a <<= 1; + mqc->c <<= 1; + mqc->ct--; + } while (mqc->a < 0x8000); +} + +/* +========================================================== + MQ-Coder interface +========================================================== +*/ + +opj_mqc_t* mqc_create(void) { + opj_mqc_t *mqc = (opj_mqc_t*)opj_malloc(sizeof(opj_mqc_t)); +#ifdef MQC_PERF_OPT + mqc->buffer = NULL; +#endif + return mqc; +} + +void mqc_destroy(opj_mqc_t *mqc) { + if(mqc) { +#ifdef MQC_PERF_OPT + if (mqc->buffer) { + opj_free(mqc->buffer); + } +#endif + opj_free(mqc); + } +} + +int mqc_numbytes(opj_mqc_t *mqc) { + return mqc->bp - mqc->start; +} + +void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp) { + mqc_setcurctx(mqc, 0); + mqc->a = 0x8000; + mqc->c = 0; + mqc->bp = bp - 1; + mqc->ct = 12; + if (*mqc->bp == 0xff) { + mqc->ct = 13; + } + mqc->start = bp; +} + +void mqc_encode(opj_mqc_t *mqc, int d) { + if ((*mqc->curctx)->mps == d) { + mqc_codemps(mqc); + } else { + mqc_codelps(mqc); + } +} + +void mqc_flush(opj_mqc_t *mqc) { + mqc_setbits(mqc); + mqc->c <<= mqc->ct; + mqc_byteout(mqc); + mqc->c <<= mqc->ct; + mqc_byteout(mqc); + + if (*mqc->bp != 0xff) { + mqc->bp++; + } +} + +void mqc_bypass_init_enc(opj_mqc_t *mqc) { + mqc->c = 0; + mqc->ct = 8; + /*if (*mqc->bp == 0xff) { + mqc->ct = 7; + } */ +} + +void mqc_bypass_enc(opj_mqc_t *mqc, int d) { + mqc->ct--; + mqc->c = mqc->c + (d << mqc->ct); + if (mqc->ct == 0) { + mqc->bp++; + *mqc->bp = mqc->c; + mqc->ct = 8; + if (*mqc->bp == 0xff) { + mqc->ct = 7; + } + mqc->c = 0; + } +} + +int mqc_bypass_flush_enc(opj_mqc_t *mqc) { + unsigned char bit_padding; + + bit_padding = 0; + + if (mqc->ct != 0) { + while (mqc->ct > 0) { + mqc->ct--; + mqc->c += bit_padding << mqc->ct; + bit_padding = (bit_padding + 1) & 0x01; + } + mqc->bp++; + *mqc->bp = mqc->c; + mqc->ct = 8; + mqc->c = 0; + } + + return 1; +} + +void mqc_reset_enc(opj_mqc_t *mqc) { + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); +} + +int mqc_restart_enc(opj_mqc_t *mqc) { + int correction = 1; + + /* */ + int n = 27 - 15 - mqc->ct; + mqc->c <<= mqc->ct; + while (n > 0) { + mqc_byteout(mqc); + n -= mqc->ct; + mqc->c <<= mqc->ct; + } + mqc_byteout(mqc); + + return correction; +} + +void mqc_restart_init_enc(opj_mqc_t *mqc) { + /* */ + mqc_setcurctx(mqc, 0); + mqc->a = 0x8000; + mqc->c = 0; + mqc->ct = 12; + mqc->bp--; + if (*mqc->bp == 0xff) { + mqc->ct = 13; + } +} + +void mqc_erterm_enc(opj_mqc_t *mqc) { + int k = 11 - mqc->ct + 1; + + while (k > 0) { + mqc->c <<= mqc->ct; + mqc->ct = 0; + mqc_byteout(mqc); + k -= mqc->ct; + } + + if (*mqc->bp != 0xff) { + mqc_byteout(mqc); + } +} + +void mqc_segmark_enc(opj_mqc_t *mqc) { + int i; + mqc_setcurctx(mqc, 18); + + for (i = 1; i < 5; i++) { + mqc_encode(mqc, i % 2); + } +} + +void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len) { + mqc_setcurctx(mqc, 0); + mqc->start = bp; + mqc->end = bp + len; + mqc->bp = bp; + if (len==0) mqc->c = 0xff << 16; + else mqc->c = *mqc->bp << 16; + +#ifdef MQC_PERF_OPT + { + unsigned int c; + unsigned int *ip; + unsigned char *end = mqc->end - 1; + mqc->buffer = opj_realloc(mqc->buffer, (len + 1) * sizeof(unsigned int)); + ip = (unsigned int *) mqc->buffer; + + while (bp < end) { + c = *(bp + 1); + if (*bp == 0xff) { + if (c > 0x8f) { + break; + } else { + *ip = 0x00000017 | (c << 9); + } + } else { + *ip = 0x00000018 | (c << 8); + } + bp++; + ip++; + } + + /* Handle last byte of data */ + c = 0xff; + if (*bp == 0xff) { + *ip = 0x0000ff18; + } else { + bp++; + *ip = 0x00000018 | (c << 8); + } + ip++; + + *ip = 0x0000ff08; + mqc->bp = mqc->buffer; + } +#endif + mqc_bytein(mqc); + mqc->c <<= 7; + mqc->ct -= 7; + mqc->a = 0x8000; +} + +int mqc_decode(opj_mqc_t *const mqc) { + int d; + mqc->a -= (*mqc->curctx)->qeval; + if ((mqc->c >> 16) < (*mqc->curctx)->qeval) { + d = mqc_lpsexchange(mqc); + mqc_renormd(mqc); + } else { + mqc->c -= (*mqc->curctx)->qeval << 16; + if ((mqc->a & 0x8000) == 0) { + d = mqc_mpsexchange(mqc); + mqc_renormd(mqc); + } else { + d = (*mqc->curctx)->mps; + } + } + + return d; +} + +void mqc_resetstates(opj_mqc_t *mqc) { + int i; + for (i = 0; i < MQC_NUMCTXS; i++) { + mqc->ctxs[i] = mqc_states; + } +} + +void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob) { + mqc->ctxs[ctxno] = &mqc_states[msb + (prob << 1)]; +} + + diff --git a/src/add-ons/translators/icns/openjpeg/mqc.h b/src/add-ons/translators/icns/openjpeg/mqc.h new file mode 100644 index 0000000000..d00cd1067d --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/mqc.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __MQC_H +#define __MQC_H +/** +@file mqc.h +@brief Implementation of an MQ-Coder (MQC) + +The functions in MQC.C have for goal to realize the MQ-coder operations. The functions +in MQC.C are used by some function in T1.C. +*/ + +/** @defgroup MQC MQC - Implementation of an MQ-Coder */ +/*@{*/ + +/** +This struct defines the state of a context. +*/ +typedef struct opj_mqc_state { + /** the probability of the Least Probable Symbol (0.75->0x8000, 1.5->0xffff) */ + unsigned int qeval; + /** the Most Probable Symbol (0 or 1) */ + int mps; + /** next state if the next encoded symbol is the MPS */ + struct opj_mqc_state *nmps; + /** next state if the next encoded symbol is the LPS */ + struct opj_mqc_state *nlps; +} opj_mqc_state_t; + +#define MQC_NUMCTXS 19 + +/** +MQ coder +*/ +typedef struct opj_mqc { + unsigned int c; + unsigned int a; + unsigned int ct; + unsigned char *bp; + unsigned char *start; + unsigned char *end; + opj_mqc_state_t *ctxs[MQC_NUMCTXS]; + opj_mqc_state_t **curctx; +#ifdef MQC_PERF_OPT + unsigned char *buffer; +#endif +} opj_mqc_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new MQC handle +@return Returns a new MQC handle if successful, returns NULL otherwise +*/ +opj_mqc_t* mqc_create(void); +/** +Destroy a previously created MQC handle +@param mqc MQC handle to destroy +*/ +void mqc_destroy(opj_mqc_t *mqc); +/** +Return the number of bytes written/read since initialisation +@param mqc MQC handle +@return Returns the number of bytes already encoded +*/ +int mqc_numbytes(opj_mqc_t *mqc); +/** +Reset the states of all the context of the coder/decoder +(each context is set to a state where 0 and 1 are more or less equiprobable) +@param mqc MQC handle +*/ +void mqc_resetstates(opj_mqc_t *mqc); +/** +Set the state of a particular context +@param mqc MQC handle +@param ctxno Number that identifies the context +@param msb The MSB of the new state of the context +@param prob Number that identifies the probability of the symbols for the new state of the context +*/ +void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob); +/** +Initialize the encoder +@param mqc MQC handle +@param bp Pointer to the start of the buffer where the bytes will be written +*/ +void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp); +/** +Set the current context used for coding/decoding +@param mqc MQC handle +@param ctxno Number that identifies the context +*/ +#define mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(int)(ctxno)] +/** +Encode a symbol using the MQ-coder +@param mqc MQC handle +@param d The symbol to be encoded (0 or 1) +*/ +void mqc_encode(opj_mqc_t *mqc, int d); +/** +Flush the encoder, so that all remaining data is written +@param mqc MQC handle +*/ +void mqc_flush(opj_mqc_t *mqc); +/** +BYPASS mode switch, initialization operation. +JPEG 2000 p 505. +

Not fully implemented and tested !!

+@param mqc MQC handle +*/ +void mqc_bypass_init_enc(opj_mqc_t *mqc); +/** +BYPASS mode switch, coding operation. +JPEG 2000 p 505. +

Not fully implemented and tested !!

+@param mqc MQC handle +@param d The symbol to be encoded (0 or 1) +*/ +void mqc_bypass_enc(opj_mqc_t *mqc, int d); +/** +BYPASS mode switch, flush operation +

Not fully implemented and tested !!

+@param mqc MQC handle +@return Returns 1 (always) +*/ +int mqc_bypass_flush_enc(opj_mqc_t *mqc); +/** +RESET mode switch +@param mqc MQC handle +*/ +void mqc_reset_enc(opj_mqc_t *mqc); +/** +RESTART mode switch (TERMALL) +@param mqc MQC handle +@return Returns 1 (always) +*/ +int mqc_restart_enc(opj_mqc_t *mqc); +/** +RESTART mode switch (TERMALL) reinitialisation +@param mqc MQC handle +*/ +void mqc_restart_init_enc(opj_mqc_t *mqc); +/** +ERTERM mode switch (PTERM) +@param mqc MQC handle +*/ +void mqc_erterm_enc(opj_mqc_t *mqc); +/** +SEGMARK mode switch (SEGSYM) +@param mqc MQC handle +*/ +void mqc_segmark_enc(opj_mqc_t *mqc); +/** +Initialize the decoder +@param mqc MQC handle +@param bp Pointer to the start of the buffer from which the bytes will be read +@param len Length of the input buffer +*/ +void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len); +/** +Decode a symbol +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) +*/ +int mqc_decode(opj_mqc_t *const mqc); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __MQC_H */ diff --git a/src/add-ons/translators/icns/openjpeg/oj_image.h b/src/add-ons/translators/icns/openjpeg/oj_image.h new file mode 100644 index 0000000000..f828b5b77c --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/oj_image.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __IMAGE_H +#define __IMAGE_H +/** +@file image.h +@brief Implementation of operations on images (IMAGE) + +The functions in IMAGE.C have for goal to realize operations on images. +*/ + +/** @defgroup IMAGE IMAGE - Implementation of operations on images */ +/*@{*/ + +/** +Create an empty image +@todo this function should be removed +@return returns an empty image if successful, returns NULL otherwise +*/ +opj_image_t* opj_image_create0(void); + +/*@}*/ + +#endif /* __IMAGE_H */ + diff --git a/src/add-ons/translators/icns/openjpeg/openjpeg.c b/src/add-ons/translators/icns/openjpeg/openjpeg.c new file mode 100644 index 0000000000..180cc844ab --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/openjpeg.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#ifdef _WIN32 +#include +#endif /* _WIN32 */ + +#include "opj_config.h" +#include "opj_includes.h" + +/* ---------------------------------------------------------------------- */ +#ifdef _WIN32 +#ifndef OPJ_STATIC +BOOL APIENTRY +DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + + OPJ_ARG_NOT_USED(lpReserved); + OPJ_ARG_NOT_USED(hModule); + + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH : + break; + case DLL_PROCESS_DETACH : + break; + case DLL_THREAD_ATTACH : + case DLL_THREAD_DETACH : + break; + } + + return TRUE; +} +#endif /* OPJ_STATIC */ +#endif /* _WIN32 */ + +/* ---------------------------------------------------------------------- */ + + +const char* OPJ_CALLCONV opj_version(void) { + return PACKAGE_VERSION; +} + +opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format) { + opj_dinfo_t *dinfo = (opj_dinfo_t*)opj_calloc(1, sizeof(opj_dinfo_t)); + if(!dinfo) return NULL; + dinfo->is_decompressor = OPJ_TRUE; + switch(format) { + case CODEC_J2K: + case CODEC_JPT: + /* get a J2K decoder handle */ + dinfo->j2k_handle = (void*)j2k_create_decompress((opj_common_ptr)dinfo); + if(!dinfo->j2k_handle) { + opj_free(dinfo); + return NULL; + } + break; + case CODEC_JP2: + /* get a JP2 decoder handle */ + dinfo->jp2_handle = (void*)jp2_create_decompress((opj_common_ptr)dinfo); + if(!dinfo->jp2_handle) { + opj_free(dinfo); + return NULL; + } + break; + case CODEC_UNKNOWN: + default: + opj_free(dinfo); + return NULL; + } + + dinfo->codec_format = format; + + return dinfo; +} + +void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo) { + if(dinfo) { + /* destroy the codec */ + switch(dinfo->codec_format) { + case CODEC_J2K: + case CODEC_JPT: + j2k_destroy_decompress((opj_j2k_t*)dinfo->j2k_handle); + break; + case CODEC_JP2: + jp2_destroy_decompress((opj_jp2_t*)dinfo->jp2_handle); + break; + case CODEC_UNKNOWN: + default: + break; + } + /* destroy the decompressor */ + opj_free(dinfo); + } +} + +void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters) { + if(parameters) { + memset(parameters, 0, sizeof(opj_dparameters_t)); + /* default decoding parameters */ + parameters->cp_layer = 0; + parameters->cp_reduce = 0; + parameters->cp_limit_decoding = NO_LIMITATION; + + parameters->decod_format = -1; + parameters->cod_format = -1; + parameters->flags = 0; +/* UniPG>> */ +#ifdef USE_JPWL + parameters->jpwl_correct = OPJ_FALSE; + parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS; + parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES; +#endif /* USE_JPWL */ +/* <codec_format) { + case CODEC_J2K: + case CODEC_JPT: + j2k_setup_decoder((opj_j2k_t*)dinfo->j2k_handle, parameters); + break; + case CODEC_JP2: + jp2_setup_decoder((opj_jp2_t*)dinfo->jp2_handle, parameters); + break; + case CODEC_UNKNOWN: + default: + break; + } + } +} + +opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio) { + return opj_decode_with_info(dinfo, cio, NULL); +} + +opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *cio, opj_codestream_info_t *cstr_info) { + if(dinfo && cio) { + switch(dinfo->codec_format) { + case CODEC_J2K: + return j2k_decode((opj_j2k_t*)dinfo->j2k_handle, cio, cstr_info); + case CODEC_JPT: + return j2k_decode_jpt_stream((opj_j2k_t*)dinfo->j2k_handle, cio, cstr_info); + case CODEC_JP2: + return opj_jp2_decode((opj_jp2_t*)dinfo->jp2_handle, cio, cstr_info); + case CODEC_UNKNOWN: + default: + break; + } + } + return NULL; +} + +opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format) { + opj_cinfo_t *cinfo = (opj_cinfo_t*)opj_calloc(1, sizeof(opj_cinfo_t)); + if(!cinfo) return NULL; + cinfo->is_decompressor = OPJ_FALSE; + switch(format) { + case CODEC_J2K: + /* get a J2K coder handle */ + cinfo->j2k_handle = (void*)j2k_create_compress((opj_common_ptr)cinfo); + if(!cinfo->j2k_handle) { + opj_free(cinfo); + return NULL; + } + break; + case CODEC_JP2: + /* get a JP2 coder handle */ + cinfo->jp2_handle = (void*)jp2_create_compress((opj_common_ptr)cinfo); + if(!cinfo->jp2_handle) { + opj_free(cinfo); + return NULL; + } + break; + case CODEC_JPT: + case CODEC_UNKNOWN: + default: + opj_free(cinfo); + return NULL; + } + + cinfo->codec_format = format; + + return cinfo; +} + +void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo) { + if(cinfo) { + /* destroy the codec */ + switch(cinfo->codec_format) { + case CODEC_J2K: + j2k_destroy_compress((opj_j2k_t*)cinfo->j2k_handle); + break; + case CODEC_JP2: + jp2_destroy_compress((opj_jp2_t*)cinfo->jp2_handle); + break; + case CODEC_JPT: + case CODEC_UNKNOWN: + default: + break; + } + /* destroy the decompressor */ + opj_free(cinfo); + } +} + +void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters) { + if(parameters) { + memset(parameters, 0, sizeof(opj_cparameters_t)); + /* default coding parameters */ + parameters->cp_cinema = OFF; + parameters->max_comp_size = 0; + parameters->numresolution = 6; + parameters->cp_rsiz = STD_RSIZ; + parameters->cblockw_init = 64; + parameters->cblockh_init = 64; + parameters->prog_order = LRCP; + parameters->roi_compno = -1; /* no ROI */ + parameters->subsampling_dx = 1; + parameters->subsampling_dy = 1; + parameters->tp_on = 0; + parameters->decod_format = -1; + parameters->cod_format = -1; + parameters->tcp_rates[0] = 0; + parameters->tcp_numlayers = 0; + parameters->cp_disto_alloc = 0; + parameters->cp_fixed_alloc = 0; + parameters->cp_fixed_quality = 0; + parameters->jpip_on = OPJ_FALSE; +/* UniPG>> */ +#ifdef USE_JPWL + parameters->jpwl_epc_on = OPJ_FALSE; + parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_hprot_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_hprot_TPH[i] = 0; /* absent */ + } + }; + { + int i; + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + parameters->jpwl_pprot_tileno[i] = -1; /* unassigned */ + parameters->jpwl_pprot_packno[i] = -1; /* unassigned */ + parameters->jpwl_pprot[i] = 0; /* absent */ + } + }; + parameters->jpwl_sens_size = 0; /* 0 means no ESD */ + parameters->jpwl_sens_addr = 0; /* 0 means auto */ + parameters->jpwl_sens_range = 0; /* 0 means packet */ + parameters->jpwl_sens_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_sens_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_sens_TPH[i] = -1; /* absent */ + } + }; +#endif /* USE_JPWL */ +/* <codec_format) { + case CODEC_J2K: + j2k_setup_encoder((opj_j2k_t*)cinfo->j2k_handle, parameters, image); + break; + case CODEC_JP2: + jp2_setup_encoder((opj_jp2_t*)cinfo->jp2_handle, parameters, image); + break; + case CODEC_JPT: + case CODEC_UNKNOWN: + default: + break; + } + } +} + +opj_bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) { + if (index != NULL) + opj_event_msg((opj_common_ptr)cinfo, EVT_WARNING, "Set index to NULL when calling the opj_encode function.\n" + "To extract the index, use the opj_encode_with_info() function.\n" + "No index will be generated during this encoding\n"); + return opj_encode_with_info(cinfo, cio, image, NULL); +} + +opj_bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { + if(cinfo && cio && image) { + switch(cinfo->codec_format) { + case CODEC_J2K: + return j2k_encode((opj_j2k_t*)cinfo->j2k_handle, cio, image, cstr_info); + case CODEC_JP2: + return opj_jp2_encode((opj_jp2_t*)cinfo->jp2_handle, cio, image, cstr_info); + case CODEC_JPT: + case CODEC_UNKNOWN: + default: + break; + } + } + return OPJ_FALSE; +} + +void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) { + if (cstr_info) { + int tileno; + for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) { + opj_tile_info_t *tile_info = &cstr_info->tile[tileno]; + opj_free(tile_info->thresh); + opj_free(tile_info->packet); + opj_free(tile_info->tp); + opj_free(tile_info->marker); + } + opj_free(cstr_info->tile); + opj_free(cstr_info->marker); + opj_free(cstr_info->numdecompos); + } +} diff --git a/src/add-ons/translators/icns/openjpeg/openjpeg.h b/src/add-ons/translators/icns/openjpeg/openjpeg.h new file mode 100644 index 0000000000..59147c8b3d --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/openjpeg.h @@ -0,0 +1,914 @@ + /* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 OPENJPEG_H +#define OPENJPEG_H + + +/* +========================================================== + Compiler directives +========================================================== +*/ + +#if defined(OPJ_STATIC) || !defined(_WIN32) +#define OPJ_API +#define OPJ_CALLCONV +#else +#define OPJ_CALLCONV __stdcall +/* +The following ifdef block is the standard way of creating macros which make exporting +from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS +symbol defined on the command line. this symbol should not be defined on any project +that uses this DLL. This way any other project whose source files include this file see +OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols +defined with this macro as being exported. +*/ +#if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) +#define OPJ_API __declspec(dllexport) +#else +#define OPJ_API __declspec(dllimport) +#endif /* OPJ_EXPORTS */ +#endif /* !OPJ_STATIC || !_WIN32 */ + +typedef int opj_bool; +#define OPJ_TRUE 1 +#define OPJ_FALSE 0 + +/* Avoid compile-time warning because parameter is not used */ +#define OPJ_ARG_NOT_USED(x) (void)(x) +/* +========================================================== + Useful constant definitions +========================================================== +*/ + +#define OPJ_PATH_LEN 4096 /**< Maximum allowed size for filenames */ + +#define J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */ +#define J2K_MAXBANDS (3*J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */ + +/* UniPG>> */ +#define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_MARKERS 512 /**< Maximum number of JPWL markers: increase at your will */ +#define JPWL_PRIVATEINDEX_NAME "jpwl_index_privatefilename" /**< index file name used when JPWL is on */ +#define JPWL_EXPECTED_COMPONENTS 3 /**< Expect this number of components, so you'll find better the first EPB */ +#define JPWL_MAXIMUM_TILES 8192 /**< Expect this maximum number of tiles, to avoid some crashes */ +#define JPWL_MAXIMUM_HAMMING 2 /**< Expect this maximum number of bit errors in marker id's */ +#define JPWL_MAXIMUM_EPB_ROOM 65450 /**< Expect this maximum number of bytes for composition of EPBs */ +/* < +
  • Error messages +
  • Warning messages +
  • Debugging messages + +*/ +typedef struct opj_event_mgr { + /** Error message callback if available, NULL otherwise */ + opj_msg_callback error_handler; + /** Warning message callback if available, NULL otherwise */ + opj_msg_callback warning_handler; + /** Debug message callback if available, NULL otherwise */ + opj_msg_callback info_handler; +} opj_event_mgr_t; + + +/* +========================================================== + codec typedef definitions +========================================================== +*/ + +/** +Progression order changes +*/ +typedef struct opj_poc { + /** Resolution num start, Component num start, given by POC */ + int resno0, compno0; + /** Layer num end,Resolution num end, Component num end, given by POC */ + int layno1, resno1, compno1; + /** Layer num start,Precinct num start, Precinct num end */ + int layno0, precno0, precno1; + /** Progression order enum*/ + OPJ_PROG_ORDER prg1,prg; + /** Progression order string*/ + char progorder[5]; + /** Tile number */ + int tile; + /** Start and end values for Tile width and height*/ + int tx0,tx1,ty0,ty1; + /** Start value, initialised in pi_initialise_encode*/ + int layS, resS, compS, prcS; + /** End value, initialised in pi_initialise_encode */ + int layE, resE, compE, prcE; + /** Start and end values of Tile width and height, initialised in pi_initialise_encode*/ + int txS,txE,tyS,tyE,dx,dy; + /** Temporary values for Tile parts, initialised in pi_create_encode */ + int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t; +} opj_poc_t; + +/** +Compression parameters +*/ +typedef struct opj_cparameters { + /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */ + opj_bool tile_size_on; + /** XTOsiz */ + int cp_tx0; + /** YTOsiz */ + int cp_ty0; + /** XTsiz */ + int cp_tdx; + /** YTsiz */ + int cp_tdy; + /** allocation by rate/distortion */ + int cp_disto_alloc; + /** allocation by fixed layer */ + int cp_fixed_alloc; + /** add fixed_quality */ + int cp_fixed_quality; + /** fixed layer */ + int *cp_matrice; + /** comment for coding */ + char *cp_comment; + /** csty : coding style */ + int csty; + /** progression order (default LRCP) */ + OPJ_PROG_ORDER prog_order; + /** progression order changes */ + opj_poc_t POC[32]; + /** number of progression order changes (POC), default to 0 */ + int numpocs; + /** number of layers */ + int tcp_numlayers; + /** rates of layers */ + float tcp_rates[100]; + /** different psnr for successive layers */ + float tcp_distoratio[100]; + /** number of resolutions */ + int numresolution; + /** initial code block width, default to 64 */ + int cblockw_init; + /** initial code block height, default to 64 */ + int cblockh_init; + /** mode switch (cblk_style) */ + int mode; + /** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */ + int irreversible; + /** region of interest: affected component in [0..3], -1 means no ROI */ + int roi_compno; + /** region of interest: upshift value */ + int roi_shift; + /* number of precinct size specifications */ + int res_spec; + /** initial precinct width */ + int prcw_init[J2K_MAXRLVLS]; + /** initial precinct height */ + int prch_init[J2K_MAXRLVLS]; + + /**@name command line encoder parameters (not used inside the library) */ + /*@{*/ + /** input file name */ + char infile[OPJ_PATH_LEN]; + /** output file name */ + char outfile[OPJ_PATH_LEN]; + /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */ + int index_on; + /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */ + char index[OPJ_PATH_LEN]; + /** subimage encoding: origin image offset in x direction */ + int image_offset_x0; + /** subimage encoding: origin image offset in y direction */ + int image_offset_y0; + /** subsampling value for dx */ + int subsampling_dx; + /** subsampling value for dy */ + int subsampling_dy; + /** input file format 0: PGX, 1: PxM, 2: BMP 3:TIF*/ + int decod_format; + /** output file format 0: J2K, 1: JP2, 2: JPT */ + int cod_format; + /*@}*/ + +/* UniPG>> */ + /**@name JPWL encoding parameters */ + /*@{*/ + /** enables writing of EPC in MH, thus activating JPWL */ + opj_bool jpwl_epc_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int jpwl_hprot_MH; + /** tile number of header protection specification (>=0) */ + int jpwl_hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int jpwl_hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int jpwl_pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int jpwl_pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int jpwl_pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0=no/1/2 bytes) */ + int jpwl_sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int jpwl_sens_addr; + /** sensitivity range (0-3) */ + int jpwl_sens_range; + /** sensitivity method for MH (-1=no,0-7) */ + int jpwl_sens_MH; + /** tile number of sensitivity specification (>=0) */ + int jpwl_sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1=no,0-7) */ + int jpwl_sens_TPH[JPWL_MAX_NO_TILESPECS]; + /*@}*/ +/* <> */ + /**@name JPWL decoding parameters */ + /*@{*/ + /** activates the JPWL correction capabilities */ + opj_bool jpwl_correct; + /** expected number of components */ + int jpwl_exp_comps; + /** maximum number of tiles */ + int jpwl_max_tiles; + /*@}*/ +/* <> */ +/** +Marker structure +*/ +typedef struct opj_marker_info_t { + /** marker type */ + unsigned short int type; + /** position in codestream */ + int pos; + /** length, marker val included */ + int len; +} opj_marker_info_t; +/* <> */ + /** number of markers */ + int marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + int maxmarknum; +/* <cp. +@param dinfo decompressor handle +@param parameters decompression parameters +*/ +OPJ_API void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters); +/** +Decode an image from a JPEG-2000 codestream +@param dinfo decompressor handle +@param cio Input buffer stream +@return Returns a decoded image if successful, returns NULL otherwise +*/ +OPJ_API opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio); + +/** +Decode an image from a JPEG-2000 codestream and extract the codestream information +@param dinfo decompressor handle +@param cio Input buffer stream +@param cstr_info Codestream information structure if needed afterwards, NULL otherwise +@return Returns a decoded image if successful, returns NULL otherwise +*/ +OPJ_API opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *cio, opj_codestream_info_t *cstr_info); +/** +Creates a J2K/JP2 compression structure +@param format Coder to select +@return Returns a handle to a compressor if successful, returns NULL otherwise +*/ +OPJ_API opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format); +/** +Destroy a compressor handle +@param cinfo compressor handle to destroy +*/ +OPJ_API void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo); +/** +Set encoding parameters to default values, that means : +
      +
    • Lossless +
    • 1 tile +
    • Size of precinct : 2^15 x 2^15 (means 1 precinct) +
    • Size of code-block : 64 x 64 +
    • Number of resolutions: 6 +
    • No SOP marker in the codestream +
    • No EPH marker in the codestream +
    • No sub-sampling in x or y direction +
    • No mode switch activated +
    • Progression order: LRCP +
    • No index file +
    • No ROI upshifted +
    • No offset of the origin of the image +
    • No offset of the origin of the tiles +
    • Reversible DWT 5-3 +
    +@param parameters Compression parameters +*/ +OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters); +/** +Setup the encoder parameters using the current image and using user parameters. +@param cinfo Compressor handle +@param parameters Compression parameters +@param image Input filled image +*/ +OPJ_API void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image); +/** +Encode an image into a JPEG-2000 codestream +3@param cinfo compressor handle +@param cio Output buffer stream +@param image Image to encode +@param index Depreacted -> Set to NULL. To extract index, used opj_encode_wci() +@return Returns true if successful, returns false otherwise +*/ +OPJ_API opj_bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index); +/** +Encode an image into a JPEG-2000 codestream and extract the codestream information +@param cinfo compressor handle +@param cio Output buffer stream +@param image Image to encode +@param cstr_info Codestream information structure if needed afterwards, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +OPJ_API opj_bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); +/** +Destroy Codestream information after compression or decompression +@param cstr_info Codestream information structure +*/ +OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info); + + +#ifdef __cplusplus +} +#endif + +#endif /* OPENJPEG_H */ diff --git a/src/add-ons/translators/icns/openjpeg/opj_config.h b/src/add-ons/translators/icns/openjpeg/opj_config.h new file mode 100644 index 0000000000..870319673b --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/opj_config.h @@ -0,0 +1,117 @@ +/* opj_config.h. Generated from opj_config.h.in by configure. */ +/* opj_config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* define to 1 if you have lcms version 1.x */ +/* #undef HAVE_LIBLCMS1 */ + +/* define to 1 if you have lcms version 2.x */ +/* #undef HAVE_LIBLCMS2 */ + +/* define to 1 if you have libpng */ +#define HAVE_LIBPNG 1 + +/* define to 1 if you have libtiff */ +#define HAVE_LIBTIFF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "openjpeg" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "openjpeg@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "OpenJPEG" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "OpenJPEG 1.5.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "openjpeg" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://www.openjpeg.org" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.5.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* define to 1 if you use jpip */ +/* #undef USE_JPIP */ + +/* define to 1 if you use jpip server */ +/* #undef USE_JPIP_SERVER */ + +/* define to 1 if you use mj2 */ +/* #undef USE_MJ2 */ + +/* Version number of package */ +#define VERSION "1.5.1" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif diff --git a/src/add-ons/translators/icns/openjpeg/opj_includes.h b/src/add-ons/translators/icns/openjpeg/opj_includes.h new file mode 100644 index 0000000000..97b0310b84 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/opj_includes.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 OPJ_INCLUDES_H +#define OPJ_INCLUDES_H + +/* + ========================================================== + Standard includes used by the library + ========================================================== +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + ========================================================== + OpenJPEG interface + ========================================================== + */ +#include "openjpeg.h" + +/* + ========================================================== + OpenJPEG modules + ========================================================== +*/ + +/* Ignore GCC attributes if this is not GCC */ +#ifndef __GNUC__ + #define __attribute__(x) /* __attribute__(x) */ +#endif + +/* +The inline keyword is supported by C99 but not by C90. +Most compilers implement their own version of this keyword ... +*/ +#ifndef INLINE + #if defined(_MSC_VER) + #define INLINE __forceinline + #elif defined(__GNUC__) + #define INLINE __inline__ + #elif defined(__MWERKS__) + #define INLINE inline + #else + /* add other compilers here ... */ + #define INLINE + #endif /* defined() */ +#endif /* INLINE */ + +/* Are restricted pointers available? (C99) */ +#if (__STDC_VERSION__ != 199901L) + /* Not a C99 compiler */ + #ifdef __GNUC__ + #define restrict __restrict__ + #else + #define restrict /* restrict */ + #endif +#endif + +/* MSVC and Borland C do not have lrintf */ +#if defined(_MSC_VER) || defined(__BORLANDC__) +static INLINE long lrintf(float f){ +#ifdef _M_X64 + return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); +#else + int i; + + _asm{ + fld f + fistp i + }; + + return i; +#endif +} +#endif + +#include "j2k_lib.h" +#include "opj_malloc.h" +#include "event.h" +#include "bio.h" +#include "cio.h" + +#include "oj_image.h" +#include "j2k.h" +#include "jp2.h" +#include "jpt.h" + +#include "mqc.h" +#include "raw.h" +#include "bio.h" +#include "tgt.h" +#include "pi.h" +#include "tcd.h" +#include "t1.h" +#include "dwt.h" +#include "t2.h" +#include "mct.h" +#include "int.h" +#include "fix.h" + +#include "cidx_manager.h" +#include "indexbox_manager.h" + +/* JPWL>> */ +#ifdef USE_JPWL +#include "./jpwl/jpwl.h" +#endif /* USE_JPWL */ +/* < + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __OPJ_MALLOC_H +#define __OPJ_MALLOC_H +/** +@file opj_malloc.h +@brief Internal functions + +The functions in opj_malloc.h are internal utilities used for memory management. +*/ + +/** @defgroup MISC MISC - Miscellaneous internal functions */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Allocate an uninitialized memory block +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +#ifdef ALLOC_PERF_OPT +void * OPJ_CALLCONV opj_malloc(size_t size); +#else +#define opj_malloc(size) malloc(size) +#endif + +/** +Allocate a memory block with elements initialized to 0 +@param num Blocks to allocate +@param size Bytes per block to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +#ifdef ALLOC_PERF_OPT +void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements); +#else +#define opj_calloc(num, size) calloc(num, size) +#endif + +/** +Allocate memory aligned to a 16 byte boundry +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ +#ifdef _WIN32 + /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ + #ifdef __GNUC__ + #include + #define HAVE_MM_MALLOC + #else /* MSVC, Intel C++ */ + #include + #ifdef _mm_malloc + #define HAVE_MM_MALLOC + #endif + #endif +#else /* Not _WIN32 */ + #if defined(__sun) + #define HAVE_MEMALIGN + #elif defined(__FreeBSD__) + #define HAVE_POSIX_MEMALIGN + /* Linux x86_64 and OSX always align allocations to 16 bytes */ + #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX) + #define HAVE_MEMALIGN + #include + #endif +#endif + +#define opj_aligned_malloc(size) malloc(size) +#define opj_aligned_free(m) free(m) + +#ifdef HAVE_MM_MALLOC + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) _mm_malloc(size, 16) + #undef opj_aligned_free + #define opj_aligned_free(m) _mm_free(m) +#endif + +#ifdef HAVE_MEMALIGN + extern void* memalign(size_t, size_t); + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) memalign(16, (size)) + #undef opj_aligned_free + #define opj_aligned_free(m) free(m) +#endif + +#ifdef HAVE_POSIX_MEMALIGN + #undef opj_aligned_malloc + extern int posix_memalign(void**, size_t, size_t); + + static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ + void* mem = NULL; + posix_memalign(&mem, 16, size); + return mem; + } + #undef opj_aligned_free + #define opj_aligned_free(m) free(m) +#endif + +#ifdef ALLOC_PERF_OPT + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) opj_malloc(size) + #undef opj_aligned_free + #define opj_aligned_free(m) opj_free(m) +#endif + +/** +Reallocate memory blocks. +@param m Pointer to previously allocated memory block +@param s New size in bytes +@return Returns a void pointer to the reallocated (and possibly moved) memory block +*/ +#ifdef ALLOC_PERF_OPT +void * OPJ_CALLCONV opj_realloc(void * m, size_t s); +#else +#define opj_realloc(m, s) realloc(m, s) +#endif + +/** +Deallocates or frees a memory block. +@param m Previously allocated memory block to be freed +*/ +#ifdef ALLOC_PERF_OPT +void OPJ_CALLCONV opj_free(void * m); +#else +#define opj_free(m) free(m) +#endif + +#ifdef __GNUC__ +#pragma GCC poison malloc calloc realloc free +#endif + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __OPJ_MALLOC_H */ + diff --git a/src/add-ons/translators/icns/openjpeg/phix_manager.c b/src/add-ons/translators/icns/openjpeg/phix_manager.c new file mode 100644 index 0000000000..60a0281178 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/phix_manager.c @@ -0,0 +1,170 @@ +/* + * $Id: phix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include +#include +#include "opj_includes.h" + +/* + * Write faix box of phix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] EPHused true if if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ +int write_phixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + +int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio) +{ + int len, lenp=0, compno, i; + opj_jp2_box_t *box; + + box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t)); + + for( i=0;i<2;i++){ + if (i) cio_seek( cio, lenp); + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_PHIX, 4); /* PHIX */ + + write_manf( i, cstr_info.numcomps, box, cio); + + for( compno=0; compno pow( 2, 32)){ + size_of_coding = 8; + version = 1; + } + else{ + size_of_coding = 4; + version = 0; + } + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FAIX, 4); /* FAIX */ + cio_write( cio, version,1); /* Version 0 = 4 bytes */ + + nmax = 0; + for( i=0; i<=cstr_info.numdecompos[compno]; i++) + nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers; + + cio_write( cio, nmax, size_of_coding); /* NMAX */ + cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */ + + for( tileno=0; tilenopw[resno]*tile_Idx->ph[resno]; + for( precno=0; precnopacket[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RLCP: + packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RPCL: + packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno]; + break; + case PCRL: + packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno]; + break; + case CPRL: + packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno]; + break; + default: + fprintf( stderr, "failed to ppix indexing\n"); + } + + cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */ + cio_write( cio, packet.end_ph_pos-packet.start_pos+1, size_of_coding); /* length */ + + num_packet++; + } + } + } + + /* PADDING */ + while( num_packet < nmax){ + cio_write( cio, 0, size_of_coding); /* start position */ + cio_write( cio, 0, size_of_coding); /* length */ + num_packet++; + } + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} diff --git a/src/add-ons/translators/icns/openjpeg/pi.c b/src/add-ons/translators/icns/openjpeg/pi.c new file mode 100644 index 0000000000..e8e33bfe60 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/pi.c @@ -0,0 +1,963 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/** @defgroup PI PI - Implementation of a packet iterator */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Get next packet in layer-resolution-component-precinct order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi); +/** +Get next packet in resolution-layer-component-precinct order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi); +/** +Get next packet in resolution-precinct-component-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi); +/** +Get next packet in precinct-component-resolution-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi); +/** +Get next packet in component-precinct-resolution-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static opj_bool pi_next_cprl(opj_pi_iterator_t * pi); + +/*@}*/ + +/*@}*/ + +/* +========================================================== + local functions +========================================================== +*/ + +static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; + pi->resno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if (!pi->tp_on){ + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP:; + } + } + } + } + + return OPJ_FALSE; +} + +static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if(!pi->tp_on){ + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP:; + } + } + } + } + + return OPJ_FALSE; +} + +static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + goto LABEL_SKIP; + } else { + int compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + int dx, dy; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + } + } +if (!pi->tp_on){ + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + int levelno; + int trx0, try0; + int trx1, try1; + int rpx, rpy; + int prci, prcj; + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); + try0 = int_ceildiv(pi->ty0, comp->dy << levelno); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); + try1 = int_ceildiv(pi->ty1, comp->dy << levelno); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ + continue; + } + if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ + continue; + } + + if ((res->pw==0)||(res->ph==0)) continue; + + if ((trx0==trx1)||(try0==try1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) + - int_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP:; + } + } + } + } + } + + return OPJ_FALSE; +} + +static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + int compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + int dx, dy; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + } + } + if (!pi->tp_on){ + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + int levelno; + int trx0, try0; + int trx1, try1; + int rpx, rpy; + int prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); + try0 = int_ceildiv(pi->ty0, comp->dy << levelno); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); + try1 = int_ceildiv(pi->ty1, comp->dy << levelno); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ + continue; + } + if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ + continue; + } + + if ((res->pw==0)||(res->ph==0)) continue; + + if ((trx0==trx1)||(try0==try1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) + - int_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP:; + } + } + } + } + } + + return OPJ_FALSE; +} + +static opj_bool pi_next_cprl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + int resno; + comp = &pi->comps[pi->compno]; + pi->dx = 0; + pi->dy = 0; + for (resno = 0; resno < comp->numresolutions; resno++) { + int dx, dy; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + if (!pi->tp_on){ + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + int levelno; + int trx0, try0; + int trx1, try1; + int rpx, rpy; + int prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); + try0 = int_ceildiv(pi->ty0, comp->dy << levelno); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); + try1 = int_ceildiv(pi->ty1, comp->dy << levelno); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ + continue; + } + if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ + continue; + } + + if ((res->pw==0)||(res->ph==0)) continue; + + if ((trx0==trx1)||(try0==try1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) + - int_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP:; + } + } + } + } + } + + return OPJ_FALSE; +} + +/* +========================================================== + Packet iterator interface +========================================================== +*/ + +opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, int tileno) { + int p, q; + int compno, resno, pino; + opj_pi_iterator_t *pi = NULL; + opj_tcp_t *tcp = NULL; + opj_tccp_t *tccp = NULL; + + tcp = &cp->tcps[tileno]; + + pi = (opj_pi_iterator_t*) opj_calloc((tcp->numpocs + 1), sizeof(opj_pi_iterator_t)); + if(!pi) { + /* TODO: throw an error */ + return NULL; + } + + for (pino = 0; pino < tcp->numpocs + 1; pino++) { /* change */ + int maxres = 0; + int maxprec = 0; + p = tileno % cp->tw; + q = tileno / cp->tw; + + pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0); + pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0); + pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1); + pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1); + pi[pino].numcomps = image->numcomps; + + pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t)); + if(!pi[pino].comps) { + /* TODO: throw an error */ + pi_destroy(pi, cp, tileno); + return NULL; + } + + for (compno = 0; compno < pi->numcomps; compno++) { + int tcx0, tcy0, tcx1, tcy1; + opj_pi_comp_t *comp = &pi[pino].comps[compno]; + tccp = &tcp->tccps[compno]; + comp->dx = image->comps[compno].dx; + comp->dy = image->comps[compno].dy; + comp->numresolutions = tccp->numresolutions; + + comp->resolutions = (opj_pi_resolution_t*) opj_calloc(comp->numresolutions, sizeof(opj_pi_resolution_t)); + if(!comp->resolutions) { + /* TODO: throw an error */ + pi_destroy(pi, cp, tileno); + return NULL; + } + + tcx0 = int_ceildiv(pi->tx0, comp->dx); + tcy0 = int_ceildiv(pi->ty0, comp->dy); + tcx1 = int_ceildiv(pi->tx1, comp->dx); + tcy1 = int_ceildiv(pi->ty1, comp->dy); + if (comp->numresolutions > maxres) { + maxres = comp->numresolutions; + } + + for (resno = 0; resno < comp->numresolutions; resno++) { + int levelno; + int rx0, ry0, rx1, ry1; + int px0, py0, px1, py1; + opj_pi_resolution_t *res = &comp->resolutions[resno]; + if (tccp->csty & J2K_CCP_CSTY_PRT) { + res->pdx = tccp->prcw[resno]; + res->pdy = tccp->prch[resno]; + } else { + res->pdx = 15; + res->pdy = 15; + } + levelno = comp->numresolutions - 1 - resno; + rx0 = int_ceildivpow2(tcx0, levelno); + ry0 = int_ceildivpow2(tcy0, levelno); + rx1 = int_ceildivpow2(tcx1, levelno); + ry1 = int_ceildivpow2(tcy1, levelno); + px0 = int_floordivpow2(rx0, res->pdx) << res->pdx; + py0 = int_floordivpow2(ry0, res->pdy) << res->pdy; + px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx; + py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy; + res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx); + res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy); + + if (res->pw*res->ph > maxprec) { + maxprec = res->pw*res->ph; + } + + } + } + + tccp = &tcp->tccps[0]; + pi[pino].step_p = 1; + pi[pino].step_c = maxprec * pi[pino].step_p; + pi[pino].step_r = image->numcomps * pi[pino].step_c; + pi[pino].step_l = maxres * pi[pino].step_r; + + if (pino == 0) { + pi[pino].include = (short int*) opj_calloc(image->numcomps * maxres * tcp->numlayers * maxprec, sizeof(short int)); + if(!pi[pino].include) { + /* TODO: throw an error */ + pi_destroy(pi, cp, tileno); + return NULL; + } + } + else { + pi[pino].include = pi[pino - 1].include; + } + + if (tcp->POC == 0) { + pi[pino].first = 1; + pi[pino].poc.resno0 = 0; + pi[pino].poc.compno0 = 0; + pi[pino].poc.layno1 = tcp->numlayers; + pi[pino].poc.resno1 = maxres; + pi[pino].poc.compno1 = image->numcomps; + pi[pino].poc.prg = tcp->prg; + } else { + pi[pino].first = 1; + pi[pino].poc.resno0 = tcp->pocs[pino].resno0; + pi[pino].poc.compno0 = tcp->pocs[pino].compno0; + pi[pino].poc.layno1 = tcp->pocs[pino].layno1; + pi[pino].poc.resno1 = tcp->pocs[pino].resno1; + pi[pino].poc.compno1 = tcp->pocs[pino].compno1; + pi[pino].poc.prg = tcp->pocs[pino].prg; + } + pi[pino].poc.layno0 = 0; + pi[pino].poc.precno0 = 0; + pi[pino].poc.precno1 = maxprec; + + } + + return pi; +} + + +opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno, J2K_T2_MODE t2_mode){ + int p, q, pino; + int compno, resno; + int maxres = 0; + int maxprec = 0; + opj_pi_iterator_t *pi = NULL; + opj_tcp_t *tcp = NULL; + opj_tccp_t *tccp = NULL; + + tcp = &cp->tcps[tileno]; + + pi = (opj_pi_iterator_t*) opj_calloc((tcp->numpocs + 1), sizeof(opj_pi_iterator_t)); + if(!pi) { return NULL;} + pi->tp_on = cp->tp_on; + + for(pino = 0;pino < tcp->numpocs+1 ; pino ++){ + p = tileno % cp->tw; + q = tileno / cp->tw; + + pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0); + pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0); + pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1); + pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1); + pi[pino].numcomps = image->numcomps; + + pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t)); + if(!pi[pino].comps) { + pi_destroy(pi, cp, tileno); + return NULL; + } + + for (compno = 0; compno < pi[pino].numcomps; compno++) { + int tcx0, tcy0, tcx1, tcy1; + opj_pi_comp_t *comp = &pi[pino].comps[compno]; + tccp = &tcp->tccps[compno]; + comp->dx = image->comps[compno].dx; + comp->dy = image->comps[compno].dy; + comp->numresolutions = tccp->numresolutions; + + comp->resolutions = (opj_pi_resolution_t*) opj_malloc(comp->numresolutions * sizeof(opj_pi_resolution_t)); + if(!comp->resolutions) { + pi_destroy(pi, cp, tileno); + return NULL; + } + + tcx0 = int_ceildiv(pi[pino].tx0, comp->dx); + tcy0 = int_ceildiv(pi[pino].ty0, comp->dy); + tcx1 = int_ceildiv(pi[pino].tx1, comp->dx); + tcy1 = int_ceildiv(pi[pino].ty1, comp->dy); + if (comp->numresolutions > maxres) { + maxres = comp->numresolutions; + } + + for (resno = 0; resno < comp->numresolutions; resno++) { + int levelno; + int rx0, ry0, rx1, ry1; + int px0, py0, px1, py1; + opj_pi_resolution_t *res = &comp->resolutions[resno]; + if (tccp->csty & J2K_CCP_CSTY_PRT) { + res->pdx = tccp->prcw[resno]; + res->pdy = tccp->prch[resno]; + } else { + res->pdx = 15; + res->pdy = 15; + } + levelno = comp->numresolutions - 1 - resno; + rx0 = int_ceildivpow2(tcx0, levelno); + ry0 = int_ceildivpow2(tcy0, levelno); + rx1 = int_ceildivpow2(tcx1, levelno); + ry1 = int_ceildivpow2(tcy1, levelno); + px0 = int_floordivpow2(rx0, res->pdx) << res->pdx; + py0 = int_floordivpow2(ry0, res->pdy) << res->pdy; + px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx; + py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy; + res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx); + res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy); + + if (res->pw*res->ph > maxprec) { + maxprec = res->pw * res->ph; + } + } + } + + tccp = &tcp->tccps[0]; + pi[pino].step_p = 1; + pi[pino].step_c = maxprec * pi[pino].step_p; + pi[pino].step_r = image->numcomps * pi[pino].step_c; + pi[pino].step_l = maxres * pi[pino].step_r; + + for (compno = 0; compno < pi->numcomps; compno++) { + opj_pi_comp_t *comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + int dx, dy; + opj_pi_resolution_t *res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); + pi[pino].dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi[pino].dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + } + + if (pino == 0) { + pi[pino].include = (short int*) opj_calloc(tcp->numlayers * pi[pino].step_l, sizeof(short int)); + if(!pi[pino].include) { + pi_destroy(pi, cp, tileno); + return NULL; + } + } + else { + pi[pino].include = pi[pino - 1].include; + } + + /* Generation of boundaries for each prog flag*/ + if(tcp->POC && ( cp->cinema || ((!cp->cinema) && (t2_mode == FINAL_PASS)))){ + tcp->pocs[pino].compS= tcp->pocs[pino].compno0; + tcp->pocs[pino].compE= tcp->pocs[pino].compno1; + tcp->pocs[pino].resS = tcp->pocs[pino].resno0; + tcp->pocs[pino].resE = tcp->pocs[pino].resno1; + tcp->pocs[pino].layE = tcp->pocs[pino].layno1; + tcp->pocs[pino].prg = tcp->pocs[pino].prg1; + if (pino > 0) + tcp->pocs[pino].layS = (tcp->pocs[pino].layE > tcp->pocs[pino - 1].layE) ? tcp->pocs[pino - 1].layE : 0; + }else { + tcp->pocs[pino].compS= 0; + tcp->pocs[pino].compE= image->numcomps; + tcp->pocs[pino].resS = 0; + tcp->pocs[pino].resE = maxres; + tcp->pocs[pino].layS = 0; + tcp->pocs[pino].layE = tcp->numlayers; + tcp->pocs[pino].prg = tcp->prg; + } + tcp->pocs[pino].prcS = 0; + tcp->pocs[pino].prcE = maxprec;; + tcp->pocs[pino].txS = pi[pino].tx0; + tcp->pocs[pino].txE = pi[pino].tx1; + tcp->pocs[pino].tyS = pi[pino].ty0; + tcp->pocs[pino].tyE = pi[pino].ty1; + tcp->pocs[pino].dx = pi[pino].dx; + tcp->pocs[pino].dy = pi[pino].dy; + } + return pi; + } + + + +void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) { + int compno, pino; + opj_tcp_t *tcp = &cp->tcps[tileno]; + if(pi) { + for (pino = 0; pino < tcp->numpocs + 1; pino++) { + if(pi[pino].comps) { + for (compno = 0; compno < pi->numcomps; compno++) { + opj_pi_comp_t *comp = &pi[pino].comps[compno]; + if(comp->resolutions) { + opj_free(comp->resolutions); + } + } + opj_free(pi[pino].comps); + } + } + if(pi->include) { + opj_free(pi->include); + } + opj_free(pi); + } +} + +opj_bool pi_next(opj_pi_iterator_t * pi) { + switch (pi->poc.prg) { + case LRCP: + return pi_next_lrcp(pi); + case RLCP: + return pi_next_rlcp(pi); + case RPCL: + return pi_next_rpcl(pi); + case PCRL: + return pi_next_pcrl(pi); + case CPRL: + return pi_next_cprl(pi); + case PROG_UNKNOWN: + return OPJ_FALSE; + } + + return OPJ_FALSE; +} + +opj_bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp){ + char prog[4]; + int i; + int incr_top=1,resetX=0; + opj_tcp_t *tcps =&cp->tcps[tileno]; + opj_poc_t *tcp= &tcps->pocs[pino]; + + pi[pino].first = 1; + pi[pino].poc.prg = tcp->prg; + + switch(tcp->prg){ + case CPRL: strncpy(prog, "CPRL",4); + break; + case LRCP: strncpy(prog, "LRCP",4); + break; + case PCRL: strncpy(prog, "PCRL",4); + break; + case RLCP: strncpy(prog, "RLCP",4); + break; + case RPCL: strncpy(prog, "RPCL",4); + break; + case PROG_UNKNOWN: + return OPJ_TRUE; + } + + if(!(cp->tp_on && ((!cp->cinema && (t2_mode == FINAL_PASS)) || cp->cinema))){ + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + pi[pino].poc.tx0 = tcp->txS; + pi[pino].poc.ty0 = tcp->tyS; + pi[pino].poc.tx1 = tcp->txE; + pi[pino].poc.ty1 = tcp->tyE; + }else { + if( tpnum < cur_totnum_tp){ + for(i=3;i>=0;i--){ + switch(prog[i]){ + case 'C': + if (i > tppos){ + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + }else{ + if (tpnum == 0){ + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t+1; + tcp->comp_t+=1; + }else{ + if (incr_top == 1){ + if(tcp->comp_t ==tcp->compE){ + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t+1; + tcp->comp_t+=1; + incr_top=1; + }else{ + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t+1; + tcp->comp_t+=1; + incr_top=0; + } + }else{ + pi[pino].poc.compno0 = tcp->comp_t-1; + pi[pino].poc.compno1 = tcp->comp_t; + } + } + } + break; + + case 'R': + if (i > tppos){ + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + }else{ + if (tpnum == 0){ + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t+1; + tcp->res_t+=1; + }else{ + if (incr_top == 1){ + if(tcp->res_t==tcp->resE){ + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t+1; + tcp->res_t+=1; + incr_top=1; + }else{ + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t+1; + tcp->res_t+=1; + incr_top=0; + } + }else{ + pi[pino].poc.resno0 = tcp->res_t - 1; + pi[pino].poc.resno1 = tcp->res_t; + } + } + } + break; + + case 'L': + if (i > tppos){ + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + }else{ + if (tpnum == 0){ + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t+1; + tcp->lay_t+=1; + }else{ + if (incr_top == 1){ + if(tcp->lay_t == tcp->layE){ + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t+1; + tcp->lay_t+=1; + incr_top=1; + }else{ + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t+1; + tcp->lay_t+=1; + incr_top=0; + } + }else{ + pi[pino].poc.layno0 = tcp->lay_t - 1; + pi[pino].poc.layno1 = tcp->lay_t; + } + } + } + break; + + case 'P': + switch(tcp->prg){ + case LRCP: + case RLCP: + if (i > tppos){ + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + }else{ + if (tpnum == 0){ + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t+1; + tcp->prc_t+=1; + }else{ + if (incr_top == 1){ + if(tcp->prc_t == tcp->prcE){ + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t+1; + tcp->prc_t+=1; + incr_top=1; + }else{ + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t+1; + tcp->prc_t+=1; + incr_top=0; + } + }else{ + pi[pino].poc.precno0 = tcp->prc_t - 1; + pi[pino].poc.precno1 = tcp->prc_t; + } + } + } + break; + default: + if (i > tppos){ + pi[pino].poc.tx0 = tcp->txS; + pi[pino].poc.ty0 = tcp->tyS; + pi[pino].poc.tx1 = tcp->txE; + pi[pino].poc.ty1 = tcp->tyE; + }else{ + if (tpnum == 0){ + tcp->tx0_t = tcp->txS; + tcp->ty0_t = tcp->tyS; + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx); + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->tx0_t = pi[pino].poc.tx1; + tcp->ty0_t = pi[pino].poc.ty1; + }else{ + if (incr_top == 1){ + if(tcp->tx0_t >= tcp->txE){ + if(tcp->ty0_t >= tcp->tyE){ + tcp->ty0_t = tcp->tyS; + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->ty0_t = pi[pino].poc.ty1; + incr_top=1;resetX=1; + }else{ + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->ty0_t = pi[pino].poc.ty1; + incr_top=0;resetX=1; + } + if(resetX==1){ + tcp->tx0_t = tcp->txS; + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx); + tcp->tx0_t = pi[pino].poc.tx1; + } + }else{ + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx); + tcp->tx0_t = pi[pino].poc.tx1; + pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy); + pi[pino].poc.ty1 = tcp->ty0_t ; + incr_top=0; + } + }else{ + pi[pino].poc.tx0 = tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx); + pi[pino].poc.tx1 = tcp->tx0_t ; + pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy); + pi[pino].poc.ty1 = tcp->ty0_t ; + } + } + } + break; + } + break; + } + } + } + } + return OPJ_FALSE; +} + diff --git a/src/add-ons/translators/icns/openjpeg/pi.h b/src/add-ons/translators/icns/openjpeg/pi.h new file mode 100644 index 0000000000..cf9135fd1f --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/pi.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __PI_H +#define __PI_H +/** +@file pi.h +@brief Implementation of a packet iterator (PI) + +The functions in PI.C have for goal to realize a packet iterator that permits to get the next +packet following the progression order and change of it. The functions in PI.C are used +by some function in T2.C. +*/ + +/** @defgroup PI PI - Implementation of a packet iterator */ +/*@{*/ + +/** +FIXME: documentation +*/ +typedef struct opj_pi_resolution { + int pdx, pdy; + int pw, ph; +} opj_pi_resolution_t; + +/** +FIXME: documentation +*/ +typedef struct opj_pi_comp { + int dx, dy; + /** number of resolution levels */ + int numresolutions; + opj_pi_resolution_t *resolutions; +} opj_pi_comp_t; + +/** +Packet iterator +*/ +typedef struct opj_pi_iterator { + /** Enabling Tile part generation*/ + char tp_on; + /** precise if the packet has been already used (usefull for progression order change) */ + short int *include; + /** layer step used to localize the packet in the include vector */ + int step_l; + /** resolution step used to localize the packet in the include vector */ + int step_r; + /** component step used to localize the packet in the include vector */ + int step_c; + /** precinct step used to localize the packet in the include vector */ + int step_p; + /** component that identify the packet */ + int compno; + /** resolution that identify the packet */ + int resno; + /** precinct that identify the packet */ + int precno; + /** layer that identify the packet */ + int layno; + /** 0 if the first packet */ + int first; + /** progression order change information */ + opj_poc_t poc; + /** number of components in the image */ + int numcomps; + /** Components*/ + opj_pi_comp_t *comps; + int tx0, ty0, tx1, ty1; + int x, y, dx, dy; +} opj_pi_iterator_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a packet iterator for Encoder +@param image Raw image for which the packets will be listed +@param cp Coding parameters +@param tileno Number that identifies the tile for which to list the packets +@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass +@return Returns a packet iterator that points to the first packet of the tile +@see pi_destroy +*/ +opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno,J2K_T2_MODE t2_mode); +/** +Modify the packet iterator for enabling tile part generation +@param pi Handle to the packet iterator generated in pi_initialise_encode +@param cp Coding parameters +@param tileno Number that identifies the tile for which to list the packets +@param pino Iterator index for pi +@param tpnum Tile part number of the current tile +@param tppos The position of the tile part flag in the progression order +@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass +@param cur_totnum_tp The total number of tile parts in the current tile +@return Returns true if an error is detected +*/ +opj_bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp); +/** +Create a packet iterator for Decoder +@param image Raw image for which the packets will be listed +@param cp Coding parameters +@param tileno Number that identifies the tile for which to list the packets +@return Returns a packet iterator that points to the first packet of the tile +@see pi_destroy +*/ +opj_pi_iterator_t *pi_create_decode(opj_image_t * image, opj_cp_t * cp, int tileno); + +/** +Destroy a packet iterator +@param pi Previously created packet iterator +@param cp Coding parameters +@param tileno Number that identifies the tile for which the packets were listed +@see pi_create +*/ +void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno); + +/** +Modify the packet iterator to point to the next packet +@param pi Packet iterator to modify +@return Returns false if pi pointed to the last packet or else returns true +*/ +opj_bool pi_next(opj_pi_iterator_t * pi); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __PI_H */ diff --git a/src/add-ons/translators/icns/openjpeg/ppix_manager.c b/src/add-ons/translators/icns/openjpeg/ppix_manager.c new file mode 100644 index 0000000000..58d324ceb4 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/ppix_manager.c @@ -0,0 +1,173 @@ +/* + * $Id: ppix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include +#include +#include +#include "opj_includes.h" + +/* + * Write faix box of ppix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] EPHused true if if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ +int write_ppixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + +int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio) +{ + int len, lenp, compno, i; + opj_jp2_box_t *box; + + /* printf("cstr_info.packno %d\n", cstr_info.packno); //NMAX? */ + + lenp = -1; + box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t)); + + for (i=0;i<2;i++){ + if (i) cio_seek( cio, lenp); + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_PPIX, 4); /* PPIX */ + + write_manf( i, cstr_info.numcomps, box, cio); + + for (compno=0; compno pow( 2, 32)){ + size_of_coding = 8; + version = 1; + } + else{ + size_of_coding = 4; + version = 0; + } + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FAIX, 4); /* FAIX */ + cio_write( cio, version, 1); /* Version 0 = 4 bytes */ + + nmax = 0; + for( i=0; i<=cstr_info.numdecompos[compno]; i++) + nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers; + + cio_write( cio, nmax, size_of_coding); /* NMAX */ + cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */ + + for( tileno=0; tilenopw[resno]*tile_Idx->ph[resno]; + for( precno=0; precnopacket[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RLCP: + packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RPCL: + packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno]; + break; + case PCRL: + packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno]; + break; + case CPRL: + packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno]; + break; + default: + fprintf( stderr, "failed to ppix indexing\n"); + } + + cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */ + cio_write( cio, packet.end_pos-packet.start_pos+1, size_of_coding); /* length */ + + num_packet++; + } + } + } + + while( num_packet < nmax){ /* PADDING */ + cio_write( cio, 0, size_of_coding); /* start position */ + cio_write( cio, 0, size_of_coding); /* length */ + num_packet++; + } + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} diff --git a/src/add-ons/translators/icns/openjpeg/raw.c b/src/add-ons/translators/icns/openjpeg/raw.c new file mode 100644 index 0000000000..3d231bfdc6 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/raw.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/* +========================================================== + local functions +========================================================== +*/ + + +/* +========================================================== + RAW encoding interface +========================================================== +*/ + +opj_raw_t* raw_create(void) { + opj_raw_t *raw = (opj_raw_t*)opj_malloc(sizeof(opj_raw_t)); + return raw; +} + +void raw_destroy(opj_raw_t *raw) { + if(raw) { + opj_free(raw); + } +} + +int raw_numbytes(opj_raw_t *raw) { + return raw->bp - raw->start; +} + +void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len) { + raw->start = bp; + raw->lenmax = len; + raw->len = 0; + raw->c = 0; + raw->ct = 0; +} + +int raw_decode(opj_raw_t *raw) { + int d; + if (raw->ct == 0) { + raw->ct = 8; + if (raw->len == raw->lenmax) { + raw->c = 0xff; + } else { + if (raw->c == 0xff) { + raw->ct = 7; + } + raw->c = *(raw->start + raw->len); + raw->len++; + } + } + raw->ct--; + d = (raw->c >> raw->ct) & 0x01; + + return d; +} + diff --git a/src/add-ons/translators/icns/openjpeg/raw.h b/src/add-ons/translators/icns/openjpeg/raw.h new file mode 100644 index 0000000000..3c4b372f3f --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/raw.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __RAW_H +#define __RAW_H +/** +@file raw.h +@brief Implementation of operations for raw encoding (RAW) + +The functions in RAW.C have for goal to realize the operation of raw encoding linked +with the corresponding mode switch. +*/ + +/** @defgroup RAW RAW - Implementation of operations for raw encoding */ +/*@{*/ + +/** +RAW encoding operations +*/ +typedef struct opj_raw { + /** temporary buffer where bits are coded or decoded */ + unsigned char c; + /** number of bits already read or free to write */ + unsigned int ct; + /** maximum length to decode */ + unsigned int lenmax; + /** length decoded */ + unsigned int len; + /** pointer to the current position in the buffer */ + unsigned char *bp; + /** pointer to the start of the buffer */ + unsigned char *start; + /** pointer to the end of the buffer */ + unsigned char *end; +} opj_raw_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new RAW handle +@return Returns a new RAW handle if successful, returns NULL otherwise +*/ +opj_raw_t* raw_create(void); +/** +Destroy a previously created RAW handle +@param raw RAW handle to destroy +*/ +void raw_destroy(opj_raw_t *raw); +/** +Return the number of bytes written/read since initialisation +@param raw RAW handle to destroy +@return Returns the number of bytes already encoded +*/ +int raw_numbytes(opj_raw_t *raw); +/** +Initialize the decoder +@param raw RAW handle +@param bp Pointer to the start of the buffer from which the bytes will be read +@param len Length of the input buffer +*/ +void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len); +/** +Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN +@param raw RAW handle +@return Returns the decoded symbol (0 or 1) +*/ +int raw_decode(opj_raw_t *raw); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __RAW_H */ diff --git a/src/add-ons/translators/icns/openjpeg/t1.c b/src/add-ons/translators/icns/openjpeg/t1.c new file mode 100644 index 0000000000..ed9cdc3fea --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/t1.c @@ -0,0 +1,1585 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Callum Lerwick + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" +#include "t1_luts.h" + +/** @defgroup T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static INLINE char t1_getctxno_zc(int f, int orient); +static char t1_getctxno_sc(int f); +static INLINE int t1_getctxno_mag(int f); +static char t1_getspb(int f); +static short t1_getnmsedec_sig(int x, int bitpos); +static short t1_getnmsedec_ref(int x, int bitpos); +static void t1_updateflags(flag_t *flagsp, int s, int stride); +/** +Encode significant pass +*/ +static void t1_enc_sigpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int bpno, + int one, + int *nmsedec, + char type, + int vsc); +/** +Decode significant pass +*/ +static INLINE void t1_dec_sigpass_step_raw( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf, + int vsc); +static INLINE void t1_dec_sigpass_step_mqc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf); +static INLINE void t1_dec_sigpass_step_mqc_vsc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf, + int vsc); +/** +Encode significant pass +*/ +static void t1_enc_sigpass( + opj_t1_t *t1, + int bpno, + int orient, + int *nmsedec, + char type, + int cblksty); +/** +Decode significant pass +*/ +static void t1_dec_sigpass_raw( + opj_t1_t *t1, + int bpno, + int orient, + int cblksty); +static void t1_dec_sigpass_mqc( + opj_t1_t *t1, + int bpno, + int orient); +static void t1_dec_sigpass_mqc_vsc( + opj_t1_t *t1, + int bpno, + int orient); +/** +Encode refinement pass +*/ +static void t1_enc_refpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int bpno, + int one, + int *nmsedec, + char type, + int vsc); +/** +Decode refinement pass +*/ +static INLINE void t1_dec_refpass_step_raw( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int poshalf, + int neghalf, + int vsc); +static INLINE void t1_dec_refpass_step_mqc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int poshalf, + int neghalf); +static INLINE void t1_dec_refpass_step_mqc_vsc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int poshalf, + int neghalf, + int vsc); + +/** +Encode refinement pass +*/ +static void t1_enc_refpass( + opj_t1_t *t1, + int bpno, + int *nmsedec, + char type, + int cblksty); +/** +Decode refinement pass +*/ +static void t1_dec_refpass_raw( + opj_t1_t *t1, + int bpno, + int cblksty); +static void t1_dec_refpass_mqc( + opj_t1_t *t1, + int bpno); +static void t1_dec_refpass_mqc_vsc( + opj_t1_t *t1, + int bpno); +/** +Encode clean-up pass +*/ +static void t1_enc_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int bpno, + int one, + int *nmsedec, + int partial, + int vsc); +/** +Decode clean-up pass +*/ +static void t1_dec_clnpass_step_partial( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf); +static void t1_dec_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf); +static void t1_dec_clnpass_step_vsc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf, + int partial, + int vsc); +/** +Encode clean-up pass +*/ +static void t1_enc_clnpass( + opj_t1_t *t1, + int bpno, + int orient, + int *nmsedec, + int cblksty); +/** +Decode clean-up pass +*/ +static void t1_dec_clnpass( + opj_t1_t *t1, + int bpno, + int orient, + int cblksty); +static double t1_getwmsedec( + int nmsedec, + int compno, + int level, + int orient, + int bpno, + int qmfbid, + double stepsize, + int numcomps, + int mct); +/** +Encode 1 code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param compno Component number +@param level +@param qmfbid +@param stepsize +@param cblksty Code-block style +@param numcomps +@param mct +@param tile +*/ +static void t1_encode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + int orient, + int compno, + int level, + int qmfbid, + double stepsize, + int cblksty, + int numcomps, + int mct, + opj_tcd_tile_t * tile); +/** +Decode 1 code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param roishift Region of interest shifting value +@param cblksty Code-block style +*/ +static void t1_decode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + int orient, + int roishift, + int cblksty); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +static char t1_getctxno_zc(int f, int orient) { + return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)]; +} + +static char t1_getctxno_sc(int f) { + return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +} + +static int t1_getctxno_mag(int f) { + int tmp1 = (f & T1_SIG_OTH) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG; + int tmp2 = (f & T1_REFINE) ? T1_CTXNO_MAG + 2 : tmp1; + return (tmp2); +} + +static char t1_getspb(int f) { + return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +} + +static short t1_getnmsedec_sig(int x, int bitpos) { + if (bitpos > T1_NMSEDEC_FRACBITS) { + return lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static short t1_getnmsedec_ref(int x, int bitpos) { + if (bitpos > T1_NMSEDEC_FRACBITS) { + return lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static void t1_updateflags(flag_t *flagsp, int s, int stride) { + flag_t *np = flagsp - stride; + flag_t *sp = flagsp + stride; + + static const flag_t mod[] = { + T1_SIG_S, T1_SIG_S|T1_SGN_S, + T1_SIG_E, T1_SIG_E|T1_SGN_E, + T1_SIG_W, T1_SIG_W|T1_SGN_W, + T1_SIG_N, T1_SIG_N|T1_SGN_N + }; + + np[-1] |= T1_SIG_SE; + np[0] |= mod[s]; + np[1] |= T1_SIG_SW; + + flagsp[-1] |= mod[s+2]; + flagsp[0] |= T1_SIG; + flagsp[1] |= mod[s+4]; + + sp[-1] |= T1_SIG_NE; + sp[0] |= mod[s+6]; + sp[1] |= T1_SIG_NW; +} + +static void t1_enc_sigpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int bpno, + int one, + int *nmsedec, + char type, + int vsc) +{ + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + v = int_abs(*datap) & one ? 1 : 0; + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); /* ESSAI */ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_bypass_enc(mqc, v); + } else { + mqc_encode(mqc, v); + } + if (v) { + v = *datap < 0 ? 1 : 0; + *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); /* ESSAI */ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_bypass_enc(mqc, v); + } else { + mqc_encode(mqc, v ^ t1_getspb(flag)); + } + t1_updateflags(flagsp, v, t1->flags_stride); + } + *flagsp |= T1_VISIT; + } +} + +static INLINE void t1_dec_sigpass_step_raw( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf, + int vsc) +{ + int v, flag; + opj_raw_t *raw = t1->raw; /* RAW component */ + + OPJ_ARG_NOT_USED(orient); + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + if (raw_decode(raw)) { + v = raw_decode(raw); /* ESSAI */ + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + *flagsp |= T1_VISIT; + } +} /* VSC and BYPASS by Antonin */ + +static INLINE void t1_dec_sigpass_step_mqc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf) +{ + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = *flagsp; + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_getspb(flag); + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + *flagsp |= T1_VISIT; + } +} /* VSC and BYPASS by Antonin */ + +static INLINE void t1_dec_sigpass_step_mqc_vsc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf, + int vsc) +{ + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_getspb(flag); + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + *flagsp |= T1_VISIT; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_sigpass( + opj_t1_t *t1, + int bpno, + int orient, + int *nmsedec, + char type, + int cblksty) +{ + int i, j, k, one, vsc; + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_enc_sigpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + bpno, + one, + nmsedec, + type, + vsc); + } + } + } +} + +static void t1_dec_sigpass_raw( + opj_t1_t *t1, + int bpno, + int orient, + int cblksty) +{ + int i, j, k, one, half, oneplushalf, vsc; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_dec_sigpass_step_raw( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + oneplushalf, + vsc); + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_dec_sigpass_mqc( + opj_t1_t *t1, + int bpno, + int orient) +{ + int i, j, k, one, half, oneplushalf; + int *data1 = t1->data; + flag_t *flags1 = &t1->flags[1]; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (k = 0; k < (t1->h & ~3); k += 4) { + for (i = 0; i < t1->w; ++i) { + int *data2 = data1 + i; + flag_t *flags2 = flags1 + i; + flags2 += t1->flags_stride; + t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + } + data1 += t1->w << 2; + flags1 += t1->flags_stride << 2; + } + for (i = 0; i < t1->w; ++i) { + int *data2 = data1 + i; + flag_t *flags2 = flags1 + i; + for (j = k; j < t1->h; ++j) { + flags2 += t1->flags_stride; + t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_dec_sigpass_mqc_vsc( + opj_t1_t *t1, + int bpno, + int orient) +{ + int i, j, k, one, half, oneplushalf, vsc; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = (j == k + 3 || j == t1->h - 1) ? 1 : 0; + t1_dec_sigpass_step_mqc_vsc( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + oneplushalf, + vsc); + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_refpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int bpno, + int one, + int *nmsedec, + char type, + int vsc) +{ + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + *nmsedec += t1_getnmsedec_ref(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); + v = int_abs(*datap) & one ? 1 : 0; + mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_bypass_enc(mqc, v); + } else { + mqc_encode(mqc, v); + } + *flagsp |= T1_REFINE; + } +} + +static INLINE void t1_dec_refpass_step_raw( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int poshalf, + int neghalf, + int vsc) +{ + int v, t, flag; + + opj_raw_t *raw = t1->raw; /* RAW component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + v = raw_decode(raw); + t = v ? poshalf : neghalf; + *datap += *datap < 0 ? -t : t; + *flagsp |= T1_REFINE; + } +} /* VSC and BYPASS by Antonin */ + +static INLINE void t1_dec_refpass_step_mqc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int poshalf, + int neghalf) +{ + int v, t, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = *flagsp; + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */ + v = mqc_decode(mqc); + t = v ? poshalf : neghalf; + *datap += *datap < 0 ? -t : t; + *flagsp |= T1_REFINE; + } +} /* VSC and BYPASS by Antonin */ + +static INLINE void t1_dec_refpass_step_mqc_vsc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int poshalf, + int neghalf, + int vsc) +{ + int v, t, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */ + v = mqc_decode(mqc); + t = v ? poshalf : neghalf; + *datap += *datap < 0 ? -t : t; + *flagsp |= T1_REFINE; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_refpass( + opj_t1_t *t1, + int bpno, + int *nmsedec, + char type, + int cblksty) +{ + int i, j, k, one, vsc; + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_enc_refpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + bpno, + one, + nmsedec, + type, + vsc); + } + } + } +} + +static void t1_dec_refpass_raw( + opj_t1_t *t1, + int bpno, + int cblksty) +{ + int i, j, k, one, poshalf, neghalf; + int vsc; + one = 1 << bpno; + poshalf = one >> 1; + neghalf = bpno > 0 ? -poshalf : -1; + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_dec_refpass_step_raw( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + poshalf, + neghalf, + vsc); + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_dec_refpass_mqc( + opj_t1_t *t1, + int bpno) +{ + int i, j, k, one, poshalf, neghalf; + int *data1 = t1->data; + flag_t *flags1 = &t1->flags[1]; + one = 1 << bpno; + poshalf = one >> 1; + neghalf = bpno > 0 ? -poshalf : -1; + for (k = 0; k < (t1->h & ~3); k += 4) { + for (i = 0; i < t1->w; ++i) { + int *data2 = data1 + i; + flag_t *flags2 = flags1 + i; + flags2 += t1->flags_stride; + t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); + data2 += t1->w; + } + data1 += t1->w << 2; + flags1 += t1->flags_stride << 2; + } + for (i = 0; i < t1->w; ++i) { + int *data2 = data1 + i; + flag_t *flags2 = flags1 + i; + for (j = k; j < t1->h; ++j) { + flags2 += t1->flags_stride; + t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); + data2 += t1->w; + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_dec_refpass_mqc_vsc( + opj_t1_t *t1, + int bpno) +{ + int i, j, k, one, poshalf, neghalf; + int vsc; + one = 1 << bpno; + poshalf = one >> 1; + neghalf = bpno > 0 ? -poshalf : -1; + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_dec_refpass_step_mqc_vsc( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + poshalf, + neghalf, + vsc); + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int bpno, + int one, + int *nmsedec, + int partial, + int vsc) +{ + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(*flagsp & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + v = int_abs(*datap) & one ? 1 : 0; + mqc_encode(mqc, v); + if (v) { +LABEL_PARTIAL: + *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = *datap < 0 ? 1 : 0; + mqc_encode(mqc, v ^ t1_getspb(flag)); + t1_updateflags(flagsp, v, t1->flags_stride); + } + } + *flagsp &= ~T1_VISIT; +} + +static void t1_dec_clnpass_step_partial( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf) +{ + int v, flag; + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + OPJ_ARG_NOT_USED(orient); + + flag = *flagsp; + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_getspb(flag); + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + *flagsp &= ~T1_VISIT; +} /* VSC and BYPASS by Antonin */ + +static void t1_dec_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf) +{ + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = *flagsp; + if (!(flag & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_getspb(flag); + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + } + *flagsp &= ~T1_VISIT; +} /* VSC and BYPASS by Antonin */ + +static void t1_dec_clnpass_step_vsc( + opj_t1_t *t1, + flag_t *flagsp, + int *datap, + int orient, + int oneplushalf, + int partial, + int vsc) +{ + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(flag & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { +LABEL_PARTIAL: + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_getspb(flag); + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + } + *flagsp &= ~T1_VISIT; +} + +static void t1_enc_clnpass( + opj_t1_t *t1, + int bpno, + int orient, + int *nmsedec, + int cblksty) +{ + int i, j, k, one, agg, runlen, vsc; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + if (k + 3 < t1->h) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || (MACRO_t1_flags(1 + k + 3,1 + i) + & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + } else { + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + } + } else { + agg = 0; + } + if (agg) { + for (runlen = 0; runlen < 4; ++runlen) { + if (int_abs(t1->data[((k + runlen)*t1->w) + i]) & one) + break; + } + mqc_setcurctx(mqc, T1_CTXNO_AGG); + mqc_encode(mqc, runlen != 4); + if (runlen == 4) { + continue; + } + mqc_setcurctx(mqc, T1_CTXNO_UNI); + mqc_encode(mqc, runlen >> 1); + mqc_encode(mqc, runlen & 1); + } else { + runlen = 0; + } + for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_enc_clnpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + bpno, + one, + nmsedec, + agg && (j == k + runlen), + vsc); + } + } + } +} + +static void t1_dec_clnpass( + opj_t1_t *t1, + int bpno, + int orient, + int cblksty) +{ + int i, j, k, one, half, oneplushalf, agg, runlen, vsc; + int segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + if (k + 3 < t1->h) { + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || (MACRO_t1_flags(1 + k + 3,1 + i) + & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + } else { + agg = 0; + } + if (agg) { + mqc_setcurctx(mqc, T1_CTXNO_AGG); + if (!mqc_decode(mqc)) { + continue; + } + mqc_setcurctx(mqc, T1_CTXNO_UNI); + runlen = mqc_decode(mqc); + runlen = (runlen << 1) | mqc_decode(mqc); + } else { + runlen = 0; + } + for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { + vsc = (j == k + 3 || j == t1->h - 1) ? 1 : 0; + t1_dec_clnpass_step_vsc( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + oneplushalf, + agg && (j == k + runlen), + vsc); + } + } + } + } else { + int *data1 = t1->data; + flag_t *flags1 = &t1->flags[1]; + for (k = 0; k < (t1->h & ~3); k += 4) { + for (i = 0; i < t1->w; ++i) { + int *data2 = data1 + i; + flag_t *flags2 = flags1 + i; + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + if (agg) { + mqc_setcurctx(mqc, T1_CTXNO_AGG); + if (!mqc_decode(mqc)) { + continue; + } + mqc_setcurctx(mqc, T1_CTXNO_UNI); + runlen = mqc_decode(mqc); + runlen = (runlen << 1) | mqc_decode(mqc); + flags2 += runlen * t1->flags_stride; + data2 += runlen * t1->w; + for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { + flags2 += t1->flags_stride; + if (agg && (j == k + runlen)) { + t1_dec_clnpass_step_partial(t1, flags2, data2, orient, oneplushalf); + } else { + t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); + } + data2 += t1->w; + } + } else { + flags2 += t1->flags_stride; + t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + flags2 += t1->flags_stride; + t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + } + } + data1 += t1->w << 2; + flags1 += t1->flags_stride << 2; + } + for (i = 0; i < t1->w; ++i) { + int *data2 = data1 + i; + flag_t *flags2 = flags1 + i; + for (j = k; j < t1->h; ++j) { + flags2 += t1->flags_stride; + t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); + data2 += t1->w; + } + } + } + + if (segsym) { + int v = 0; + mqc_setcurctx(mqc, T1_CTXNO_UNI); + v = mqc_decode(mqc); + v = (v << 1) | mqc_decode(mqc); + v = (v << 1) | mqc_decode(mqc); + v = (v << 1) | mqc_decode(mqc); + /* + if (v!=0xa) { + opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); + } + */ + } +} /* VSC and BYPASS by Antonin */ + + +/** mod fixed_quality */ +static double t1_getwmsedec( + int nmsedec, + int compno, + int level, + int orient, + int bpno, + int qmfbid, + double stepsize, + int numcomps, + int mct) +{ + double w1, w2, wmsedec; + if (qmfbid == 1) { + w1 = (mct && numcomps==3) ? mct_getnorm(compno) : 1.0; + w2 = dwt_getnorm(level, orient); + } else { /* if (qmfbid == 0) */ + w1 = (mct && numcomps==3) ? mct_getnorm_real(compno) : 1.0; + w2 = dwt_getnorm_real(level, orient); + } + wmsedec = w1 * w2 * stepsize * (1 << bpno); + wmsedec *= wmsedec * nmsedec / 8192.0; + + return wmsedec; +} + +static opj_bool allocate_buffers( + opj_t1_t *t1, + int w, + int h) +{ + int datasize=w * h; + int flagssize; + + if(datasize > t1->datasize){ + opj_aligned_free(t1->data); + t1->data = (int*) opj_aligned_malloc(datasize * sizeof(int)); + if(!t1->data){ + return OPJ_FALSE; + } + t1->datasize=datasize; + } + memset(t1->data,0,datasize * sizeof(int)); + + t1->flags_stride=w+2; + flagssize=t1->flags_stride * (h+2); + + if(flagssize > t1->flagssize){ + opj_aligned_free(t1->flags); + t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t)); + if(!t1->flags){ + return OPJ_FALSE; + } + t1->flagssize=flagssize; + } + memset(t1->flags,0,flagssize * sizeof(flag_t)); + + t1->w=w; + t1->h=h; + + return OPJ_TRUE; +} + +/** mod fixed_quality */ +static void t1_encode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + int orient, + int compno, + int level, + int qmfbid, + double stepsize, + int cblksty, + int numcomps, + int mct, + opj_tcd_tile_t * tile) +{ + double cumwmsedec = 0.0; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + int passno, bpno, passtype; + int nmsedec = 0; + int i, max; + char type = T1_TYPE_MQ; + double tempwmsedec; + + max = 0; + for (i = 0; i < t1->w * t1->h; ++i) { + int tmp = abs(t1->data[i]); + max = int_max(max, tmp); + } + + cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0; + + bpno = cblk->numbps - 1; + passtype = 2; + + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + mqc_init_enc(mqc, cblk->data); + + for (passno = 0; bpno >= 0; ++passno) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + int correction = 3; + type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + + switch (passtype) { + case 0: + t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty); + break; + case 1: + t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty); + break; + case 2: + t1_enc_clnpass(t1, bpno, orient, &nmsedec, cblksty); + /* code switch SEGMARK (i.e. SEGSYM) */ + if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) + mqc_segmark_enc(mqc); + break; + } + + /* fixed_quality */ + tempwmsedec = t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps, mct); + cumwmsedec += tempwmsedec; + tile->distotile += tempwmsedec; + + /* Code switch "RESTART" (i.e. TERMALL) */ + if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) { + if (type == T1_TYPE_RAW) { + mqc_flush(mqc); + correction = 1; + /* correction = mqc_bypass_flush_enc(); */ + } else { /* correction = mqc_restart_enc(); */ + mqc_flush(mqc); + correction = 1; + } + pass->term = 1; + } else { + if (((bpno < (cblk->numbps - 4) && (passtype > 0)) + || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) { + if (type == T1_TYPE_RAW) { + mqc_flush(mqc); + correction = 1; + /* correction = mqc_bypass_flush_enc(); */ + } else { /* correction = mqc_restart_enc(); */ + mqc_flush(mqc); + correction = 1; + } + pass->term = 1; + } else { + pass->term = 0; + } + } + + if (++passtype == 3) { + passtype = 0; + bpno--; + } + + if (pass->term && bpno > 0) { + type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + if (type == T1_TYPE_RAW) + mqc_bypass_init_enc(mqc); + else + mqc_restart_init_enc(mqc); + } + + pass->distortiondec = cumwmsedec; + pass->rate = mqc_numbytes(mqc) + correction; /* FIXME */ + + /* Code-switch "RESET" */ + if (cblksty & J2K_CCP_CBLKSTY_RESET) + mqc_reset_enc(mqc); + } + + /* Code switch "ERTERM" (i.e. PTERM) */ + if (cblksty & J2K_CCP_CBLKSTY_PTERM) + mqc_erterm_enc(mqc); + else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY)) + mqc_flush(mqc); + + cblk->totalpasses = passno; + + for (passno = 0; passnototalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + if (pass->rate > mqc_numbytes(mqc)) + pass->rate = mqc_numbytes(mqc); + /*Preventing generation of FF as last data byte of a pass*/ + if((pass->rate>1) && (cblk->data[pass->rate - 1] == 0xFF)){ + pass->rate--; + } + pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); + } +} + +static void t1_decode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + int orient, + int roishift, + int cblksty) +{ + opj_raw_t *raw = t1->raw; /* RAW component */ + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + int bpno, passtype; + int segno, passno; + char type = T1_TYPE_MQ; /* BYPASS mode */ + + if(!allocate_buffers( + t1, + cblk->x1 - cblk->x0, + cblk->y1 - cblk->y0)) + { + return; + } + + bpno = roishift + cblk->numbps - 1; + passtype = 2; + + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + + for (segno = 0; segno < cblk->numsegs; ++segno) { + opj_tcd_seg_t *seg = &cblk->segs[segno]; + + /* BYPASS mode */ + type = ((bpno <= (cblk->numbps - 1) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + /* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */ + if(seg->data == NULL){ + continue; + } + if (type == T1_TYPE_RAW) { + raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len); + } else { + mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len); + } + + for (passno = 0; passno < seg->numpasses; ++passno) { + switch (passtype) { + case 0: + if (type == T1_TYPE_RAW) { + t1_dec_sigpass_raw(t1, bpno+1, orient, cblksty); + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + t1_dec_sigpass_mqc_vsc(t1, bpno+1, orient); + } else { + t1_dec_sigpass_mqc(t1, bpno+1, orient); + } + } + break; + case 1: + if (type == T1_TYPE_RAW) { + t1_dec_refpass_raw(t1, bpno+1, cblksty); + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + t1_dec_refpass_mqc_vsc(t1, bpno+1); + } else { + t1_dec_refpass_mqc(t1, bpno+1); + } + } + break; + case 2: + t1_dec_clnpass(t1, bpno+1, orient, cblksty); + break; + } + + if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + } + if (++passtype == 3) { + passtype = 0; + bpno--; + } + } + } +} + +/* ----------------------------------------------------------------------- */ + +opj_t1_t* t1_create(opj_common_ptr cinfo) { + opj_t1_t *t1 = (opj_t1_t*) opj_malloc(sizeof(opj_t1_t)); + if(!t1) + return NULL; + + t1->cinfo = cinfo; + /* create MQC and RAW handles */ + t1->mqc = mqc_create(); + t1->raw = raw_create(); + + t1->data=NULL; + t1->flags=NULL; + t1->datasize=0; + t1->flagssize=0; + + return t1; +} + +void t1_destroy(opj_t1_t *t1) { + if(t1) { + /* destroy MQC and RAW handles */ + mqc_destroy(t1->mqc); + raw_destroy(t1->raw); + opj_aligned_free(t1->data); + opj_aligned_free(t1->flags); + opj_free(t1); + } +} + +void t1_encode_cblks( + opj_t1_t *t1, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp) +{ + int compno, resno, bandno, precno, cblkno; + + tile->distotile = 0; /* fixed_quality */ + + for (compno = 0; compno < tile->numcomps; ++compno) { + opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; + opj_tccp_t* tccp = &tcp->tccps[compno]; + int tile_w = tilec->x1 - tilec->x0; + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* restrict band = &res->bands[bandno]; + int bandconst = 8192 * 8192 / ((int) floor(band->stepsize * 8192)); + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + int* restrict datap; + int* restrict tiledp; + int cblk_w; + int cblk_h; + int i, j; + + int x = cblk->x0 - band->x0; + int y = cblk->y0 - band->y0; + if (band->bandno & 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + if(!allocate_buffers( + t1, + cblk->x1 - cblk->x0, + cblk->y1 - cblk->y0)) + { + return; + } + + datap=t1->data; + cblk_w = t1->w; + cblk_h = t1->h; + + tiledp=&tilec->data[(y * tile_w) + x]; + if (tccp->qmfbid == 1) { + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + int tmp = tiledp[(j * tile_w) + i]; + datap[(j * cblk_w) + i] = tmp << T1_NMSEDEC_FRACBITS; + } + } + } else { /* if (tccp->qmfbid == 0) */ + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + int tmp = tiledp[(j * tile_w) + i]; + datap[(j * cblk_w) + i] = + fix_mul( + tmp, + bandconst) >> (11 - T1_NMSEDEC_FRACBITS); + } + } + } + + t1_encode_cblk( + t1, + cblk, + band->bandno, + compno, + tilec->numresolutions - 1 - resno, + tccp->qmfbid, + band->stepsize, + tccp->cblksty, + tile->numcomps, + tcp->mct, + tile); + + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ +} + +void t1_decode_cblks( + opj_t1_t* t1, + opj_tcd_tilecomp_t* tilec, + opj_tccp_t* tccp) +{ + int resno, bandno, precno, cblkno; + + int tile_w = tilec->x1 - tilec->x0; + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t* res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* restrict band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t* precinct = &band->precincts[precno]; + + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + int* restrict datap; + int cblk_w, cblk_h; + int x, y; + int i, j; + + t1_decode_cblk( + t1, + cblk, + band->bandno, + tccp->roishift, + tccp->cblksty); + + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + if (band->bandno & 1) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + datap=t1->data; + cblk_w = t1->w; + cblk_h = t1->h; + + if (tccp->roishift) { + int thresh = 1 << tccp->roishift; + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + int val = datap[(j * cblk_w) + i]; + int mag = abs(val); + if (mag >= thresh) { + mag >>= tccp->roishift; + datap[(j * cblk_w) + i] = val < 0 ? -mag : mag; + } + } + } + } + + if (tccp->qmfbid == 1) { + int* restrict tiledp = &tilec->data[(y * tile_w) + x]; + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + int tmp = datap[(j * cblk_w) + i]; + ((int*)tiledp)[(j * tile_w) + i] = tmp / 2; + } + } + } else { /* if (tccp->qmfbid == 0) */ + float* restrict tiledp = (float*) &tilec->data[(y * tile_w) + x]; + for (j = 0; j < cblk_h; ++j) { + float* restrict tiledp2 = tiledp; + for (i = 0; i < cblk_w; ++i) { + float tmp = *datap * band->stepsize; + *tiledp2 = tmp; + datap++; + tiledp2++; + } + tiledp += tile_w; + } + } + opj_free(cblk->data); + opj_free(cblk->segs); + } /* cblkno */ + opj_free(precinct->cblks.dec); + precinct->cblks.dec = NULL; + } /* precno */ + } /* bandno */ + } /* resno */ +} + diff --git a/src/add-ons/translators/icns/openjpeg/t1.h b/src/add-ons/translators/icns/openjpeg/t1.h new file mode 100644 index 0000000000..572ec88d2f --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/t1.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __T1_H +#define __T1_H +/** +@file t1.h +@brief Implementation of the tier-1 coding (coding of code-block coefficients) (T1) + +The functions in T1.C have for goal to realize the tier-1 coding operation. The functions +in T1.C are used by some function in TCD.C. +*/ + +/** @defgroup T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ + +/* ----------------------------------------------------------------------- */ +#define T1_NMSEDEC_BITS 7 + +#define T1_SIG_NE 0x0001 /**< Context orientation : North-East direction */ +#define T1_SIG_SE 0x0002 /**< Context orientation : South-East direction */ +#define T1_SIG_SW 0x0004 /**< Context orientation : South-West direction */ +#define T1_SIG_NW 0x0008 /**< Context orientation : North-West direction */ +#define T1_SIG_N 0x0010 /**< Context orientation : North direction */ +#define T1_SIG_E 0x0020 /**< Context orientation : East direction */ +#define T1_SIG_S 0x0040 /**< Context orientation : South direction */ +#define T1_SIG_W 0x0080 /**< Context orientation : West direction */ +#define T1_SIG_OTH (T1_SIG_N|T1_SIG_NE|T1_SIG_E|T1_SIG_SE|T1_SIG_S|T1_SIG_SW|T1_SIG_W|T1_SIG_NW) +#define T1_SIG_PRIM (T1_SIG_N|T1_SIG_E|T1_SIG_S|T1_SIG_W) + +#define T1_SGN_N 0x0100 +#define T1_SGN_E 0x0200 +#define T1_SGN_S 0x0400 +#define T1_SGN_W 0x0800 +#define T1_SGN (T1_SGN_N|T1_SGN_E|T1_SGN_S|T1_SGN_W) + +#define T1_SIG 0x1000 +#define T1_REFINE 0x2000 +#define T1_VISIT 0x4000 + +#define T1_NUMCTXS_ZC 9 +#define T1_NUMCTXS_SC 5 +#define T1_NUMCTXS_MAG 3 +#define T1_NUMCTXS_AGG 1 +#define T1_NUMCTXS_UNI 1 + +#define T1_CTXNO_ZC 0 +#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC) +#define T1_CTXNO_MAG (T1_CTXNO_SC+T1_NUMCTXS_SC) +#define T1_CTXNO_AGG (T1_CTXNO_MAG+T1_NUMCTXS_MAG) +#define T1_CTXNO_UNI (T1_CTXNO_AGG+T1_NUMCTXS_AGG) +#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI) + +#define T1_NMSEDEC_FRACBITS (T1_NMSEDEC_BITS-1) + +#define T1_TYPE_MQ 0 /**< Normal coding using entropy coder */ +#define T1_TYPE_RAW 1 /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/ + +/* ----------------------------------------------------------------------- */ + +typedef short flag_t; + +/** +Tier-1 coding (coding of code-block coefficients) +*/ +typedef struct opj_t1 { + /** codec context */ + opj_common_ptr cinfo; + + /** MQC component */ + opj_mqc_t *mqc; + /** RAW component */ + opj_raw_t *raw; + + int *data; + flag_t *flags; + int w; + int h; + int datasize; + int flagssize; + int flags_stride; +} opj_t1_t; + +#define MACRO_t1_flags(x,y) t1->flags[((x)*(t1->flags_stride))+(y)] + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new T1 handle +and initialize the look-up tables of the Tier-1 coder/decoder +@return Returns a new T1 handle if successful, returns NULL otherwise +@see t1_init_luts +*/ +opj_t1_t* t1_create(opj_common_ptr cinfo); +/** +Destroy a previously created T1 handle +@param t1 T1 handle to destroy +*/ +void t1_destroy(opj_t1_t *t1); +/** +Encode the code-blocks of a tile +@param t1 T1 handle +@param tile The tile to encode +@param tcp Tile coding parameters +*/ +void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp); +/** +Decode the code-blocks of a tile +@param t1 T1 handle +@param tilec The tile to decode +@param tccp Tile coding parameters +*/ +void t1_decode_cblks(opj_t1_t* t1, opj_tcd_tilecomp_t* tilec, opj_tccp_t* tccp); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __T1_H */ diff --git a/src/add-ons/translators/icns/openjpeg/t1_generate_luts.c b/src/add-ons/translators/icns/openjpeg/t1_generate_luts.c new file mode 100644 index 0000000000..39880414fb --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/t1_generate_luts.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Callum Lerwick + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" +#include + +static int t1_init_ctxno_zc(int f, int orient) { + int h, v, d, n, t, hv; + n = 0; + h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0); + v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0); + d = ((f & T1_SIG_NW) != 0) + ((f & T1_SIG_NE) != 0) + ((f & T1_SIG_SE) != 0) + ((f & T1_SIG_SW) != 0); + + switch (orient) { + case 2: + t = h; + h = v; + v = t; + case 0: + case 1: + if (!h) { + if (!v) { + if (!d) + n = 0; + else if (d == 1) + n = 1; + else + n = 2; + } else if (v == 1) { + n = 3; + } else { + n = 4; + } + } else if (h == 1) { + if (!v) { + if (!d) + n = 5; + else + n = 6; + } else { + n = 7; + } + } else + n = 8; + break; + case 3: + hv = h + v; + if (!d) { + if (!hv) { + n = 0; + } else if (hv == 1) { + n = 1; + } else { + n = 2; + } + } else if (d == 1) { + if (!hv) { + n = 3; + } else if (hv == 1) { + n = 4; + } else { + n = 5; + } + } else if (d == 2) { + if (!hv) { + n = 6; + } else { + n = 7; + } + } else { + n = 8; + } + break; + } + + return (T1_CTXNO_ZC + n); +} + +static int t1_init_ctxno_sc(int f) { + int hc, vc, n; + n = 0; + + hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == + T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), + 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == + (T1_SIG_E | T1_SGN_E)) + + ((f & (T1_SIG_W | T1_SGN_W)) == + (T1_SIG_W | T1_SGN_W)), 1); + + vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == + T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), + 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == + (T1_SIG_N | T1_SGN_N)) + + ((f & (T1_SIG_S | T1_SGN_S)) == + (T1_SIG_S | T1_SGN_S)), 1); + + if (hc < 0) { + hc = -hc; + vc = -vc; + } + if (!hc) { + if (vc == -1) + n = 1; + else if (!vc) + n = 0; + else + n = 1; + } else if (hc == 1) { + if (vc == -1) + n = 2; + else if (!vc) + n = 3; + else + n = 4; + } + + return (T1_CTXNO_SC + n); +} + +static int t1_init_spb(int f) { + int hc, vc, n; + + hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == + T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), + 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == + (T1_SIG_E | T1_SGN_E)) + + ((f & (T1_SIG_W | T1_SGN_W)) == + (T1_SIG_W | T1_SGN_W)), 1); + + vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == + T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), + 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == + (T1_SIG_N | T1_SGN_N)) + + ((f & (T1_SIG_S | T1_SGN_S)) == + (T1_SIG_S | T1_SGN_S)), 1); + + if (!hc && !vc) + n = 0; + else + n = (!(hc > 0 || (!hc && vc > 0))); + + return n; +} + +void dump_array16(int array[],int size){ + int i; + --size; + for (i = 0; i < size; ++i) { + printf("0x%04x, ", array[i]); + if(!((i+1)&0x7)) + printf("\n "); + } + printf("0x%04x\n};\n\n", array[size]); +} + +int main(){ + int i, j; + double u, v, t; + + int lut_ctxno_zc[1024]; + int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS]; + + printf("/* This file was automatically generated by t1_generate_luts.c */\n\n"); + + // lut_ctxno_zc + for (j = 0; j < 4; ++j) { + for (i = 0; i < 256; ++i) { + int orient = j; + if (orient == 2) { + orient = 1; + } else if (orient == 1) { + orient = 2; + } + lut_ctxno_zc[(orient << 8) | i] = t1_init_ctxno_zc(i, j); + } + } + + printf("static char lut_ctxno_zc[1024] = {\n "); + for (i = 0; i < 1023; ++i) { + printf("%i, ", lut_ctxno_zc[i]); + if(!((i+1)&0x1f)) + printf("\n "); + } + printf("%i\n};\n\n", lut_ctxno_zc[1023]); + + // lut_ctxno_sc + printf("static char lut_ctxno_sc[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("0x%x, ", t1_init_ctxno_sc(i << 4)); + if(!((i+1)&0xf)) + printf("\n "); + } + printf("0x%x\n};\n\n", t1_init_ctxno_sc(255 << 4)); + + // lut_spb + printf("static char lut_spb[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("%i, ", t1_init_spb(i << 4)); + if(!((i+1)&0x1f)) + printf("\n "); + } + printf("%i\n};\n\n", t1_init_spb(255 << 4)); + + /* FIXME FIXME FIXME */ + /* fprintf(stdout,"nmsedec luts:\n"); */ + for (i = 0; i < (1 << T1_NMSEDEC_BITS); ++i) { + t = i / pow(2, T1_NMSEDEC_FRACBITS); + u = t; + v = t - 1.5; + lut_nmsedec_sig[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_sig0[i] = + int_max(0, + (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + u = t - 1.0; + if (i & (1 << (T1_NMSEDEC_BITS - 1))) { + v = t - 1.5; + } else { + v = t - 0.5; + } + lut_nmsedec_ref[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_ref0[i] = + int_max(0, + (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + } + + printf("static short lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_sig, 1 << T1_NMSEDEC_BITS); + + printf("static short lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_sig0, 1 << T1_NMSEDEC_BITS); + + printf("static short lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_ref, 1 << T1_NMSEDEC_BITS); + + printf("static short lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_ref0, 1 << T1_NMSEDEC_BITS); + + return 0; +} diff --git a/src/add-ons/translators/icns/openjpeg/t1_luts.h b/src/add-ons/translators/icns/openjpeg/t1_luts.h new file mode 100644 index 0000000000..e5e33f6656 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/t1_luts.h @@ -0,0 +1,143 @@ +/* This file was automatically generated by t1_generate_luts.c */ + +static char lut_ctxno_zc[1024] = { + 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 3, 3, 6, 3, 6, 6, 8, 3, 6, 6, 8, 6, 8, 8, 8, 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, + 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8 +}; + +static char lut_ctxno_sc[256] = { + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd +}; + +static char lut_spb[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static short lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0180, 0x0300, 0x0480, 0x0600, 0x0780, 0x0900, 0x0a80, + 0x0c00, 0x0d80, 0x0f00, 0x1080, 0x1200, 0x1380, 0x1500, 0x1680, + 0x1800, 0x1980, 0x1b00, 0x1c80, 0x1e00, 0x1f80, 0x2100, 0x2280, + 0x2400, 0x2580, 0x2700, 0x2880, 0x2a00, 0x2b80, 0x2d00, 0x2e80, + 0x3000, 0x3180, 0x3300, 0x3480, 0x3600, 0x3780, 0x3900, 0x3a80, + 0x3c00, 0x3d80, 0x3f00, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5100, 0x5280, + 0x5400, 0x5580, 0x5700, 0x5880, 0x5a00, 0x5b80, 0x5d00, 0x5e80, + 0x6000, 0x6180, 0x6300, 0x6480, 0x6600, 0x6780, 0x6900, 0x6a80, + 0x6c00, 0x6d80, 0x6f00, 0x7080, 0x7200, 0x7380, 0x7500, 0x7680 +}; + +static short lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00, + 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2680, 0x2780, + 0x2880, 0x2980, 0x2b00, 0x2c00, 0x2d00, 0x2e80, 0x2f80, 0x3100, + 0x3200, 0x3380, 0x3480, 0x3600, 0x3700, 0x3880, 0x3a00, 0x3b00, + 0x3c80, 0x3e00, 0x3f80, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5180, 0x5300, + 0x5480, 0x5600, 0x5800, 0x5980, 0x5b00, 0x5d00, 0x5e80, 0x6080, + 0x6200, 0x6400, 0x6580, 0x6780, 0x6900, 0x6b00, 0x6d00, 0x6e80, + 0x7080, 0x7280, 0x7480, 0x7600, 0x7800, 0x7a00, 0x7c00, 0x7e00 +}; + +static short lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = { + 0x1800, 0x1780, 0x1700, 0x1680, 0x1600, 0x1580, 0x1500, 0x1480, + 0x1400, 0x1380, 0x1300, 0x1280, 0x1200, 0x1180, 0x1100, 0x1080, + 0x1000, 0x0f80, 0x0f00, 0x0e80, 0x0e00, 0x0d80, 0x0d00, 0x0c80, + 0x0c00, 0x0b80, 0x0b00, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0500, 0x0480, + 0x0400, 0x0380, 0x0300, 0x0280, 0x0200, 0x0180, 0x0100, 0x0080, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, + 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b00, 0x0b80, + 0x0c00, 0x0c80, 0x0d00, 0x0d80, 0x0e00, 0x0e80, 0x0f00, 0x0f80, + 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, + 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780 +}; + +static short lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = { + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x1b00, 0x1a80, 0x1980, + 0x1880, 0x1780, 0x1700, 0x1600, 0x1500, 0x1480, 0x1380, 0x1300, + 0x1200, 0x1180, 0x1080, 0x1000, 0x0f00, 0x0e80, 0x0e00, 0x0d00, + 0x0c80, 0x0c00, 0x0b80, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0580, 0x0500, + 0x0480, 0x0400, 0x0400, 0x0380, 0x0300, 0x0300, 0x0280, 0x0280, + 0x0200, 0x0200, 0x0180, 0x0180, 0x0100, 0x0100, 0x0100, 0x0080, + 0x0080, 0x0080, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00 +}; + diff --git a/src/add-ons/translators/icns/openjpeg/t2.c b/src/add-ons/translators/icns/openjpeg/t2.c new file mode 100644 index 0000000000..cae29f09b1 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/t2.c @@ -0,0 +1,822 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/** @defgroup T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static void t2_putcommacode(opj_bio_t *bio, int n); +static int t2_getcommacode(opj_bio_t *bio); +/** +Variable length code for signalling delta Zil (truncation point) +@param bio Bit Input/Output component +@param n delta Zil +*/ +static void t2_putnumpasses(opj_bio_t *bio, int n); +static int t2_getnumpasses(opj_bio_t *bio); +/** +Encode a packet of a tile to a destination buffer +@param tile Tile for which to write the packets +@param tcp Tile coding parameters +@param pi Packet identity +@param dest Destination buffer +@param len Length of the destination buffer +@param cstr_info Codestream information structure +@param tileno Number of the tile encoded +@return +*/ +static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_codestream_info_t *cstr_info, int tileno); +/** +@param cblk +@param index +@param cblksty +@param first +*/ +static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first); +/** +Decode a packet of a tile from a source buffer +@param t2 T2 handle +@param src Source buffer +@param len Length of the source buffer +@param tile Tile for which to write the packets +@param tcp Tile coding parameters +@param pi Packet identity +@param pack_info Packet information +@return +*/ +static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, + opj_tcp_t *tcp, opj_pi_iterator_t *pi, opj_packet_info_t *pack_info); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +/* #define RESTART 0x04 */ + +static void t2_putcommacode(opj_bio_t *bio, int n) { + while (--n >= 0) { + bio_write(bio, 1, 1); + } + bio_write(bio, 0, 1); +} + +static int t2_getcommacode(opj_bio_t *bio) { + int n; + for (n = 0; bio_read(bio, 1); n++) { + ; + } + return n; +} + +static void t2_putnumpasses(opj_bio_t *bio, int n) { + if (n == 1) { + bio_write(bio, 0, 1); + } else if (n == 2) { + bio_write(bio, 2, 2); + } else if (n <= 5) { + bio_write(bio, 0xc | (n - 3), 4); + } else if (n <= 36) { + bio_write(bio, 0x1e0 | (n - 6), 9); + } else if (n <= 164) { + bio_write(bio, 0xff80 | (n - 37), 16); + } +} + +static int t2_getnumpasses(opj_bio_t *bio) { + int n; + if (!bio_read(bio, 1)) + return 1; + if (!bio_read(bio, 1)) + return 2; + if ((n = bio_read(bio, 2)) != 3) + return (3 + n); + if ((n = bio_read(bio, 5)) != 31) + return (6 + n); + return (37 + bio_read(bio, 7)); +} + +static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_iterator_t *pi, unsigned char *dest, int length, opj_codestream_info_t *cstr_info, int tileno) { + int bandno, cblkno; + unsigned char *c = dest; + + int compno = pi->compno; /* component value */ + int resno = pi->resno; /* resolution level value */ + int precno = pi->precno; /* precinct value */ + int layno = pi->layno; /* quality layer value */ + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + opj_bio_t *bio = NULL; /* BIO component */ + + /* */ + if (tcp->csty & J2K_CP_CSTY_SOP) { + c[0] = 255; + c[1] = 145; + c[2] = 0; + c[3] = 4; + c[4] = (unsigned char)((tile->packno % 65536) / 256); + c[5] = (unsigned char)((tile->packno % 65536) % 256); + c += 6; + } + /* */ + + if (!layno) { + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + tgt_reset(prc->incltree); + tgt_reset(prc->imsbtree); + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + cblk->numpasses = 0; + tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk->numbps); + } + } + } + + bio = bio_create(); + bio_init_enc(bio, c, length); + bio_write(bio, 1, 1); /* Empty header bit */ + + /* Writing Packet header */ + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + if (!cblk->numpasses && layer->numpasses) { + tgt_setvalue(prc->incltree, cblkno, layno); + } + } + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + int increment = 0; + int nump = 0; + int len = 0, passno; + /* cblk inclusion bits */ + if (!cblk->numpasses) { + tgt_encode(bio, prc->incltree, cblkno, layno + 1); + } else { + bio_write(bio, layer->numpasses != 0, 1); + } + /* if cblk not included, go to the next cblk */ + if (!layer->numpasses) { + continue; + } + /* if first instance of cblk --> zero bit-planes information */ + if (!cblk->numpasses) { + cblk->numlenbits = 3; + tgt_encode(bio, prc->imsbtree, cblkno, 999); + } + /* number of coding passes included */ + t2_putnumpasses(bio, layer->numpasses); + + /* computation of the increase of the length indicator and insertion in the header */ + for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + nump++; + len += pass->len; + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + increment = int_max(increment, int_floorlog2(len) + 1 - (cblk->numlenbits + int_floorlog2(nump))); + len = 0; + nump = 0; + } + } + t2_putcommacode(bio, increment); + + /* computation of the new Length indicator */ + cblk->numlenbits += increment; + + /* insertion of the codeword segment length */ + for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + nump++; + len += pass->len; + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + bio_write(bio, len, cblk->numlenbits + int_floorlog2(nump)); + len = 0; + nump = 0; + } + } + } + } + + if (bio_flush(bio)) { + bio_destroy(bio); + return -999; /* modified to eliminate longjmp !! */ + } + + c += bio_numbytes(bio); + bio_destroy(bio); + + /* */ + if (tcp->csty & J2K_CP_CSTY_EPH) { + c[0] = 255; + c[1] = 146; + c += 2; + } + /* */ + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value */ + if(cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->end_ph_pos = (int)(c - dest); + } + /* INDEX >> */ + + /* Writing the packet body */ + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + if (!layer->numpasses) { + continue; + } + if (c + layer->len > dest + length) { + return -999; + } + + memcpy(c, layer->data, layer->len); + cblk->numpasses += layer->numpasses; + c += layer->len; + /* << INDEX */ + if(cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->disto += layer->disto; + if (cstr_info->D_max < info_PK->disto) { + cstr_info->D_max = info_PK->disto; + } + } + /* INDEX >> */ + } + } + + return (c - dest); +} + +static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) { + opj_tcd_seg_t* seg; + opj_tcd_seg_t* segs; + segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t)); + + if (segs == NULL) + { + return OPJ_FALSE; + } + cblk->segs = segs; + + seg = &cblk->segs[index]; + seg->data = NULL; + seg->dataindex = 0; + seg->numpasses = 0; + seg->len = 0; + if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { + seg->maxpasses = 1; + } + else if (cblksty & J2K_CCP_CBLKSTY_LAZY) { + if (first) { + seg->maxpasses = 10; + } else { + seg->maxpasses = (((seg - 1)->maxpasses == 1) || ((seg - 1)->maxpasses == 10)) ? 2 : 1; + } + } else { + seg->maxpasses = 109; + } + + return OPJ_TRUE; +} + +static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, + opj_tcp_t *tcp, opj_pi_iterator_t *pi, opj_packet_info_t *pack_info) { + int bandno, cblkno; + unsigned char *c = src; + + opj_cp_t *cp = t2->cp; + + int compno = pi->compno; /* component value */ + int resno = pi->resno; /* resolution level value */ + int precno = pi->precno; /* precinct value */ + int layno = pi->layno; /* quality layer value */ + + opj_tcd_resolution_t* res = &tile->comps[compno].resolutions[resno]; + + unsigned char *hd = NULL; + int present; + + opj_bio_t *bio = NULL; /* BIO component */ + + if (layno == 0) { + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue; + + tgt_reset(prc->incltree); + tgt_reset(prc->imsbtree); + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno]; + cblk->numsegs = 0; + } + } + } + + /* SOP markers */ + + if (tcp->csty & J2K_CP_CSTY_SOP) { + if ((*c) != 0xff || (*(c + 1) != 0x91)) { + opj_event_msg(t2->cinfo, EVT_WARNING, "Expected SOP marker\n"); + } else { + c += 6; + } + + /** TODO : check the Nsop value */ + } + + /* + When the marker PPT/PPM is used the packet header are store in PPT/PPM marker + This part deal with this caracteristic + step 1: Read packet header in the saved structure + step 2: Return to codestream for decoding + */ + + bio = bio_create(); + + if (cp->ppm == 1) { /* PPM */ + hd = cp->ppm_data; + bio_init_dec(bio, hd, cp->ppm_len); + } else if (tcp->ppt == 1) { /* PPT */ + hd = tcp->ppt_data; + bio_init_dec(bio, hd, tcp->ppt_len); + } else { /* Normal Case */ + hd = c; + bio_init_dec(bio, hd, src+len-hd); + } + + present = bio_read(bio, 1); + + if (!present) { + bio_inalign(bio); + hd += bio_numbytes(bio); + bio_destroy(bio); + + /* EPH markers */ + + if (tcp->csty & J2K_CP_CSTY_EPH) { + if ((*hd) != 0xff || (*(hd + 1) != 0x92)) { + printf("Error : expected EPH marker\n"); + } else { + hd += 2; + } + } + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value*/ + if(pack_info) { + pack_info->end_ph_pos = (int)(c - src); + } + /* INDEX >> */ + + if (cp->ppm == 1) { /* PPM case */ + cp->ppm_len += cp->ppm_data-hd; + cp->ppm_data = hd; + return (c - src); + } + if (tcp->ppt == 1) { /* PPT case */ + tcp->ppt_len+=tcp->ppt_data-hd; + tcp->ppt_data = hd; + return (c - src); + } + + return (hd - src); + } + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + int included, increment, n, segno; + opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno]; + /* if cblk not yet included before --> inclusion tagtree */ + if (!cblk->numsegs) { + included = tgt_decode(bio, prc->incltree, cblkno, layno + 1); + /* else one bit */ + } else { + included = bio_read(bio, 1); + } + /* if cblk not included */ + if (!included) { + cblk->numnewpasses = 0; + continue; + } + /* if cblk not yet included --> zero-bitplane tagtree */ + if (!cblk->numsegs) { + int i, numimsbs; + for (i = 0; !tgt_decode(bio, prc->imsbtree, cblkno, i); i++) { + ; + } + numimsbs = i - 1; + cblk->numbps = band->numbps - numimsbs; + cblk->numlenbits = 3; + } + /* number of coding passes */ + cblk->numnewpasses = t2_getnumpasses(bio); + increment = t2_getcommacode(bio); + /* length indicator increment */ + cblk->numlenbits += increment; + segno = 0; + if (!cblk->numsegs) { + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } + } else { + segno = cblk->numsegs - 1; + if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) { + ++segno; + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } + } + } + n = cblk->numnewpasses; + + do { + cblk->segs[segno].numnewpasses = int_min(cblk->segs[segno].maxpasses - cblk->segs[segno].numpasses, n); + cblk->segs[segno].newlen = bio_read(bio, cblk->numlenbits + int_floorlog2(cblk->segs[segno].numnewpasses)); + n -= cblk->segs[segno].numnewpasses; + if (n > 0) { + ++segno; + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } + } + } while (n > 0); + } + } + + if (bio_inalign(bio)) { + bio_destroy(bio); + return -999; + } + + hd += bio_numbytes(bio); + bio_destroy(bio); + + /* EPH markers */ + if (tcp->csty & J2K_CP_CSTY_EPH) { + if ((*hd) != 0xff || (*(hd + 1) != 0x92)) { + opj_event_msg(t2->cinfo, EVT_ERROR, "Expected EPH marker\n"); + return -999; + } else { + hd += 2; + } + } + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value*/ + if(pack_info) { + pack_info->end_ph_pos = (int)(hd - src); + } + /* INDEX >> */ + + if (cp->ppm==1) { + cp->ppm_len+=cp->ppm_data-hd; + cp->ppm_data = hd; + } else if (tcp->ppt == 1) { + tcp->ppt_len+=tcp->ppt_data-hd; + tcp->ppt_data = hd; + } else { + c=hd; + } + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno]; + opj_tcd_seg_t *seg = NULL; + if (!cblk->numnewpasses) + continue; + if (!cblk->numsegs) { + seg = &cblk->segs[0]; + cblk->numsegs++; + cblk->len = 0; + } else { + seg = &cblk->segs[cblk->numsegs - 1]; + if (seg->numpasses == seg->maxpasses) { + seg++; + cblk->numsegs++; + } + } + + do { + if (c + seg->newlen > src + len) { + return -999; + } + +#ifdef USE_JPWL + /* we need here a j2k handle to verify if making a check to + the validity of cblocks parameters is selected from user (-W) */ + + /* let's check that we are not exceeding */ + if ((cblk->len + seg->newlen) > 8192) { + opj_event_msg(t2->cinfo, EVT_WARNING, + "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + seg->newlen, cblkno, precno, bandno, resno, compno); + if (!JPWL_ASSUME) { + opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return -999; + } + seg->newlen = 8192 - cblk->len; + opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen); + break; + }; + +#endif /* USE_JPWL */ + + cblk->data = (unsigned char*) opj_realloc(cblk->data, (cblk->len + seg->newlen) * sizeof(unsigned char)); + memcpy(cblk->data + cblk->len, c, seg->newlen); + if (seg->numpasses == 0) { + seg->data = &cblk->data; + seg->dataindex = cblk->len; + } + c += seg->newlen; + cblk->len += seg->newlen; + seg->len += seg->newlen; + seg->numpasses += seg->numnewpasses; + cblk->numnewpasses -= seg->numnewpasses; + if (cblk->numnewpasses > 0) { + seg++; + cblk->numsegs++; + } + } while (cblk->numnewpasses > 0); + } + } + + return (c - src); +} + +/* ----------------------------------------------------------------------- */ + +int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_codestream_info_t *cstr_info,int tpnum, int tppos,int pino, J2K_T2_MODE t2_mode, int cur_totnum_tp){ + unsigned char *c = dest; + int e = 0; + int compno; + opj_pi_iterator_t *pi = NULL; + int poc; + opj_image_t *image = t2->image; + opj_cp_t *cp = t2->cp; + opj_tcp_t *tcp = &cp->tcps[tileno]; + int pocno = cp->cinema == CINEMA4K_24? 2: 1; + int maxcomp = cp->max_comp_size > 0 ? image->numcomps : 1; + + pi = pi_initialise_encode(image, cp, tileno, t2_mode); + if(!pi) { + /* TODO: throw an error */ + return -999; + } + + if(t2_mode == THRESH_CALC ){ /* Calculating threshold */ + for(compno = 0; compno < maxcomp; compno++ ){ + for(poc = 0; poc < pocno ; poc++){ + int comp_len = 0; + int tpnum = compno; + if (pi_create_encode(pi, cp,tileno,poc,tpnum,tppos,t2_mode,cur_totnum_tp)) { + opj_event_msg(t2->cinfo, EVT_ERROR, "Error initializing Packet Iterator\n"); + pi_destroy(pi, cp, tileno); + return -999; + } + while (pi_next(&pi[poc])) { + if (pi[poc].layno < maxlayers) { + e = t2_encode_packet(tile, &cp->tcps[tileno], &pi[poc], c, dest + len - c, cstr_info, tileno); + comp_len = comp_len + e; + if (e == -999) { + break; + } else { + c += e; + } + } + } + if (e == -999) break; + if (cp->max_comp_size){ + if (comp_len > cp->max_comp_size){ + e = -999; + break; + } + } + } + if (e == -999) break; + } + }else{ /* t2_mode == FINAL_PASS */ + pi_create_encode(pi, cp,tileno,pino,tpnum,tppos,t2_mode,cur_totnum_tp); + while (pi_next(&pi[pino])) { + if (pi[pino].layno < maxlayers) { + e = t2_encode_packet(tile, &cp->tcps[tileno], &pi[pino], c, dest + len - c, cstr_info, tileno); + if (e == -999) { + break; + } else { + c += e; + } + /* INDEX >> */ + if(cstr_info) { + if(cstr_info->index_write) { + opj_tile_info_t *info_TL = &cstr_info->tile[tileno]; + opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; + if (!cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else { + info_PK->start_pos = ((cp->tp_on | tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + e - 1; + info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance + // to start of packet is incremented by value of start of packet*/ + } + + cstr_info->packno++; + } + /* << INDEX */ + tile->packno++; + } + } + } + + pi_destroy(pi, cp, tileno); + + if (e == -999) { + return e; + } + + return (c - dest); +} + +int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info) { + unsigned char *c = src; + opj_pi_iterator_t *pi; + int pino, e = 0; + int n = 0, curtp = 0; + int tp_start_packno; + + opj_image_t *image = t2->image; + opj_cp_t *cp = t2->cp; + + /* create a packet iterator */ + pi = pi_create_decode(image, cp, tileno); + if(!pi) { + /* TODO: throw an error */ + return -999; + } + + tp_start_packno = 0; + + for (pino = 0; pino <= cp->tcps[tileno].numpocs; pino++) { + while (pi_next(&pi[pino])) { + if ((cp->layer==0) || (cp->layer>=((pi[pino].layno)+1))) { + opj_packet_info_t *pack_info; + if (cstr_info) + pack_info = &cstr_info->tile[tileno].packet[cstr_info->packno]; + else + pack_info = NULL; + e = t2_decode_packet(t2, c, src + len - c, tile, &cp->tcps[tileno], &pi[pino], pack_info); + } else { + e = 0; + } + if(e == -999) + { + pi_destroy(pi, cp, tileno); + return -999; + } + /* progression in resolution */ + image->comps[pi[pino].compno].resno_decoded = + (e > 0) ? + int_max(pi[pino].resno, image->comps[pi[pino].compno].resno_decoded) + : image->comps[pi[pino].compno].resno_decoded; + n++; + + /* INDEX >> */ + if(cstr_info) { + opj_tile_info_t *info_TL = &cstr_info->tile[tileno]; + opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; + if (!cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else if (info_TL->packet[cstr_info->packno-1].end_pos >= (int)cstr_info->tile[tileno].tp[curtp].tp_end_pos){ /* New tile part*/ + info_TL->tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; /* Number of packets in previous tile-part*/ + info_TL->tp[curtp].tp_start_pack = tp_start_packno; + tp_start_packno = cstr_info->packno; + curtp++; + info_PK->start_pos = cstr_info->tile[tileno].tp[curtp].tp_end_header+1; + } else { + info_PK->start_pos = (cp->tp_on && info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + e - 1; + info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance + // to start of packet is incremented by value of start of packet*/ + cstr_info->packno++; + } + /* << INDEX */ + + if (e == -999) { /* ADD */ + break; + } else { + c += e; + } + } + } + /* INDEX >> */ + if(cstr_info) { + cstr_info->tile[tileno].tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; /* Number of packets in last tile-part*/ + cstr_info->tile[tileno].tp[curtp].tp_start_pack = tp_start_packno; + } + /* << INDEX */ + + /* don't forget to release pi */ + pi_destroy(pi, cp, tileno); + + if (e == -999) { + return e; + } + + return (c - src); +} + +/* ----------------------------------------------------------------------- */ + +opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp) { + /* create the tcd structure */ + opj_t2_t *t2 = (opj_t2_t*)opj_malloc(sizeof(opj_t2_t)); + if(!t2) return NULL; + t2->cinfo = cinfo; + t2->image = image; + t2->cp = cp; + + return t2; +} + +void t2_destroy(opj_t2_t *t2) { + if(t2) { + opj_free(t2); + } +} + + + + + diff --git a/src/add-ons/translators/icns/openjpeg/t2.h b/src/add-ons/translators/icns/openjpeg/t2.h new file mode 100644 index 0000000000..2151ba67f4 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/t2.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __T2_H +#define __T2_H +/** +@file t2.h +@brief Implementation of a tier-2 coding (packetization of code-block data) (T2) + +*/ + +/** @defgroup T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** +Tier-2 coding +*/ +typedef struct opj_t2 { + /** codec context */ + opj_common_ptr cinfo; + + /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */ + opj_image_t *image; + /** pointer to the image coding parameters */ + opj_cp_t *cp; +} opj_t2_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Encode the packets of a tile to a destination buffer +@param t2 T2 handle +@param tileno number of the tile encoded +@param tile the tile for which to write the packets +@param maxlayers maximum number of layers +@param dest the destination buffer +@param len the length of the destination buffer +@param cstr_info Codestream information structure +@param tpnum Tile part number of the current tile +@param tppos The position of the tile part flag in the progression order +@param pino +@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass +@param cur_totnum_tp The total number of tile parts in the current tile +*/ +int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_codestream_info_t *cstr_info,int tpnum, int tppos,int pino,J2K_T2_MODE t2_mode,int cur_totnum_tp); +/** +Decode the packets of a tile from a source buffer +@param t2 T2 handle +@param src the source buffer +@param len length of the source buffer +@param tileno number that identifies the tile for which to decode the packets +@param tile tile for which to decode the packets +@param cstr_info Codestream information structure + */ +int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info); + +/** +Create a T2 handle +@param cinfo Codec context info +@param image Source or destination image +@param cp Image coding parameters +@return Returns a new T2 handle if successful, returns NULL otherwise +*/ +opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp); +/** +Destroy a T2 handle +@param t2 T2 handle to destroy +*/ +void t2_destroy(opj_t2_t *t2); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __T2_H */ diff --git a/src/add-ons/translators/icns/openjpeg/tcd.c b/src/add-ons/translators/icns/openjpeg/tcd.c new file mode 100644 index 0000000000..ee05205566 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/tcd.c @@ -0,0 +1,1574 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#define _ISOC99_SOURCE /* lrintf is C99 */ +#include "opj_includes.h" + +void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) { + int tileno, compno, resno, bandno, precno;/*, cblkno;*/ + + fprintf(fd, "image {\n"); + fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n", + img->tw, img->th, tcd->image->x0, tcd->image->x1, tcd->image->y0, tcd->image->y1); + + for (tileno = 0; tileno < img->th * img->tw; tileno++) { + opj_tcd_tile_t *tile = &tcd->tcd_image->tiles[tileno]; + fprintf(fd, " tile {\n"); + fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n", + tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + fprintf(fd, " tilec {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n", + tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions); + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + fprintf(fd, "\n res {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n", + res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands); + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + fprintf(fd, " band {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%f, numbps=%d\n", + band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps); + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + fprintf(fd, " prec {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n", + prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch); + /* + for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) { + opj_tcd_cblk_t *cblk = &prec->cblks[cblkno]; + fprintf(fd, " cblk {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d\n", + cblk->x0, cblk->y0, cblk->x1, cblk->y1); + fprintf(fd, " }\n"); + } + */ + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, "}\n"); +} + +/* ----------------------------------------------------------------------- */ + +/** +Create a new TCD handle +*/ +opj_tcd_t* tcd_create(opj_common_ptr cinfo) { + /* create the tcd structure */ + opj_tcd_t *tcd = (opj_tcd_t*)opj_malloc(sizeof(opj_tcd_t)); + if(!tcd) return NULL; + tcd->cinfo = cinfo; + tcd->tcd_image = (opj_tcd_image_t*)opj_malloc(sizeof(opj_tcd_image_t)); + if(!tcd->tcd_image) { + opj_free(tcd); + return NULL; + } + + return tcd; +} + +/** +Destroy a previously created TCD handle +*/ +void tcd_destroy(opj_tcd_t *tcd) { + if(tcd) { + opj_free(tcd->tcd_image); + opj_free(tcd); + } +} + +/* ----------------------------------------------------------------------- */ + +void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno) { + int tileno, compno, resno, bandno, precno, cblkno; + + tcd->image = image; + tcd->cp = cp; + tcd->tcd_image->tw = cp->tw; + tcd->tcd_image->th = cp->th; + tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(sizeof(opj_tcd_tile_t)); + + for (tileno = 0; tileno < 1; tileno++) { + opj_tcp_t *tcp = &cp->tcps[curtileno]; + int j; + + /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + int p = curtileno % cp->tw; /* si numerotation matricielle .. */ + int q = curtileno / cp->tw; /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */ + + /* opj_tcd_tile_t *tile=&tcd->tcd_image->tiles[tileno]; */ + opj_tcd_tile_t *tile = tcd->tcd_image->tiles; + + /* 4 borders of the tile rescale on the image if necessary */ + tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0); + tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0); + tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1); + tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1); + tile->numcomps = image->numcomps; + /* tile->PPT=image->PPT; */ + + /* Modification of the RATE >> */ + for (j = 0; j < tcp->numlayers; j++) { + tcp->rates[j] = tcp->rates[j] ? + cp->tp_on ? + (((float) (tile->numcomps + * (tile->x1 - tile->x0) + * (tile->y1 - tile->y0) + * image->comps[0].prec)) + /(tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)) - (((tcd->cur_totnum_tp - 1) * 14 )/ tcp->numlayers) + : + ((float) (tile->numcomps + * (tile->x1 - tile->x0) + * (tile->y1 - tile->y0) + * image->comps[0].prec))/ + (tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy) + : 0; + + if (tcp->rates[j]) { + if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) { + tcp->rates[j] = tcp->rates[j - 1] + 20; + } else { + if (!j && tcp->rates[j] < 30) + tcp->rates[j] = 30; + } + + if(j == (tcp->numlayers-1)){ + tcp->rates[j] = tcp->rates[j]- 2; + } + } + } + /* << Modification of the RATE */ + + tile->comps = (opj_tcd_tilecomp_t *) opj_malloc(image->numcomps * sizeof(opj_tcd_tilecomp_t)); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tccp_t *tccp = &tcp->tccps[compno]; + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + /* border of each tile component (global) */ + tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx); + tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy); + tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx); + tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy); + + tilec->data = (int *) opj_aligned_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int)); + tilec->numresolutions = tccp->numresolutions; + + tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(tilec->numresolutions * sizeof(opj_tcd_resolution_t)); + + for (resno = 0; resno < tilec->numresolutions; resno++) { + int pdx, pdy; + int levelno = tilec->numresolutions - 1 - resno; + int tlprcxstart, tlprcystart, brprcxend, brprcyend; + int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; + int cbgwidthexpn, cbgheightexpn; + int cblkwidthexpn, cblkheightexpn; + + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + /* border for each resolution level (global) */ + res->x0 = int_ceildivpow2(tilec->x0, levelno); + res->y0 = int_ceildivpow2(tilec->y0, levelno); + res->x1 = int_ceildivpow2(tilec->x1, levelno); + res->y1 = int_ceildivpow2(tilec->y1, levelno); + + res->numbands = resno == 0 ? 1 : 3; + /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ + if (tccp->csty & J2K_CCP_CSTY_PRT) { + pdx = tccp->prcw[resno]; + pdy = tccp->prch[resno]; + } else { + pdx = 15; + pdy = 15; + } + /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; + tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; + + brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; + brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; + + res->pw = (brprcxend - tlprcxstart) >> pdx; + res->ph = (brprcyend - tlprcystart) >> pdy; + + if (resno == 0) { + tlcbgxstart = tlprcxstart; + tlcbgystart = tlprcystart; + brcbgxend = brprcxend; + brcbgyend = brprcyend; + cbgwidthexpn = pdx; + cbgheightexpn = pdy; + } else { + tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); + tlcbgystart = int_ceildivpow2(tlprcystart, 1); + brcbgxend = int_ceildivpow2(brprcxend, 1); + brcbgyend = int_ceildivpow2(brprcyend, 1); + cbgwidthexpn = pdx - 1; + cbgheightexpn = pdy - 1; + } + + cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn); + cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn); + + for (bandno = 0; bandno < res->numbands; bandno++) { + int x0b, y0b, i; + int gain, numbps; + opj_stepsize_t *ss = NULL; + + opj_tcd_band_t *band = &res->bands[bandno]; + + band->bandno = resno == 0 ? 0 : bandno + 1; + x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0; + y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0; + + if (band->bandno == 0) { + /* band border (global) */ + band->x0 = int_ceildivpow2(tilec->x0, levelno); + band->y0 = int_ceildivpow2(tilec->y0, levelno); + band->x1 = int_ceildivpow2(tilec->x1, levelno); + band->y1 = int_ceildivpow2(tilec->y1, levelno); + } else { + /* band border (global) */ + band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1); + band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1); + band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1); + band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1); + } + + ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1]; + gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno); + numbps = image->comps[compno].prec + gain; + + band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn)); + band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ + + band->precincts = (opj_tcd_precinct_t *) opj_malloc(3 * res->pw * res->ph * sizeof(opj_tcd_precinct_t)); + + for (i = 0; i < res->pw * res->ph * 3; i++) { + band->precincts[i].imsbtree = NULL; + band->precincts[i].incltree = NULL; + band->precincts[i].cblks.enc = NULL; + } + + for (precno = 0; precno < res->pw * res->ph; precno++) { + int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; + + int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn); + int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn); + int cbgxend = cbgxstart + (1 << cbgwidthexpn); + int cbgyend = cbgystart + (1 << cbgheightexpn); + + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + /* precinct size (global) */ + prc->x0 = int_max(cbgxstart, band->x0); + prc->y0 = int_max(cbgystart, band->y0); + prc->x1 = int_min(cbgxend, band->x1); + prc->y1 = int_min(cbgyend, band->y1); + + tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; + tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; + brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; + brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; + prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; + prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn; + + prc->cblks.enc = (opj_tcd_cblk_enc_t*) opj_calloc((prc->cw * prc->ch), sizeof(opj_tcd_cblk_enc_t)); + prc->incltree = tgt_create(prc->cw, prc->ch); + prc->imsbtree = tgt_create(prc->cw, prc->ch); + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn); + int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn); + int cblkxend = cblkxstart + (1 << cblkwidthexpn); + int cblkyend = cblkystart + (1 << cblkheightexpn); + + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + + /* code-block size (global) */ + cblk->x0 = int_max(cblkxstart, prc->x0); + cblk->y0 = int_max(cblkystart, prc->y0); + cblk->x1 = int_min(cblkxend, prc->x1); + cblk->y1 = int_min(cblkyend, prc->y1); + cblk->data = (unsigned char*) opj_calloc(9728+2, sizeof(unsigned char)); + /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */ + cblk->data[0] = 0; + cblk->data[1] = 0; + cblk->data += 2; + cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t)); + cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t)); + } + } + } + } + } + } + + /* tcd_dump(stdout, tcd, &tcd->tcd_image); */ +} + +void tcd_free_encode(opj_tcd_t *tcd) { + int tileno, compno, resno, bandno, precno, cblkno; + + for (tileno = 0; tileno < 1; tileno++) { + opj_tcd_tile_t *tile = tcd->tcd_image->tiles; + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + if (prc->incltree != NULL) { + tgt_destroy(prc->incltree); + prc->incltree = NULL; + } + if (prc->imsbtree != NULL) { + tgt_destroy(prc->imsbtree); + prc->imsbtree = NULL; + } + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_free(prc->cblks.enc[cblkno].data - 2); + opj_free(prc->cblks.enc[cblkno].layers); + opj_free(prc->cblks.enc[cblkno].passes); + } + opj_free(prc->cblks.enc); + } /* for (precno */ + opj_free(band->precincts); + band->precincts = NULL; + } /* for (bandno */ + } /* for (resno */ + opj_free(tilec->resolutions); + tilec->resolutions = NULL; + } /* for (compno */ + opj_free(tile->comps); + tile->comps = NULL; + } /* for (tileno */ + opj_free(tcd->tcd_image->tiles); + tcd->tcd_image->tiles = NULL; +} + +void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno) { + int tileno, compno, resno, bandno, precno, cblkno; + + for (tileno = 0; tileno < 1; tileno++) { + opj_tcp_t *tcp = &cp->tcps[curtileno]; + int j; + /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + int p = curtileno % cp->tw; + int q = curtileno / cp->tw; + + opj_tcd_tile_t *tile = tcd->tcd_image->tiles; + + /* 4 borders of the tile rescale on the image if necessary */ + tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0); + tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0); + tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1); + tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1); + + tile->numcomps = image->numcomps; + /* tile->PPT=image->PPT; */ + + /* Modification of the RATE >> */ + for (j = 0; j < tcp->numlayers; j++) { + tcp->rates[j] = tcp->rates[j] ? + cp->tp_on ? + (((float) (tile->numcomps + * (tile->x1 - tile->x0) + * (tile->y1 - tile->y0) + * image->comps[0].prec)) + /(tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)) - (((tcd->cur_totnum_tp - 1) * 14 )/ tcp->numlayers) + : + ((float) (tile->numcomps + * (tile->x1 - tile->x0) + * (tile->y1 - tile->y0) + * image->comps[0].prec))/ + (tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy) + : 0; + + if (tcp->rates[j]) { + if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) { + tcp->rates[j] = tcp->rates[j - 1] + 20; + } else { + if (!j && tcp->rates[j] < 30) + tcp->rates[j] = 30; + } + } + } + /* << Modification of the RATE */ + + /* tile->comps=(opj_tcd_tilecomp_t*)opj_realloc(tile->comps,image->numcomps*sizeof(opj_tcd_tilecomp_t)); */ + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tccp_t *tccp = &tcp->tccps[compno]; + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + /* border of each tile component (global) */ + tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx); + tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy); + tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx); + tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy); + + tilec->data = (int *) opj_aligned_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int)); + tilec->numresolutions = tccp->numresolutions; + /* tilec->resolutions=(opj_tcd_resolution_t*)opj_realloc(tilec->resolutions,tilec->numresolutions*sizeof(opj_tcd_resolution_t)); */ + for (resno = 0; resno < tilec->numresolutions; resno++) { + int pdx, pdy; + + int levelno = tilec->numresolutions - 1 - resno; + int tlprcxstart, tlprcystart, brprcxend, brprcyend; + int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; + int cbgwidthexpn, cbgheightexpn; + int cblkwidthexpn, cblkheightexpn; + + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + /* border for each resolution level (global) */ + res->x0 = int_ceildivpow2(tilec->x0, levelno); + res->y0 = int_ceildivpow2(tilec->y0, levelno); + res->x1 = int_ceildivpow2(tilec->x1, levelno); + res->y1 = int_ceildivpow2(tilec->y1, levelno); + res->numbands = resno == 0 ? 1 : 3; + + /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ + if (tccp->csty & J2K_CCP_CSTY_PRT) { + pdx = tccp->prcw[resno]; + pdy = tccp->prch[resno]; + } else { + pdx = 15; + pdy = 15; + } + /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; + tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; + brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; + brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; + + res->pw = (brprcxend - tlprcxstart) >> pdx; + res->ph = (brprcyend - tlprcystart) >> pdy; + + if (resno == 0) { + tlcbgxstart = tlprcxstart; + tlcbgystart = tlprcystart; + brcbgxend = brprcxend; + brcbgyend = brprcyend; + cbgwidthexpn = pdx; + cbgheightexpn = pdy; + } else { + tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); + tlcbgystart = int_ceildivpow2(tlprcystart, 1); + brcbgxend = int_ceildivpow2(brprcxend, 1); + brcbgyend = int_ceildivpow2(brprcyend, 1); + cbgwidthexpn = pdx - 1; + cbgheightexpn = pdy - 1; + } + + cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn); + cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn); + + for (bandno = 0; bandno < res->numbands; bandno++) { + int x0b, y0b; + int gain, numbps; + opj_stepsize_t *ss = NULL; + + opj_tcd_band_t *band = &res->bands[bandno]; + + band->bandno = resno == 0 ? 0 : bandno + 1; + x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0; + y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0; + + if (band->bandno == 0) { + /* band border */ + band->x0 = int_ceildivpow2(tilec->x0, levelno); + band->y0 = int_ceildivpow2(tilec->y0, levelno); + band->x1 = int_ceildivpow2(tilec->x1, levelno); + band->y1 = int_ceildivpow2(tilec->y1, levelno); + } else { + band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1); + band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1); + band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1); + band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1); + } + + ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1]; + gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno); + numbps = image->comps[compno].prec + gain; + band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn)); + band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ + + for (precno = 0; precno < res->pw * res->ph; precno++) { + int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; + + int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn); + int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn); + int cbgxend = cbgxstart + (1 << cbgwidthexpn); + int cbgyend = cbgystart + (1 << cbgheightexpn); + + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + /* precinct size (global) */ + prc->x0 = int_max(cbgxstart, band->x0); + prc->y0 = int_max(cbgystart, band->y0); + prc->x1 = int_min(cbgxend, band->x1); + prc->y1 = int_min(cbgyend, band->y1); + + tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; + tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; + brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; + brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; + prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; + prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn; + + opj_free(prc->cblks.enc); + prc->cblks.enc = (opj_tcd_cblk_enc_t*) opj_calloc(prc->cw * prc->ch, sizeof(opj_tcd_cblk_enc_t)); + + if (prc->incltree != NULL) { + tgt_destroy(prc->incltree); + } + if (prc->imsbtree != NULL) { + tgt_destroy(prc->imsbtree); + } + + prc->incltree = tgt_create(prc->cw, prc->ch); + prc->imsbtree = tgt_create(prc->cw, prc->ch); + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn); + int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn); + int cblkxend = cblkxstart + (1 << cblkwidthexpn); + int cblkyend = cblkystart + (1 << cblkheightexpn); + + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + + /* code-block size (global) */ + cblk->x0 = int_max(cblkxstart, prc->x0); + cblk->y0 = int_max(cblkystart, prc->y0); + cblk->x1 = int_min(cblkxend, prc->x1); + cblk->y1 = int_min(cblkyend, prc->y1); + cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char)); + /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */ + cblk->data[0] = 0; + cblk->data[1] = 0; + cblk->data += 2; + cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t)); + cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t)); + } + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ + } /* tileno */ + + /* tcd_dump(stdout, tcd, &tcd->tcd_image); */ +} + +void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) { + int i, j, tileno, p, q; + unsigned int x0 = 0, y0 = 0, x1 = 0, y1 = 0, w, h; + + tcd->image = image; + tcd->tcd_image->tw = cp->tw; + tcd->tcd_image->th = cp->th; + tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(cp->tw * cp->th, sizeof(opj_tcd_tile_t)); + + /* + Allocate place to store the decoded data = final image + Place limited by the tile really present in the codestream + */ + + for (j = 0; j < cp->tileno_size; j++) { + opj_tcd_tile_t *tile; + + tileno = cp->tileno[j]; + tile = &(tcd->tcd_image->tiles[cp->tileno[tileno]]); + tile->numcomps = image->numcomps; + tile->comps = (opj_tcd_tilecomp_t*) opj_calloc(image->numcomps, sizeof(opj_tcd_tilecomp_t)); + } + + for (i = 0; i < image->numcomps; i++) { + for (j = 0; j < cp->tileno_size; j++) { + opj_tcd_tile_t *tile; + opj_tcd_tilecomp_t *tilec; + + /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + + tileno = cp->tileno[j]; + + tile = &(tcd->tcd_image->tiles[cp->tileno[tileno]]); + tilec = &tile->comps[i]; + + p = tileno % cp->tw; /* si numerotation matricielle .. */ + q = tileno / cp->tw; /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */ + + /* 4 borders of the tile rescale on the image if necessary */ + tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0); + tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0); + tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1); + tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1); + + tilec->x0 = int_ceildiv(tile->x0, image->comps[i].dx); + tilec->y0 = int_ceildiv(tile->y0, image->comps[i].dy); + tilec->x1 = int_ceildiv(tile->x1, image->comps[i].dx); + tilec->y1 = int_ceildiv(tile->y1, image->comps[i].dy); + + x0 = j == 0 ? tilec->x0 : int_min(x0, (unsigned int) tilec->x0); + y0 = j == 0 ? tilec->y0 : int_min(y0, (unsigned int) tilec->y0); + x1 = j == 0 ? tilec->x1 : int_max(x1, (unsigned int) tilec->x1); + y1 = j == 0 ? tilec->y1 : int_max(y1, (unsigned int) tilec->y1); + } + + w = int_ceildivpow2(x1 - x0, image->comps[i].factor); + h = int_ceildivpow2(y1 - y0, image->comps[i].factor); + + image->comps[i].w = w; + image->comps[i].h = h; + image->comps[i].x0 = x0; + image->comps[i].y0 = y0; + } +} + +void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int tileno, opj_codestream_info_t *cstr_info) { + int compno, resno, bandno, precno, cblkno; + opj_tcp_t *tcp; + opj_tcd_tile_t *tile; + + OPJ_ARG_NOT_USED(cstr_info); + + tcd->cp = cp; + + tcp = &(cp->tcps[cp->tileno[tileno]]); + tile = &(tcd->tcd_image->tiles[cp->tileno[tileno]]); + + tileno = cp->tileno[tileno]; + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + if (tccp->numresolutions <= 0) + { + cp->tileno[tileno] = -1; + return; + } + + /* border of each tile component (global) */ + tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx); + tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy); + tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx); + tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy); + + tilec->numresolutions = tccp->numresolutions; + tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(tilec->numresolutions * sizeof(opj_tcd_resolution_t)); + + for (resno = 0; resno < tilec->numresolutions; resno++) { + int pdx, pdy; + int levelno = tilec->numresolutions - 1 - resno; + int tlprcxstart, tlprcystart, brprcxend, brprcyend; + int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; + int cbgwidthexpn, cbgheightexpn; + int cblkwidthexpn, cblkheightexpn; + + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + /* border for each resolution level (global) */ + res->x0 = int_ceildivpow2(tilec->x0, levelno); + res->y0 = int_ceildivpow2(tilec->y0, levelno); + res->x1 = int_ceildivpow2(tilec->x1, levelno); + res->y1 = int_ceildivpow2(tilec->y1, levelno); + res->numbands = resno == 0 ? 1 : 3; + + /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ + if (tccp->csty & J2K_CCP_CSTY_PRT) { + pdx = tccp->prcw[resno]; + pdy = tccp->prch[resno]; + } else { + pdx = 15; + pdy = 15; + } + + /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; + tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; + brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; + brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; + + res->pw = (res->x0 == res->x1) ? 0 : ((brprcxend - tlprcxstart) >> pdx); + res->ph = (res->y0 == res->y1) ? 0 : ((brprcyend - tlprcystart) >> pdy); + + if (resno == 0) { + tlcbgxstart = tlprcxstart; + tlcbgystart = tlprcystart; + brcbgxend = brprcxend; + brcbgyend = brprcyend; + cbgwidthexpn = pdx; + cbgheightexpn = pdy; + } else { + tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); + tlcbgystart = int_ceildivpow2(tlprcystart, 1); + brcbgxend = int_ceildivpow2(brprcxend, 1); + brcbgyend = int_ceildivpow2(brprcyend, 1); + cbgwidthexpn = pdx - 1; + cbgheightexpn = pdy - 1; + } + + cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn); + cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn); + + for (bandno = 0; bandno < res->numbands; bandno++) { + int x0b, y0b; + int gain, numbps; + opj_stepsize_t *ss = NULL; + + opj_tcd_band_t *band = &res->bands[bandno]; + band->bandno = resno == 0 ? 0 : bandno + 1; + x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0; + y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0; + + if (band->bandno == 0) { + /* band border (global) */ + band->x0 = int_ceildivpow2(tilec->x0, levelno); + band->y0 = int_ceildivpow2(tilec->y0, levelno); + band->x1 = int_ceildivpow2(tilec->x1, levelno); + band->y1 = int_ceildivpow2(tilec->y1, levelno); + } else { + /* band border (global) */ + band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1); + band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1); + band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1); + band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1); + } + + ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1]; + gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno); + numbps = image->comps[compno].prec + gain; + band->stepsize = (float)(((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn)) * 0.5); + band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ + + band->precincts = (opj_tcd_precinct_t *) opj_malloc(res->pw * res->ph * sizeof(opj_tcd_precinct_t)); + + for (precno = 0; precno < res->pw * res->ph; precno++) { + int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; + int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn); + int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn); + int cbgxend = cbgxstart + (1 << cbgwidthexpn); + int cbgyend = cbgystart + (1 << cbgheightexpn); + + opj_tcd_precinct_t *prc = &band->precincts[precno]; + /* precinct size (global) */ + prc->x0 = int_max(cbgxstart, band->x0); + prc->y0 = int_max(cbgystart, band->y0); + prc->x1 = int_min(cbgxend, band->x1); + prc->y1 = int_min(cbgyend, band->y1); + + tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; + tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; + brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; + brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; + prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; + prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn; + + prc->cblks.dec = (opj_tcd_cblk_dec_t*) opj_malloc(prc->cw * prc->ch * sizeof(opj_tcd_cblk_dec_t)); + + prc->incltree = tgt_create(prc->cw, prc->ch); + prc->imsbtree = tgt_create(prc->cw, prc->ch); + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn); + int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn); + int cblkxend = cblkxstart + (1 << cblkwidthexpn); + int cblkyend = cblkystart + (1 << cblkheightexpn); + + opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno]; + cblk->data = NULL; + cblk->segs = NULL; + /* code-block size (global) */ + cblk->x0 = int_max(cblkxstart, prc->x0); + cblk->y0 = int_max(cblkystart, prc->y0); + cblk->x1 = int_min(cblkxend, prc->x1); + cblk->y1 = int_min(cblkyend, prc->y1); + cblk->numsegs = 0; + } + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ + /* tcd_dump(stdout, tcd, &tcd->tcd_image); */ +} + +void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final) { + int compno, resno, bandno, precno, cblkno; + int value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */ + int matrice[10][10][3]; + int i, j, k; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_tile; + opj_tcp_t *tcd_tcp = tcd->tcp; + + /*matrice=(int*)opj_malloc(tcd_tcp->numlayers*tcd_tile->comps[0].numresolutions*3*sizeof(int)); */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + for (i = 0; i < tcd_tcp->numlayers; i++) { + for (j = 0; j < tilec->numresolutions; j++) { + for (k = 0; k < 3; k++) { + matrice[i][j][k] = + (int) (cp->matrice[i * tilec->numresolutions * 3 + j * 3 + k] + * (float) (tcd->image->comps[compno].prec / 16.0)); + } + } + } + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + int n; + int imsb = tcd->image->comps[compno].prec - cblk->numbps; /* number of bit-plan equal to zero */ + /* Correction of the matrix of coefficient to include the IMSB information */ + if (layno == 0) { + value = matrice[layno][resno][bandno]; + if (imsb >= value) { + value = 0; + } else { + value -= imsb; + } + } else { + value = matrice[layno][resno][bandno] - matrice[layno - 1][resno][bandno]; + if (imsb >= matrice[layno - 1][resno][bandno]) { + value -= (imsb - matrice[layno - 1][resno][bandno]); + if (value < 0) { + value = 0; + } + } + } + + if (layno == 0) { + cblk->numpassesinlayers = 0; + } + + n = cblk->numpassesinlayers; + if (cblk->numpassesinlayers == 0) { + if (value != 0) { + n = 3 * value - 2 + cblk->numpassesinlayers; + } else { + n = cblk->numpassesinlayers; + } + } else { + n = 3 * value + cblk->numpassesinlayers; + } + + layer->numpasses = n - cblk->numpassesinlayers; + + if (!layer->numpasses) + continue; + + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + } + if (final) + cblk->numpassesinlayers = n; + } + } + } + } + } +} + +void tcd_rateallocate_fixed(opj_tcd_t *tcd) { + int layno; + for (layno = 0; layno < tcd->tcp->numlayers; layno++) { + tcd_makelayer_fixed(tcd, layno, 1); + } +} + +void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) { + int compno, resno, bandno, precno, cblkno, passno; + + opj_tcd_tile_t *tcd_tile = tcd->tcd_tile; + + tcd_tile->distolayer[layno] = 0; /* fixed_quality */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + + int n; + if (layno == 0) { + cblk->numpassesinlayers = 0; + } + n = cblk->numpassesinlayers; + for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { + int dr; + double dd; + opj_tcd_pass_t *pass = &cblk->passes[passno]; + if (n == 0) { + dr = pass->rate; + dd = pass->distortiondec; + } else { + dr = pass->rate - cblk->passes[n - 1].rate; + dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; + } + if (!dr) { + if (dd != 0) + n = passno + 1; + continue; + } + if (dd / dr >= thresh) + n = passno + 1; + } + layer->numpasses = n - cblk->numpassesinlayers; + + if (!layer->numpasses) { + layer->disto = 0; + continue; + } + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + layer->disto = cblk->passes[n - 1].distortiondec; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->disto = cblk->passes[n - 1].distortiondec - cblk->passes[cblk->numpassesinlayers - 1].distortiondec; + } + + tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */ + + if (final) + cblk->numpassesinlayers = n; + } + } + } + } + } +} + +opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) { + int compno, resno, bandno, precno, cblkno, passno, layno; + double min, max; + double cumdisto[100]; /* fixed_quality */ + const double K = 1; /* 1.1; fixed_quality */ + double maxSE = 0; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_tile; + opj_tcp_t *tcd_tcp = tcd->tcp; + + min = DBL_MAX; + max = 0; + + tcd_tile->numpix = 0; /* fixed_quality */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + tilec->numpix = 0; + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + + for (passno = 0; passno < cblk->totalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + int dr; + double dd, rdslope; + if (passno == 0) { + dr = pass->rate; + dd = pass->distortiondec; + } else { + dr = pass->rate - cblk->passes[passno - 1].rate; + dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec; + } + if (dr == 0) { + continue; + } + rdslope = dd / dr; + if (rdslope < min) { + min = rdslope; + } + if (rdslope > max) { + max = rdslope; + } + } /* passno */ + + /* fixed_quality */ + tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); + tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); + } /* cbklno */ + } /* precno */ + } /* bandno */ + } /* resno */ + + maxSE += (((double)(1 << tcd->image->comps[compno].prec) - 1.0) + * ((double)(1 << tcd->image->comps[compno].prec) -1.0)) + * ((double)(tilec->numpix)); + } /* compno */ + + /* index file */ + if(cstr_info) { + opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno]; + tile_info->numpix = tcd_tile->numpix; + tile_info->distotile = tcd_tile->distotile; + tile_info->thresh = (double *) opj_malloc(tcd_tcp->numlayers * sizeof(double)); + } + + for (layno = 0; layno < tcd_tcp->numlayers; layno++) { + double lo = min; + double hi = max; + int success = 0; + int maxlen = tcd_tcp->rates[layno] ? int_min(((int) ceil(tcd_tcp->rates[layno])), len) : len; + double goodthresh = 0; + double stable_thresh = 0; + int i; + double distotarget; /* fixed_quality */ + + /* fixed_quality */ + distotarget = tcd_tile->distotile - ((K * maxSE) / pow((float)10, tcd_tcp->distoratio[layno] / 10)); + + /* Don't try to find an optimal threshold but rather take everything not included yet, if + -r xx,yy,zz,0 (disto_alloc == 1 and rates == 0) + -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0) + ==> possible to have some lossy layers and the last layer for sure lossless */ + if ( ((cp->disto_alloc==1) && (tcd_tcp->rates[layno]>0)) || ((cp->fixed_quality==1) && (tcd_tcp->distoratio[layno]>0))) { + opj_t2_t *t2 = t2_create(tcd->cinfo, tcd->image, cp); + double thresh = 0; + + for (i = 0; i < 128; i++) { + int l = 0; + double distoachieved = 0; /* fixed_quality */ + thresh = (lo + hi) / 2; + + tcd_makelayer(tcd, layno, thresh, 0); + + if (cp->fixed_quality) { /* fixed_quality */ + if(cp->cinema){ + l = t2_encode_packets(t2,tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC, tcd->cur_totnum_tp); + if (l == -999) { + lo = thresh; + continue; + }else{ + distoachieved = layno == 0 ? + tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno]; + if (distoachieved < distotarget) { + hi=thresh; + stable_thresh = thresh; + continue; + }else{ + lo=thresh; + } + } + }else{ + distoachieved = (layno == 0) ? + tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + if (distoachieved < distotarget) { + hi = thresh; + stable_thresh = thresh; + continue; + } + lo = thresh; + } + } else { + l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC, tcd->cur_totnum_tp); + /* TODO: what to do with l ??? seek / tell ??? */ + /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ + if (l == -999) { + lo = thresh; + continue; + } + hi = thresh; + stable_thresh = thresh; + } + } + success = 1; + goodthresh = stable_thresh == 0? thresh : stable_thresh; + t2_destroy(t2); + } else { + success = 1; + goodthresh = min; + } + + if (!success) { + return OPJ_FALSE; + } + + if(cstr_info) { /* Threshold for Marcela Index */ + cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh; + } + tcd_makelayer(tcd, layno, goodthresh, 1); + + /* fixed_quality */ + cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + } + + return OPJ_TRUE; +} + +int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) { + int compno; + int l, i, numpacks = 0; + opj_tcd_tile_t *tile = NULL; + opj_tcp_t *tcd_tcp = NULL; + opj_cp_t *cp = NULL; + + opj_tcp_t *tcp = &tcd->cp->tcps[0]; + opj_tccp_t *tccp = &tcp->tccps[0]; + opj_image_t *image = tcd->image; + + opj_t1_t *t1 = NULL; /* T1 component */ + opj_t2_t *t2 = NULL; /* T2 component */ + + tcd->tcd_tileno = tileno; + tcd->tcd_tile = tcd->tcd_image->tiles; + tcd->tcp = &tcd->cp->tcps[tileno]; + + tile = tcd->tcd_tile; + tcd_tcp = tcd->tcp; + cp = tcd->cp; + + if(tcd->cur_tp_num == 0){ + tcd->encoding_time = opj_clock(); /* time needed to encode a tile */ + /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */ + if(cstr_info) { + opj_tcd_tilecomp_t *tilec_idx = &tile->comps[0]; /* based on component 0 */ + for (i = 0; i < tilec_idx->numresolutions; i++) { + opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[i]; + + cstr_info->tile[tileno].pw[i] = res_idx->pw; + cstr_info->tile[tileno].ph[i] = res_idx->ph; + + numpacks += res_idx->pw * res_idx->ph; + + cstr_info->tile[tileno].pdx[i] = tccp->prcw[i]; + cstr_info->tile[tileno].pdy[i] = tccp->prch[i]; + } + cstr_info->tile[tileno].packet = (opj_packet_info_t*) opj_calloc(cstr_info->numcomps * cstr_info->numlayers * numpacks, sizeof(opj_packet_info_t)); + } + /* << INDEX */ + + /*---------------TILE-------------------*/ + + for (compno = 0; compno < tile->numcomps; compno++) { + int x, y; + + int adjust = image->comps[compno].sgnd ? 0 : 1 << (image->comps[compno].prec - 1); + int offset_x = int_ceildiv(image->x0, image->comps[compno].dx); + int offset_y = int_ceildiv(image->y0, image->comps[compno].dy); + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + int tw = tilec->x1 - tilec->x0; + int w = int_ceildiv(image->x1 - image->x0, image->comps[compno].dx); + + /* extract tile data */ + + if (tcd_tcp->tccps[compno].qmfbid == 1) { + for (y = tilec->y0; y < tilec->y1; y++) { + /* start of the src tile scanline */ + int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w]; + /* start of the dst tile scanline */ + int *tile_data = &tilec->data[(y - tilec->y0) * tw]; + for (x = tilec->x0; x < tilec->x1; x++) { + *tile_data++ = *data++ - adjust; + } + } + } else if (tcd_tcp->tccps[compno].qmfbid == 0) { + for (y = tilec->y0; y < tilec->y1; y++) { + /* start of the src tile scanline */ + int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w]; + /* start of the dst tile scanline */ + int *tile_data = &tilec->data[(y - tilec->y0) * tw]; + for (x = tilec->x0; x < tilec->x1; x++) { + *tile_data++ = (*data++ - adjust) << 11; + } + + } + } + } + + /*----------------MCT-------------------*/ + if (tcd_tcp->mct) { + int samples = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0); + if (tcd_tcp->tccps[0].qmfbid == 0) { + mct_encode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples); + } else { + mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples); + } + } + + /*----------------DWT---------------------*/ + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + if (tcd_tcp->tccps[compno].qmfbid == 1) { + dwt_encode(tilec); + } else if (tcd_tcp->tccps[compno].qmfbid == 0) { + dwt_encode_real(tilec); + } + } + + /*------------------TIER1-----------------*/ + t1 = t1_create(tcd->cinfo); + t1_encode_cblks(t1, tile, tcd_tcp); + t1_destroy(t1); + + /*-----------RATE-ALLOCATE------------------*/ + + /* INDEX */ + if(cstr_info) { + cstr_info->index_write = 0; + } + if (cp->disto_alloc || cp->fixed_quality) { /* fixed_quality */ + /* Normal Rate/distortion allocation */ + tcd_rateallocate(tcd, dest, len, cstr_info); + } else { + /* Fixed layer allocation */ + tcd_rateallocate_fixed(tcd); + } + } + /*--------------TIER2------------------*/ + + /* INDEX */ + if(cstr_info) { + cstr_info->index_write = 1; + } + + t2 = t2_create(tcd->cinfo, image, cp); + l = t2_encode_packets(t2,tileno, tile, tcd_tcp->numlayers, dest, len, cstr_info,tcd->tp_num,tcd->tp_pos,tcd->cur_pino,FINAL_PASS,tcd->cur_totnum_tp); + t2_destroy(t2); + + /*---------------CLEAN-------------------*/ + + + if(tcd->cur_tp_num == tcd->cur_totnum_tp - 1){ + tcd->encoding_time = opj_clock() - tcd->encoding_time; + opj_event_msg(tcd->cinfo, EVT_INFO, "- tile encoded in %f s\n", tcd->encoding_time); + + /* cleaning memory */ + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_aligned_free(tilec->data); + } + } + + return l; +} + +opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info) { + int l; + int compno; + int eof = 0; + double tile_time, t1_time, dwt_time; + opj_tcd_tile_t *tile = NULL; + + opj_t1_t *t1 = NULL; /* T1 component */ + opj_t2_t *t2 = NULL; /* T2 component */ + + tcd->tcd_tileno = tileno; + tcd->tcd_tile = &(tcd->tcd_image->tiles[tileno]); + tcd->tcp = &(tcd->cp->tcps[tileno]); + tile = tcd->tcd_tile; + + tile_time = opj_clock(); /* time needed to decode a tile */ + opj_event_msg(tcd->cinfo, EVT_INFO, "tile %d of %d\n", tileno + 1, tcd->cp->tw * tcd->cp->th); + + /* INDEX >> */ + if(cstr_info) { + int resno, compno, numprec = 0; + for (compno = 0; compno < cstr_info->numcomps; compno++) { + opj_tcp_t *tcp = &tcd->cp->tcps[0]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_tcd_tilecomp_t *tilec_idx = &tile->comps[compno]; + for (resno = 0; resno < tilec_idx->numresolutions; resno++) { + opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[resno]; + cstr_info->tile[tileno].pw[resno] = res_idx->pw; + cstr_info->tile[tileno].ph[resno] = res_idx->ph; + numprec += res_idx->pw * res_idx->ph; + if (tccp->csty & J2K_CP_CSTY_PRT) { + cstr_info->tile[tileno].pdx[resno] = tccp->prcw[resno]; + cstr_info->tile[tileno].pdy[resno] = tccp->prch[resno]; + } + else { + cstr_info->tile[tileno].pdx[resno] = 15; + cstr_info->tile[tileno].pdy[resno] = 15; + } + } + } + cstr_info->tile[tileno].packet = (opj_packet_info_t *) opj_malloc(cstr_info->numlayers * numprec * sizeof(opj_packet_info_t)); + cstr_info->packno = 0; + } + /* << INDEX */ + + /*--------------TIER2------------------*/ + + t2 = t2_create(tcd->cinfo, tcd->image, tcd->cp); + l = t2_decode_packets(t2, src, len, tileno, tile, cstr_info); + t2_destroy(t2); + + if (l == -999) { + eof = 1; + opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: incomplete bistream\n"); + } + + /*------------------TIER1-----------------*/ + + t1_time = opj_clock(); /* time needed to decode a tile */ + t1 = t1_create(tcd->cinfo); + if (t1 == NULL) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + t1_destroy(t1); + return OPJ_FALSE; + } + + for (compno = 0; compno < tile->numcomps; ++compno) { + opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; + /* The +3 is headroom required by the vectorized DWT */ + tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int)); + if (tilec->data == NULL) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + return OPJ_FALSE; + } + + t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]); + } + t1_destroy(t1); + t1_time = opj_clock() - t1_time; + opj_event_msg(tcd->cinfo, EVT_INFO, "- tiers-1 took %f s\n", t1_time); + + /*----------------DWT---------------------*/ + + dwt_time = opj_clock(); /* time needed to decode a tile */ + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + int numres2decode; + + if (tcd->cp->reduce != 0) { + if ( tile->comps[compno].numresolutions < ( tcd->cp->reduce - 1 ) ) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Error decoding tile. The number of resolutions to remove [%d+1] is higher than the number " + " of resolutions in the original codestream [%d]\nModify the cp_reduce parameter.\n", tcd->cp->reduce, tile->comps[compno].numresolutions); + return OPJ_FALSE; + } + else { + tcd->image->comps[compno].resno_decoded = + tile->comps[compno].numresolutions - tcd->cp->reduce - 1; + } + } + + numres2decode = tcd->image->comps[compno].resno_decoded + 1; + if(numres2decode > 0){ + if (tcd->tcp->tccps[compno].qmfbid == 1) { + dwt_decode(tilec, numres2decode); + } else { + dwt_decode_real(tilec, numres2decode); + } + } + } + dwt_time = opj_clock() - dwt_time; + opj_event_msg(tcd->cinfo, EVT_INFO, "- dwt took %f s\n", dwt_time); + + /*----------------MCT-------------------*/ + + if (tcd->tcp->mct) { + int n = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0); + + if (tile->numcomps >= 3 ){ + if (tcd->tcp->tccps[0].qmfbid == 1) { + mct_decode( + tile->comps[0].data, + tile->comps[1].data, + tile->comps[2].data, + n); + } else { + mct_decode_real( + (float*)tile->comps[0].data, + (float*)tile->comps[1].data, + (float*)tile->comps[2].data, + n); + } + } else{ + opj_event_msg(tcd->cinfo, EVT_WARNING,"Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",tile->numcomps); + } + } + + /*---------------TILE-------------------*/ + + for (compno = 0; compno < tile->numcomps; ++compno) { + opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; + opj_image_comp_t* imagec = &tcd->image->comps[compno]; + opj_tcd_resolution_t* res = &tilec->resolutions[imagec->resno_decoded]; + int adjust = imagec->sgnd ? 0 : 1 << (imagec->prec - 1); + int min = imagec->sgnd ? -(1 << (imagec->prec - 1)) : 0; + int max = imagec->sgnd ? (1 << (imagec->prec - 1)) - 1 : (1 << imagec->prec) - 1; + + int tw = tilec->x1 - tilec->x0; + int w = imagec->w; + + int offset_x = int_ceildivpow2(imagec->x0, imagec->factor); + int offset_y = int_ceildivpow2(imagec->y0, imagec->factor); + + int i, j; + if(!imagec->data){ + imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int)); + } + if (!imagec->data) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + return OPJ_FALSE; + } + if(tcd->tcp->tccps[compno].qmfbid == 1) { + for(j = res->y0; j < res->y1; ++j) { + for(i = res->x0; i < res->x1; ++i) { + int v = tilec->data[i - res->x0 + (j - res->y0) * tw]; + v += adjust; + imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max); + } + } + }else{ + for(j = res->y0; j < res->y1; ++j) { + for(i = res->x0; i < res->x1; ++i) { + float tmp = ((float*)tilec->data)[i - res->x0 + (j - res->y0) * tw]; + int v = lrintf(tmp); + v += adjust; + imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max); + } + } + } + opj_aligned_free(tilec->data); + } + + tile_time = opj_clock() - tile_time; /* time needed to decode a tile */ + opj_event_msg(tcd->cinfo, EVT_INFO, "- tile decoded in %f s\n", tile_time); + + if (eof) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +void tcd_free_decode(opj_tcd_t *tcd) { + opj_tcd_image_t *tcd_image = tcd->tcd_image; + int i = 0; + for (i = 0; i < tcd_image->tw * tcd_image->th; i++) + { + tcd_free_decode_tile(tcd, i); + } + + opj_free(tcd_image->tiles); +} + +void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) { + int compno,resno,bandno,precno,cblkno; + + opj_tcd_image_t *tcd_image = tcd->tcd_image; + + opj_tcd_tile_t *tile = &tcd_image->tiles[tileno]; + if (tile->comps != NULL) { + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + for (precno = 0; precno < res->ph * res->pw; precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + if (prec->cblks.dec != NULL) { + for (cblkno = 0; cblkno < prec->cw * prec->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &prec->cblks.dec[cblkno]; + opj_free(cblk->data); + opj_free(cblk->segs); + } + opj_free(prec->cblks.dec); + } + if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree); + if (prec->incltree != NULL) tgt_destroy(prec->incltree); + + + } + opj_free(band->precincts); + } + } + opj_free(tilec->resolutions); + } + opj_free(tile->comps); + tile->comps = NULL; + } +} + + + diff --git a/src/add-ons/translators/icns/openjpeg/tcd.h b/src/add-ons/translators/icns/openjpeg/tcd.h new file mode 100644 index 0000000000..e3f93adc37 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/tcd.h @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __TCD_H +#define __TCD_H +/** +@file tcd.h +@brief Implementation of a tile coder/decoder (TCD) + +The functions in TCD.C have for goal to encode or decode each tile independently from +each other. The functions in TCD.C are used by some function in J2K.C. +*/ + +/** @defgroup TCD TCD - Implementation of a tile coder/decoder */ +/*@{*/ + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_seg { + unsigned char** data; + int dataindex; + int numpasses; + int len; + int maxpasses; + int numnewpasses; + int newlen; +} opj_tcd_seg_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_pass { + int rate; + double distortiondec; + int term, len; +} opj_tcd_pass_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_layer { + int numpasses; /* Number of passes in the layer */ + int len; /* len of information */ + double disto; /* add for index (Cfr. Marcela) */ + unsigned char *data; /* data */ +} opj_tcd_layer_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_cblk_enc { + unsigned char* data; /* Data */ + opj_tcd_layer_t* layers; /* layer information */ + opj_tcd_pass_t* passes; /* information about the passes */ + int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + int numbps; + int numlenbits; + int numpasses; /* number of pass already done for the code-blocks */ + int numpassesinlayers; /* number of passes in the layer */ + int totalpasses; /* total number of passes */ +} opj_tcd_cblk_enc_t; + +typedef struct opj_tcd_cblk_dec { + unsigned char* data; /* Data */ + opj_tcd_seg_t* segs; /* segments informations */ + int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + int numbps; + int numlenbits; + int len; /* length */ + int numnewpasses; /* number of pass added to the code-blocks */ + int numsegs; /* number of segments */ +} opj_tcd_cblk_dec_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_precinct { + int x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */ + int cw, ch; /* number of precinct in width and heigth */ + union{ /* code-blocks informations */ + opj_tcd_cblk_enc_t* enc; + opj_tcd_cblk_dec_t* dec; + } cblks; + opj_tgt_tree_t *incltree; /* inclusion tree */ + opj_tgt_tree_t *imsbtree; /* IMSB tree */ +} opj_tcd_precinct_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_band { + int x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */ + int bandno; + opj_tcd_precinct_t *precincts; /* precinct information */ + int numbps; + float stepsize; +} opj_tcd_band_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_resolution { + int x0, y0, x1, y1; /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */ + int pw, ph; + int numbands; /* number sub-band for the resolution level */ + opj_tcd_band_t bands[3]; /* subband information */ +} opj_tcd_resolution_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_tilecomp { + int x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ + int numresolutions; /* number of resolutions level */ + opj_tcd_resolution_t *resolutions; /* resolutions information */ + int *data; /* data of the component */ + int numpix; /* add fixed_quality */ +} opj_tcd_tilecomp_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_tile { + int x0, y0, x1, y1; /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */ + int numcomps; /* number of components in tile */ + opj_tcd_tilecomp_t *comps; /* Components information */ + int numpix; /* add fixed_quality */ + double distotile; /* add fixed_quality */ + double distolayer[100]; /* add fixed_quality */ + /** packet number */ + int packno; +} opj_tcd_tile_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_image { + int tw, th; /* number of tiles in width and heigth */ + opj_tcd_tile_t *tiles; /* Tiles information */ +} opj_tcd_image_t; + +/** +Tile coder/decoder +*/ +typedef struct opj_tcd { + /** Position of the tilepart flag in Progression order*/ + int tp_pos; + /** Tile part number*/ + int tp_num; + /** Current tile part number*/ + int cur_tp_num; + /** Total number of tileparts of the current tile*/ + int cur_totnum_tp; + /** Current Packet iterator number */ + int cur_pino; + /** codec context */ + opj_common_ptr cinfo; + + /** info on each image tile */ + opj_tcd_image_t *tcd_image; + /** image */ + opj_image_t *image; + /** coding parameters */ + opj_cp_t *cp; + /** pointer to the current encoded/decoded tile */ + opj_tcd_tile_t *tcd_tile; + /** coding/decoding parameters common to all tiles */ + opj_tcp_t *tcp; + /** current encoded/decoded tile */ + int tcd_tileno; + /** Time taken to encode a tile*/ + double encoding_time; +} opj_tcd_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Dump the content of a tcd structure +*/ +void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img); +/** +Create a new TCD handle +@param cinfo Codec context info +@return Returns a new TCD handle if successful returns NULL otherwise +*/ +opj_tcd_t* tcd_create(opj_common_ptr cinfo); +/** +Destroy a previously created TCD handle +@param tcd TCD handle to destroy +*/ +void tcd_destroy(opj_tcd_t *tcd); +/** +Initialize the tile coder (allocate the memory) +@param tcd TCD handle +@param image Raw image +@param cp Coding parameters +@param curtileno Number that identifies the tile that will be encoded +*/ +void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno); +/** +Free the memory allocated for encoding +@param tcd TCD handle +*/ +void tcd_free_encode(opj_tcd_t *tcd); +/** +Initialize the tile coder (reuses the memory allocated by tcd_malloc_encode) +@param tcd TCD handle +@param image Raw image +@param cp Coding parameters +@param curtileno Number that identifies the tile that will be encoded +*/ +void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno); +/** +Initialize the tile decoder +@param tcd TCD handle +@param image Raw image +@param cp Coding parameters +*/ +void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp); +void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int tileno, opj_codestream_info_t *cstr_info); +void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final); +void tcd_rateallocate_fixed(opj_tcd_t *tcd); +void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final); +opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info); +/** +Encode a tile from the raw image into a buffer +@param tcd TCD handle +@param tileno Number that identifies one of the tiles to be encoded +@param dest Destination buffer +@param len Length of destination buffer +@param cstr_info Codestream information structure +@return +*/ +int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info); +/** +Decode a tile from a buffer into a raw image +@param tcd TCD handle +@param src Source buffer +@param len Length of source buffer +@param tileno Number that identifies one of the tiles to be decoded +@param cstr_info Codestream information structure +*/ +opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info); +/** +Free the memory allocated for decoding +@param tcd TCD handle +*/ +void tcd_free_decode(opj_tcd_t *tcd); +void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __TCD_H */ diff --git a/src/add-ons/translators/icns/openjpeg/tgt.c b/src/add-ons/translators/icns/openjpeg/tgt.c new file mode 100644 index 0000000000..a5dbcd3cef --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/tgt.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +#include "opj_includes.h" + +/* +========================================================== + Tag-tree coder interface +========================================================== +*/ + +opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv) { + int nplh[32]; + int nplv[32]; + opj_tgt_node_t *node = NULL; + opj_tgt_node_t *parentnode = NULL; + opj_tgt_node_t *parentnode0 = NULL; + opj_tgt_tree_t *tree = NULL; + int i, j, k; + int numlvls; + int n; + + tree = (opj_tgt_tree_t *) opj_malloc(sizeof(opj_tgt_tree_t)); + if(!tree) return NULL; + tree->numleafsh = numleafsh; + tree->numleafsv = numleafsv; + + numlvls = 0; + nplh[0] = numleafsh; + nplv[0] = numleafsv; + tree->numnodes = 0; + do { + n = nplh[numlvls] * nplv[numlvls]; + nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2; + nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2; + tree->numnodes += n; + ++numlvls; + } while (n > 1); + + /* ADD */ + if (tree->numnodes == 0) { + opj_free(tree); + return NULL; + } + + tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t)); + if(!tree->nodes) { + opj_free(tree); + return NULL; + } + + node = tree->nodes; + parentnode = &tree->nodes[tree->numleafsh * tree->numleafsv]; + parentnode0 = parentnode; + + for (i = 0; i < numlvls - 1; ++i) { + for (j = 0; j < nplv[i]; ++j) { + k = nplh[i]; + while (--k >= 0) { + node->parent = parentnode; + ++node; + if (--k >= 0) { + node->parent = parentnode; + ++node; + } + ++parentnode; + } + if ((j & 1) || j == nplv[i] - 1) { + parentnode0 = parentnode; + } else { + parentnode = parentnode0; + parentnode0 += nplh[i]; + } + } + } + node->parent = 0; + + tgt_reset(tree); + + return tree; +} + +void tgt_destroy(opj_tgt_tree_t *tree) { + opj_free(tree->nodes); + opj_free(tree); +} + +void tgt_reset(opj_tgt_tree_t *tree) { + int i; + + if (NULL == tree) + return; + + for (i = 0; i < tree->numnodes; i++) { + tree->nodes[i].value = 999; + tree->nodes[i].low = 0; + tree->nodes[i].known = 0; + } +} + +void tgt_setvalue(opj_tgt_tree_t *tree, int leafno, int value) { + opj_tgt_node_t *node; + node = &tree->nodes[leafno]; + while (node && node->value > value) { + node->value = value; + node = node->parent; + } +} + +void tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold) { + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + int low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; + } + + while (low < threshold) { + if (low >= node->value) { + if (!node->known) { + bio_write(bio, 1, 1); + node->known = 1; + } + break; + } + bio_write(bio, 0, 1); + ++low; + } + + node->low = low; + if (stkptr == stk) + break; + node = *--stkptr; + } +} + +int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold) { + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + int low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; + } + while (low < threshold && low < node->value) { + if (bio_read(bio, 1)) { + node->value = low; + } else { + ++low; + } + } + node->low = low; + if (stkptr == stk) { + break; + } + node = *--stkptr; + } + + return (node->value < threshold) ? 1 : 0; +} diff --git a/src/add-ons/translators/icns/openjpeg/tgt.h b/src/add-ons/translators/icns/openjpeg/tgt.h new file mode 100644 index 0000000000..c08c8da0af --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/tgt.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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 __TGT_H +#define __TGT_H +/** +@file tgt.h +@brief Implementation of a tag-tree coder (TGT) + +The functions in TGT.C have for goal to realize a tag-tree coder. The functions in TGT.C +are used by some function in T2.C. +*/ + +/** @defgroup TGT TGT - Implementation of a tag-tree coder */ +/*@{*/ + +/** +Tag node +*/ +typedef struct opj_tgt_node { + struct opj_tgt_node *parent; + int value; + int low; + int known; +} opj_tgt_node_t; + +/** +Tag tree +*/ +typedef struct opj_tgt_tree { + int numleafsh; + int numleafsv; + int numnodes; + opj_tgt_node_t *nodes; +} opj_tgt_tree_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a tag-tree +@param numleafsh Width of the array of leafs of the tree +@param numleafsv Height of the array of leafs of the tree +@return Returns a new tag-tree if successful, returns NULL otherwise +*/ +opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv); +/** +Destroy a tag-tree, liberating memory +@param tree Tag-tree to destroy +*/ +void tgt_destroy(opj_tgt_tree_t *tree); +/** +Reset a tag-tree (set all leaves to 0) +@param tree Tag-tree to reset +*/ +void tgt_reset(opj_tgt_tree_t *tree); +/** +Set the value of a leaf of a tag-tree +@param tree Tag-tree to modify +@param leafno Number that identifies the leaf to modify +@param value New value of the leaf +*/ +void tgt_setvalue(opj_tgt_tree_t *tree, int leafno, int value); +/** +Encode the value of a leaf of the tag-tree up to a given threshold +@param bio Pointer to a BIO handle +@param tree Tag-tree to modify +@param leafno Number that identifies the leaf to encode +@param threshold Threshold to use when encoding value of the leaf +*/ +void tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold); +/** +Decode the value of a leaf of the tag-tree up to a given threshold +@param bio Pointer to a BIO handle +@param tree Tag-tree to decode +@param leafno Number that identifies the leaf to decode +@param threshold Threshold to use when decoding value of the leaf +@return Returns 1 if the node's value < threshold, returns 0 otherwise +*/ +int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __TGT_H */ diff --git a/src/add-ons/translators/icns/openjpeg/thix_manager.c b/src/add-ons/translators/icns/openjpeg/thix_manager.c new file mode 100644 index 0000000000..aa55f217c0 --- /dev/null +++ b/src/add-ons/translators/icns/openjpeg/thix_manager.c @@ -0,0 +1,120 @@ +/* + * $Id: thix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include +#include +#include +#include "opj_includes.h" + +/* + * Write tile-part headers mhix box + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] tileno tile number + * @param[in] cio file output handle + * @return length of mhix box + */ +int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio); + +int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio) +{ + int len, lenp, i; + int tileno; + opj_jp2_box_t *box; + + lenp = 0; + box = (opj_jp2_box_t *)opj_calloc( cstr_info.tw*cstr_info.th, sizeof(opj_jp2_box_t)); + + for ( i = 0; i < 2 ; i++ ){ + if (i) + cio_seek( cio, lenp); + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_THIX, 4); /* THIX */ + write_manf( i, cstr_info.tw*cstr_info.th, box, cio); + + for (tileno = 0; tileno < cstr_info.tw*cstr_info.th; tileno++){ + box[tileno].length = write_tilemhix( coff, cstr_info, tileno, cio); + box[tileno].type = JPIP_MHIX; + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + } + + opj_free(box); + + return len; +} + +int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio) +{ + int i; + opj_tile_info_t tile; + opj_tp_info_t tp; + int len, lenp; + opj_marker_info_t *marker; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_MHIX, 4); /* MHIX */ + + tile = cstr_info.tile[tileno]; + tp = tile.tp[0]; + + cio_write( cio, tp.tp_end_header-tp.tp_start_pos+1, 8); /* TLEN */ + + marker = cstr_info.tile[tileno].marker; + + for( i=0; i +#include "opj_includes.h" + +#define MAX(a,b) ((a)>(b)?(a):(b)) + + +/* + * Write faix box of tpix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ +int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio); + + +int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio) +{ + int len, lenp; + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_TPIX, 4); /* TPIX */ + + write_tpixfaix( coff, 0, cstr_info, j2klen, cio); + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} + + +/* + * Get number of maximum tile parts per tile + * + * @param[in] cstr_info codestream information + * @return number of maximum tile parts per tile + */ +int get_num_max_tile_parts( opj_codestream_info_t cstr_info); + +int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio) +{ + int len, lenp; + int i, j; + int Aux; + int num_max_tile_parts; + int size_of_coding; /* 4 or 8 */ + opj_tp_info_t tp; + int version; + + num_max_tile_parts = get_num_max_tile_parts( cstr_info); + + if( j2klen > pow( 2, 32)){ + size_of_coding = 8; + version = num_max_tile_parts == 1 ? 1:3; + } + else{ + size_of_coding = 4; + version = num_max_tile_parts == 1 ? 0:2; + } + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FAIX, 4); /* FAIX */ + cio_write( cio, version, 1); /* Version 0 = 4 bytes */ + + cio_write( cio, num_max_tile_parts, size_of_coding); /* NMAX */ + cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */ + for (i = 0; i < cstr_info.tw*cstr_info.th; i++){ + for (j = 0; j < cstr_info.tile[i].num_tps; j++){ + tp = cstr_info.tile[i].tp[j]; + cio_write( cio, tp.tp_start_pos-coff, size_of_coding); /* start position */ + cio_write( cio, tp.tp_end_pos-tp.tp_start_pos+1, size_of_coding); /* length */ + if (version & 0x02){ + if( cstr_info.tile[i].num_tps == 1 && cstr_info.numdecompos[compno] > 1) + Aux = cstr_info.numdecompos[compno] + 1; + else + Aux = j + 1; + + cio_write( cio, Aux,4); + /*cio_write(img.tile[i].tile_parts[j].num_reso_AUX,4);*/ /* Aux_i,j : Auxiliary value */ + /* fprintf(stderr,"AUX value %d\n",Aux);*/ + } + /*cio_write(0,4);*/ + } + /* PADDING */ + while (j < num_max_tile_parts){ + cio_write( cio, 0, size_of_coding); /* start position */ + cio_write( cio, 0, size_of_coding); /* length */ + if (version & 0x02) + cio_write( cio, 0,4); /* Aux_i,j : Auxiliary value */ + j++; + } + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; + +} + +int get_num_max_tile_parts( opj_codestream_info_t cstr_info) +{ + int num_max_tp = 0, i; + + for( i=0; i Date: Thu, 8 Nov 2012 10:32:22 +0000 Subject: [PATCH 3/9] Add Apple icon translator to the image --- build/jam/HaikuImage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 81fddaefd8..1f182c0b8f 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -129,7 +129,7 @@ SYSTEM_ADD_ONS_TRANSLATORS = BMPTranslator EXRTranslator GIFTranslator HVIFTranslator ICOTranslator JPEGTranslator JPEG2000Translator PCXTranslator PNGTranslator PPMTranslator RAWTranslator RTFTranslator SGITranslator STXTTranslator TGATranslator - TIFFTranslator WebPTranslator WonderBrushTranslator + TIFFTranslator WebPTranslator WonderBrushTranslator ICNSTranslator ; SYSTEM_ADD_ONS_LOCALE_CATALOGS = plaintext ; SYSTEM_ADD_ONS_MEDIA = cortex_audioadapter.media_addon From d3f77ddee320d0795e516d316b1fc7e0b85c905e Mon Sep 17 00:00:00 2001 From: Humdinger Date: Thu, 8 Nov 2012 20:05:45 +0100 Subject: [PATCH 4/9] Added correct flags for Hungarian and Brazilian. +alpha4 (just in case its rebuild...) --- docs/welcome/images/flags/hu.png | Bin 0 -> 124 bytes docs/welcome/images/flags/pt_BR.png | Bin 0 -> 337 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/welcome/images/flags/hu.png create mode 100644 docs/welcome/images/flags/pt_BR.png diff --git a/docs/welcome/images/flags/hu.png b/docs/welcome/images/flags/hu.png new file mode 100644 index 0000000000000000000000000000000000000000..6ddb72d90541b0785a3feb08ba37f2f1ba343cf1 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~e!VDy5o>bTbq$C1-LR=Zz1Dsl71Dcb!1cmH% z@i-@{{_NSa|Ns9lo%MS*P>sB&i(?4K^<)#l1ct`{J?nNzzH~8Qv1^d*iIC_DU}Fg1 W#BW*iU}+UlDTAl0pUXO@geCxY>L+Lb literal 0 HcmV?d00001 diff --git a/docs/welcome/images/flags/pt_BR.png b/docs/welcome/images/flags/pt_BR.png new file mode 100644 index 0000000000000000000000000000000000000000..93c6ee03c3fbb46773dae2757cb69bfe771f34e0 GIT binary patch literal 337 zcmV-X0j~auP)!UNb|;)WJ3VwllTb#WI7&`;Oj?LgPI6F?T3=ajU~iCRr8s7#IA?a0Z-1G8kfec< zrGc$Af^}(vtu=*~sFtX+oQq<6hnihsJJUAC@PyprJDc$I|@Yy&C{JTliUMe{=|oL+IU6bb%(Sde3Fmw3qtXg$2tS9s Date: Fri, 9 Nov 2012 00:21:41 +0100 Subject: [PATCH 5/9] vm_page_allocate_page_run: use a mask to enforce the boundary * use a mask to enforce the boundary as suggested by Ingo. Thanks! --- src/system/kernel/vm/vm_page.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/system/kernel/vm/vm_page.cpp b/src/system/kernel/vm/vm_page.cpp index 007aacdae9..d2add5a297 100644 --- a/src/system/kernel/vm/vm_page.cpp +++ b/src/system/kernel/vm/vm_page.cpp @@ -3831,8 +3831,8 @@ vm_page_allocate_page_run(uint32 flags, page_num_t length, ASSERT(((alignmentMask + 1) & alignmentMask) == 0); // alignment must be a power of 2 - // compute the boundary shift - uint32 boundaryShift = 0; + // compute the boundary mask + uint32 boundaryMask = 0; if (restrictions->boundary != 0) { page_num_t boundary = restrictions->boundary / B_PAGE_SIZE; // boundary must be a power of two and not less than alignment and @@ -3841,8 +3841,7 @@ vm_page_allocate_page_run(uint32 flags, page_num_t length, ASSERT(boundary >= alignmentMask + 1); ASSERT(boundary >= length); - while ((boundary >>= 1) > 0) - boundaryShift++; + boundaryMask = -boundary; } vm_page_reservation reservation; @@ -3858,19 +3857,17 @@ vm_page_allocate_page_run(uint32 flags, page_num_t length, int useCached = freePages > 0 && (page_num_t)freePages > 2 * length ? 0 : 1; for (;;) { - if (alignmentMask != 0 || boundaryShift != 0) { + if (alignmentMask != 0 || boundaryMask != 0) { page_num_t offsetStart = start + sPhysicalPageOffset; // enforce alignment - if ((offsetStart & alignmentMask) != 0) { + if ((offsetStart & alignmentMask) != 0) offsetStart = (offsetStart + alignmentMask) & ~alignmentMask; - } // enforce boundary - if (boundaryShift != 0 && offsetStart << boundaryShift - != (offsetStart + length - 1) << boundaryShift) { - offsetStart = (offsetStart + length - 1) << boundaryShift - >> boundaryShift; + if (boundaryMask != 0 && ((offsetStart ^ (offsetStart + + length - 1)) & boundaryMask) != 0) { + offsetStart = (offsetStart + length - 1) & boundaryMask; } start = offsetStart - sPhysicalPageOffset; From 99400679903cd8b0eabac0b90d8abfc8980ae453 Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Thu, 8 Nov 2012 23:27:52 +0000 Subject: [PATCH 6/9] Add MIME type for Apple icon --- src/data/beos_mime/image/icns | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/data/beos_mime/image/icns diff --git a/src/data/beos_mime/image/icns b/src/data/beos_mime/image/icns new file mode 100644 index 0000000000..92f87ad95d --- /dev/null +++ b/src/data/beos_mime/image/icns @@ -0,0 +1,13 @@ + +resource(0, "BEOS:TYPE") #'MIMS' "application/x-vnd.Be-meta-mime"; + +resource(1, "META:TYPE") "image/icns"; + +resource(2, "META:SNIFF_RULE") "0.50 (\"icns\")"; + +resource(3, "META:S:DESC") #'MSDC' "Apple icon"; + +resource(4, "META:EXTENS") message(234) { + "extensions" = "icns", + "type" = "image/icns" +}; From 69fb792e7661d7e916cace862c4639d164617927 Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Fri, 9 Nov 2012 00:46:22 +0000 Subject: [PATCH 7/9] ICNSTranslator: Fix memory leak --- src/add-ons/translators/icns/ICNSLoader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/add-ons/translators/icns/ICNSLoader.cpp b/src/add-ons/translators/icns/ICNSLoader.cpp index c98c34f446..032ef65fd0 100644 --- a/src/add-ons/translators/icns/ICNSLoader.cpp +++ b/src/add-ons/translators/icns/ICNSLoader.cpp @@ -223,6 +223,7 @@ ICNSSaver::ICNSSaver(BPositionIO *stream, uint32 rowBytes, icns_type_t type) icns_type_t iconType = icns_get_type_from_image_info(iconInfo); if (iconType == ICNS_NULL_TYPE) { + delete bits; free(fIconFamily); fIconFamily = NULL; return; @@ -278,6 +279,8 @@ ICNSSaver::ICNSSaver(BPositionIO *stream, uint32 rowBytes, icns_type_t type) free(fIconFamily); fIconFamily = NULL; } + + delete bits; } From 0810cfe451df8e618ff49320f055ee4eee316dca Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Fri, 9 Nov 2012 00:50:04 +0000 Subject: [PATCH 8/9] ICNSTranslator: Add icon number for multi-element files --- src/add-ons/translators/icns/ICNSTranslator.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/add-ons/translators/icns/ICNSTranslator.cpp b/src/add-ons/translators/icns/ICNSTranslator.cpp index 0eca734f9e..843a49c970 100644 --- a/src/add-ons/translators/icns/ICNSTranslator.cpp +++ b/src/add-ons/translators/icns/ICNSTranslator.cpp @@ -139,7 +139,10 @@ ICNSTranslator::DerivedIdentify(BPositionIO *stream, info->group = B_TRANSLATOR_BITMAP; info->quality = ICNS_IN_QUALITY; info->capability = ICNS_IN_CAPABILITY; - snprintf(info->name, sizeof(info->name), "Apple icon"); + BString iconName("Apple icon"); + if (documentCount > 1) + iconName << " #" << documentIndex; + snprintf(info->name, sizeof(info->name), iconName.String()); strcpy(info->MIME, kICNSMimeType); return B_OK; From 70f32936e931e6a4835d5f293fb16272c8a9af5d Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Fri, 9 Nov 2012 04:15:30 +0000 Subject: [PATCH 9/9] ICNSTranslator: Minor fixes * documentIndex not zero-based * more error handling * memory leak --- src/add-ons/translators/icns/ICNSLoader.cpp | 22 +++++++++++++------ .../translators/icns/ICNSTranslator.cpp | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/add-ons/translators/icns/ICNSLoader.cpp b/src/add-ons/translators/icns/ICNSLoader.cpp index 032ef65fd0..49f27e9362 100644 --- a/src/add-ons/translators/icns/ICNSLoader.cpp +++ b/src/add-ons/translators/icns/ICNSLoader.cpp @@ -60,6 +60,9 @@ ICNSLoader::ICNSLoader(BPositionIO *stream) stream->Seek(0, SEEK_END); fStreamSize = stream->Position(); stream->Seek(0, SEEK_SET); + + if (fStreamSize <= 0) + return; uint8* icnsDataBuffer = new uint8[fStreamSize]; size_t readedBytes = stream->Read(icnsDataBuffer,fStreamSize); @@ -67,8 +70,11 @@ ICNSLoader::ICNSLoader(BPositionIO *stream) fIconFamily = NULL; int status = icns_import_family_data(readedBytes, icnsDataBuffer, &fIconFamily); - if (status != 0) + + if (status != 0) { + delete icnsDataBuffer; return; + } icns_byte_t *dataPtr = (icns_byte_t*)fIconFamily; off_t dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); @@ -89,10 +95,10 @@ ICNSLoader::ICNSLoader(BPositionIO *stream) } dataOffset += iconElement.elementSize; } - + fFormatList.SortItems(compareTypes); - delete icnsDataBuffer; + delete icnsDataBuffer; fLoaded = true; } @@ -275,7 +281,7 @@ ICNSSaver::ICNSSaver(BPositionIO *stream, uint32 rowBytes, icns_type_t type) icns_free_image(&icnsMask); } - if(!fCreated) { + if (!fCreated) { free(fIconFamily); fIconFamily = NULL; } @@ -297,9 +303,11 @@ ICNSSaver::SaveData(BPositionIO *target) icns_size_t dataSize; icns_byte_t *dataPtrOut; icns_export_family_data(fIconFamily, &dataSize, &dataPtrOut); - target->Write(dataPtrOut, dataSize); - - return B_OK; + if (dataSize != 0 && dataPtrOut != NULL) { + if (target->Write(dataPtrOut, dataSize) == dataSize); + return B_OK; + } + return B_ERROR; } diff --git a/src/add-ons/translators/icns/ICNSTranslator.cpp b/src/add-ons/translators/icns/ICNSTranslator.cpp index 843a49c970..c4cf42d868 100644 --- a/src/add-ons/translators/icns/ICNSTranslator.cpp +++ b/src/add-ons/translators/icns/ICNSTranslator.cpp @@ -191,7 +191,7 @@ ICNSTranslator::DerivedTranslate(BPositionIO *source, if (!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0) return B_NO_TRANSLATOR; - int32 documentIndex = 0; + int32 documentIndex = 1; if (ioExtension) { if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK)