MJ2 codec restructuration. Created MJ2_codec directory and moved M2 codec files to this directory

This commit is contained in:
Francois-Olivier Devaux 2006-12-08 17:04:31 +00:00
parent 76ee6b8441
commit bc145d8dc8
22 changed files with 9261 additions and 0 deletions

View File

@ -0,0 +1,128 @@
# Microsoft Developer Studio Project File - Name="MJ2_Extractor" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=MJ2_Extractor - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "MJ2_Extractor.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "MJ2_Extractor.mak" CFG="MJ2_Extractor - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "MJ2_Extractor - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "MJ2_Extractor - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "MJ2_Extractor - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../libopenjpeg" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "MJ2_Extractor - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "MJ2_Extractor___Win32_Debug"
# PROP BASE Intermediate_Dir "MJ2_Extractor___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "MJ2_Extractor___Win32_Debug"
# PROP Intermediate_Dir "MJ2_Extractor___Win32_Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../libopenjpeg" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "MJ2_Extractor - Win32 Release"
# Name "MJ2_Extractor - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\libopenjpeg\cio.c
# End Source File
# Begin Source File
SOURCE=.\extract_j2k_from_mj2.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.c
# End Source File
# Begin Source File
SOURCE=.\mj2.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\libopenjpeg\cio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.h
# End Source File
# Begin Source File
SOURCE=.\mj2.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@ -0,0 +1,136 @@
# Microsoft Developer Studio Project File - Name="MJ2_Wrapper" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=MJ2_Wrapper - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "MJ2_Wrapper.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "MJ2_Wrapper.mak" CFG="MJ2_Wrapper - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "MJ2_Wrapper - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "MJ2_Wrapper - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "MJ2_Wrapper - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../libopenjpeg" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "MJ2_Wrapper - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "MJ2_Wrapper___Win32_Debug"
# PROP BASE Intermediate_Dir "MJ2_Wrapper___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "MJ2_Wrapper___Win32_Debug"
# PROP Intermediate_Dir "MJ2_Wrapper___Win32_Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../libopenjpeg" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "MJ2_Wrapper - Win32 Release"
# Name "MJ2_Wrapper - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\libopenjpeg\cio.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.c
# End Source File
# Begin Source File
SOURCE=.\mj2.c
# End Source File
# Begin Source File
SOURCE=.\wrap_j2k_in_mj2.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\libopenjpeg\cio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.h
# End Source File
# Begin Source File
SOURCE=.\mj2.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

79
mj2/MJ2_codec/Makefile Normal file
View File

@ -0,0 +1,79 @@
#
# Valentin Mesaros (Octalis | DICE/UCL Belgium)
# 19 April 2005
#
# Makefile for mj2 source files (frames_to_mj2, mj2_to_frames, extract_j2k_from_mj2, wrap_j2k_in_mj2)
#
INCLUDES = -Imj2 \
-I../libopenjpeg
C_OPT = -Wall
CFLAGS = $(INCLUDES) $(C_OPT)
CC = gcc
OBJ_MJ2_DIR = obj
BIN_MJ2_DIR = bin
LIB_OPENJPEG_DIR = ../libopenjpeg/lib
LIB_OPENJPEG = $(LIB_OPENJPEG_DIR)/libopenjpeg.a
all: $(OBJ_MJ2_DIR) $(BIN_MJ2_DIR) \
$(BIN_MJ2_DIR)/frames_to_mj2 \
$(BIN_MJ2_DIR)/mj2_to_frames \
$(BIN_MJ2_DIR)/extract_j2k_from_mj2 \
$(BIN_MJ2_DIR)/wrap_j2k_in_mj2
$(OBJ_MJ2_DIR):
mkdir $(OBJ_MJ2_DIR)
$(BIN_MJ2_DIR):
mkdir $(BIN_MJ2_DIR)
$(OBJ_MJ2_DIR)/%.o:
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJ_MJ2_DIR)/frames_to_mj2.o: frames_to_mj2.c
$(OBJ_MJ2_DIR)/mj2_to_frames.o: mj2_to_frames.c
$(OBJ_MJ2_DIR)/mj2.o: mj2.c
$(OBJ_MJ2_DIR)/mj2_convert.o: mj2_convert.c
$(OBJ_MJ2_DIR)/extract_j2k_from_mj2.o: extract_j2k_from_mj2.c
$(OBJ_MJ2_DIR)/wrap_j2k_in_mj2.o: wrap_j2k_in_mj2.c
MJ2_OBJS = $(addprefix $(OBJ_MJ2_DIR)/, mj2.o mj2_convert.o)
$(BIN_MJ2_DIR)/frames_to_mj2: $(OBJ_MJ2_DIR)/frames_to_mj2.o $(MJ2_OBJS) $(LIB_OPENJPEG)
$(CC) $(CFLAGS) \
-o $(BIN_MJ2_DIR)/frames_to_mj2 \
$(MJ2_OBJS) $(OBJ_MJ2_DIR)/frames_to_mj2.o \
$(LIB_OPENJPEG) \
-lm
$(BIN_MJ2_DIR)/mj2_to_frames: $(OBJ_MJ2_DIR)/mj2_to_frames.o $(MJ2_OBJS) $(LIB_OPENJPEG)
$(CC) $(CFLAGS) \
-o $(BIN_MJ2_DIR)/mj2_to_frames \
$(MJ2_OBJS) $(OBJ_MJ2_DIR)/mj2_to_frames.o \
$(LIB_OPENJPEG) \
-lm
$(BIN_MJ2_DIR)/extract_j2k_from_mj2: $(OBJ_MJ2_DIR)/extract_j2k_from_mj2.o $(MJ2_OBJS) $(LIB_OPENJPEG)
$(CC) $(CFLAGS) \
-o $(BIN_MJ2_DIR)/extract_j2k_from_mj2 \
$(MJ2_OBJS) $(OBJ_MJ2_DIR)/extract_j2k_from_mj2.o \
$(LIB_OPENJPEG) \
-lm
$(BIN_MJ2_DIR)/wrap_j2k_in_mj2: $(OBJ_MJ2_DIR)/wrap_j2k_in_mj2.o $(MJ2_OBJS) $(LIB_OPENJPEG)
$(CC) $(CFLAGS) \
-o $(BIN_MJ2_DIR)/wrap_j2k_in_mj2 \
$(MJ2_OBJS) $(OBJ_MJ2_DIR)/wrap_j2k_in_mj2.o \
$(LIB_OPENJPEG) \
-lm
clean:
rm -f $(BIN_MJ2_DIR)/* $(OBJ_MJ2_DIR)/*

View File

@ -0,0 +1,81 @@
#include <stdio.h>
#include <malloc.h>
#include <setjmp.h>
#include "mj2.h"
//MEMORY LEAK
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h> // Must be included first
#include <crtdbg.h>
#endif
//MEM
jmp_buf j2k_error;
int main(int argc, char *argv[]) {
int tnum;
unsigned int snum;
mj2_movie_t movie;
mj2_tk_t *track;
mj2_sample_t *sample;
unsigned char* frame_codestream;
FILE *file, *outfile;
char outfilename[50];
if (argc != 3) {
printf("Bad syntax: Usage: MJ2_extractor mj2filename output_location\n");
printf("Example: MJ2_extractor foreman.mj2 output/foreman\n");
return 1;
}
file = fopen(argv[1], "rb");
if (!file) {
fprintf(stderr, "failed to open %s for reading\n", argv[1]);
return 1;
}
if (mj2_read_struct(file, &movie)) // Creating the movie structure
return 1;
// Decode first video track
tnum = 0;
while (movie.tk[tnum].track_type != 0)
tnum ++;
track = &movie.tk[tnum];
fprintf(stdout,"Extracting %d frames from file...\n",track->num_samples);
for (snum=0; snum < track->num_samples; snum++)
{
sample = &track->sample[snum];
frame_codestream = (unsigned char*) malloc (sample->sample_size-8); // Skipping JP2C marker
fseek(file,sample->offset+8,SEEK_SET);
fread(frame_codestream,sample->sample_size-8,1, file); // Assuming that jp and ftyp markers size do
sprintf(outfilename,"%s_%d.j2k",argv[2],snum);
outfile = fopen(outfilename, "wb");
if (!outfile) {
fprintf(stderr, "failed to open %s for writing\n",outfilename);
return 1;
}
fwrite(frame_codestream,sample->sample_size-8,1,outfile);
fclose(outfile);
free(frame_codestream);
}
fclose(file);
fprintf(stdout, "%d frames correctly extracted\n", snum);
mj2_memory_free(&movie);
//MEMORY LEAK
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif
//MEM
return 0;
}

View File

@ -0,0 +1,997 @@
/*
* Copyright (c) 2003-2004, François-Olivier Devaux
* Copyright (c) 2002-2004, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
* 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 <openjpeg.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <setjmp.h>
#ifndef DONT_HAVE_GETOPT
#include <getopt.h>
#else
#include "compat/getopt.h"
#endif
#include "mj2_convert.h"
#define MJ2_MDAT 0x6d646174
#define JP2_JP2C 0x6a703263
//MEMORY LEAK
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h> // Must be included first
#include <crtdbg.h>
#endif
//MEM
jmp_buf j2k_error;
void help_display()
{
fprintf(stdout,"HELP\n----\n\n");
fprintf(stdout,"- the -h option displays this help information on screen\n\n");
fprintf(stdout,"List of parameters for the MJ2 encoder:\n");
fprintf(stdout,"\n");
fprintf(stdout,"REMARKS:\n");
fprintf(stdout,"---------\n");
fprintf(stdout,"\n");
fprintf
(stdout,"The markers written to the main_header are : SOC SIZ COD QCD COM.\n");
fprintf
(stdout,"COD and QCD never appear in the tile_header.\n");
fprintf(stdout,"\n");
fprintf
(stdout,"- This coder can encode a mega image, a test was made on a 24000x24000 pixels \n");
fprintf
(stdout,"color image. You need enough disk space memory (twice the original) to encode \n");
fprintf
(stdout,"the image,i.e. for a 1.5 GB image you need a minimum of 3GB of disk memory)\n");
fprintf(stdout,"\n");
fprintf(stdout,"By default:\n");
fprintf(stdout,"------------\n");
fprintf(stdout,"\n");
fprintf(stdout," * Lossless\n");
fprintf(stdout," * 1 tile\n");
fprintf(stdout," * Size of precinct : 2^15 x 2^15 (means 1 precinct)\n");
fprintf(stdout," * Size of code-block : 64 x 64\n");
fprintf(stdout," * Number of resolutions: 6\n");
fprintf(stdout," * No SOP marker in the codestream\n");
fprintf(stdout," * No EPH marker in the codestream\n");
fprintf(stdout," * No sub-sampling in x or y direction\n");
fprintf(stdout," * No mode switch activated\n");
fprintf(stdout," * Progression order: LRCP\n");
fprintf(stdout," * No index file\n");
fprintf(stdout," * No ROI upshifted\n");
fprintf(stdout," * No offset of the origin of the image\n");
fprintf(stdout," * No offset of the origin of the tiles\n");
fprintf(stdout," * Reversible DWT 5-3\n");
fprintf(stdout,"\n");
fprintf(stdout,"Parameters:\n");
fprintf(stdout,"------------\n");
fprintf(stdout,"\n");
fprintf
(stdout,"Required Parameters (except with -h):\n");
fprintf
(stdout,"-i : source file (-i source.yuv) \n");
fprintf
(stdout,"-o : destination file (-o dest.mj2) \n");
fprintf
(stdout,"Optional Parameters:\n");
fprintf(stdout,"-h : display the help information \n");
fprintf(stdout,"-r : different compression ratios for successive layers (-r 20,10,5)\n ");
fprintf(stdout," - The rate specified for each quality level is the desired \n");
fprintf(stdout," compression factor.\n");
fprintf(stdout," Example: -r 20,10,1 means quality 1: compress 20x, \n");
fprintf(stdout," quality 2: compress 10x and quality 3: compress lossless\n");
fprintf(stdout," (options -r and -q cannot be used together)\n ");
fprintf(stdout,"-q : different psnr for successive layers (-q 30,40,50) \n ");
fprintf(stdout," (options -r and -q cannot be used together)\n ");
fprintf(stdout,"-n : number of resolutions (-n 3) \n");
fprintf(stdout,"-b : size of code block (-b 32,32) \n");
fprintf(stdout,"-c : size of precinct (-c 128,128) \n");
fprintf(stdout,"-t : size of tile (-t 512,512) \n");
fprintf
(stdout,"-p : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] \n");
fprintf
(stdout,"-s : subsampling factor (-s 2,2) [-s X,Y] \n");
fprintf(stdout," Remark: subsampling bigger than 2 can produce error\n");
fprintf
(stdout,"-SOP : write SOP marker before each packet \n");
fprintf
(stdout,"-EPH : write EPH marker after each header packet \n");
fprintf
(stdout,"-M : mode switch (-M 3) [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL)\n");
fprintf
(stdout," 8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)] \n");
fprintf
(stdout," Indicate multiple modes by adding their values. \n");
fprintf
(stdout," ex: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
fprintf
(stdout,"-x : create an index file *.Idx (-x index_name.Idx) \n");
fprintf
(stdout,"-ROI : c=%%d,U=%%d : quantization indices upshifted \n");
fprintf
(stdout," for component c=%%d [%%d = 0,1,2]\n");
fprintf
(stdout," with a value of U=%%d [0 <= %%d <= 37] (i.e. -ROI:c=0,U=25) \n");
fprintf
(stdout,"-d : offset of the origin of the image (-d 150,300) \n");
fprintf
(stdout,"-T : offset of the origin of the tiles (-T 100,75) \n");
fprintf(stdout,"-I : use the irreversible DWT 9-7 (-I) \n");
fprintf(stdout,"-W : image width, height and the dx and dy subsampling \n");
fprintf(stdout," of the Cb and Cr components for YUV files \n");
fprintf(stdout," (default is '352,288,2,2' for CIF format's 352x288 and 4:2:0)\n");
fprintf(stdout,"-F : video frame rate (set to 25 by default)\n");
fprintf(stdout,"\n");
fprintf(stdout,"IMPORTANT:\n");
fprintf(stdout,"-----------\n");
fprintf(stdout,"\n");
fprintf(stdout,"The index file has the structure below:\n");
fprintf(stdout,"---------------------------------------\n");
fprintf(stdout,"\n");
fprintf(stdout,"Image_height Image_width\n");
fprintf(stdout,"progression order\n");
fprintf(stdout,"Tiles_size_X Tiles_size_Y\n");
fprintf(stdout,"Components_nb\n");
fprintf(stdout,"Layers_nb\n");
fprintf(stdout,"decomposition_levels\n");
fprintf(stdout,"[Precincts_size_X_res_Nr Precincts_size_Y_res_Nr]...\n");
fprintf(stdout," [Precincts_size_X_res_0 Precincts_size_Y_res_0]\n");
fprintf(stdout,"Main_header_end_position\n");
fprintf(stdout,"Codestream_size\n");
fprintf(stdout,"Tile_0 start_pos end_Theader end_pos TotalDisto NumPix MaxMSE\n");
fprintf(stdout,"Tile_1 '' '' '' '' '' ''\n");
fprintf(stdout,"...\n");
fprintf(stdout,"Tile_Nt '' '' '' '' '' ''\n");
fprintf(stdout,"Tpacket_0 Tile layer res. comp. prec. start_pos end_pos disto\n");
fprintf(stdout,"...\n");
fprintf(stdout,"Tpacket_Np '' '' '' '' '' '' '' ''\n");
fprintf(stdout,"MaxDisto\n");
fprintf(stdout,"TotalDisto\n\n");
}
int give_progression(char progression[4])
{
if (progression[0] == 'L' && progression[1] == 'R'
&& progression[2] == 'C' && progression[3] == 'P') {
return 0;
} else {
if (progression[0] == 'R' && progression[1] == 'L'
&& progression[2] == 'C' && progression[3] == 'P') {
return 1;
} else {
if (progression[0] == 'R' && progression[1] == 'P'
&& progression[2] == 'C' && progression[3] == 'L') {
return 2;
} else {
if (progression[0] == 'P' && progression[1] == 'C'
&& progression[2] == 'R' && progression[3] == 'L') {
return 3;
} else {
if (progression[0] == 'C' && progression[1] == 'P'
&& progression[2] == 'R' && progression[3] == 'L') {
return 4;
} else {
return -1;
}
}
}
}
}
}
double dwt_norms_97[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}
};
int floorlog2(int a)
{
int l;
for (l = 0; a > 1; l++) {
a >>= 1;
}
return l;
}
void encode_stepsize(int stepsize, int numbps, int *expn, int *mant)
{
int p, n;
p = floorlog2(stepsize) - 13;
n = 11 - floorlog2(stepsize);
*mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff;
*expn = numbps - p;
}
void calc_explicit_stepsizes(j2k_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_97[orient][level];
stepsize = (1 << (gain + 1)) / norm;
}
encode_stepsize((int) floor(stepsize * 8192.0), prec + gain,
&tccp->stepsizes[bandno].expn,
&tccp->stepsizes[bandno].mant);
}
}
int main(int argc, char **argv)
{
int NumResolution, numD_min; /* NumResolution : number of resolution */
int Tile_arg; /* Tile_arg = 0 (not in argument) ou = 1 (in argument) */
int CSty; /* CSty : coding style */
int Prog_order; /* progression order (default LRCP) */
char progression[4];
int numpocs, numpocs_tile; /* Number of progression order change (POC) default 0 */
int prcw_init[J2K_MAXRLVLS]; /* Initialisation Precinct width */
int prch_init[J2K_MAXRLVLS]; /* Initialisation Precinct height */
//int prcw_init, prch_init; /* Initialisation precincts' size */
int cblockw_init, cblockh_init; /* Initialisation codeblocks' size */
int mode, value; /* Mode switch (cblk_style) */
int subsampling_dx, subsampling_dy; /* subsampling value for dx and dy */
int ROI_compno, ROI_shift; /* region of interrest */
int Dim[2]; /* portion of the image coded */
int TX0, TY0; /* tile off-set */
mj2_movie_t movie;
j2k_cp_t cp, cp_init; /* cp_init is used to initialise in multiple tiles */
j2k_tcp_t *tcp, *tcp_init; /* tcp_init is used to initialise in multiple tile */
j2k_poc_t POC[32]; /* POC : used in case of Progression order change */
j2k_poc_t *tcp_poc;
j2k_tccp_t *tccp;
int i, tileno, l, j;
char *infile = 0;
char *outfile = 0;
char *index = 0;
char *s, S1, S2, S3;
char *buf;
int ir = 0;
int res_spec = 0; /* For various precinct sizes specification */
char sep;
int w; /* Width of YUV file */
int h; /* Height of YUV file */
int CbCr_subsampling_dx; /* Sample rate of YUV 4:4:4 4:2:2 or 4:2:0 */
int CbCr_subsampling_dy; /* Sample rate of YUV 4:4:4 4:2:2 or 4:2:0 */
int frame_rate; /* Video Frame Rate */
int numcomps; /* In YUV files, numcomps always considered as 3 */
int prec; /* In YUV files, precision always considered as 8 */
int x1, y1, len, jp2c_initpos, m, k, pos;
long mdat_initpos, offset;
FILE *mj2file, *yuvfile;
unsigned int sampleno;
j2k_image_t img;
/* default value */
/* ------------- */
NumResolution = 6;
CSty = 0;
cblockw_init = 64;
cblockh_init = 64;
cp.tw = 1;
cp.th = 1;
cp.index_on = 0;
Prog_order = 0;
numpocs = 0;
mode = 0;
subsampling_dx = 1;
subsampling_dy = 1;
ROI_compno = -1; /* no ROI */
ROI_shift = 0;
Dim[0] = 0;
Dim[1] = 0;
TX0 = 0;
TY0 = 0;
cp.comment = NULL;
cp.disto_alloc = 0;
cp.fixed_alloc = 0;
cp.fixed_quality = 0; //add fixed_quality
w = 352; // CIF default value
h = 288; // CIF default value
CbCr_subsampling_dx = 2; // CIF default value
CbCr_subsampling_dy = 2; // CIF default value
frame_rate = 25;
Tile_arg = 0;
cp_init.tcps = (j2k_tcp_t *) malloc(sizeof(j2k_tcp_t)); /* initialisation if only one tile */
tcp_init = &cp_init.tcps[0];
tcp_init->numlayers = 0;
cp.intermed_file = 0; // Don't store each tile in a file during processing
while (1) {
int c = getopt(argc, argv,
"i:o:r:q:f:t:n:c:b:x:p:s:d:h:P:S:E:M:R:T:C:I:W:F:");
if (c == -1)
break;
switch (c) {
case 'i': /* IN fill */
infile = optarg;
s = optarg;
while (*s) {
s++;
}
s--;
S3 = *s;
s--;
S2 = *s;
s--;
S1 = *s;
if ((S1 == 'y' && S2 == 'u' && S3 == 'v')
|| (S1 == 'Y' && S2 == 'U' && S3 == 'V')) {
cp.decod_format = YUV_DFMT;
break;
}
fprintf(stderr,
"!! Unrecognized format for infile : %c%c%c [accept only *.yuv] !!\n\n",
S1, S2, S3);
return 1;
break;
/* ----------------------------------------------------- */
case 'o': /* OUT fill */
outfile = optarg;
while (*outfile) {
outfile++;
}
outfile--;
S3 = *outfile;
outfile--;
S2 = *outfile;
outfile--;
S1 = *outfile;
outfile = optarg;
if ((S1 == 'm' && S2 == 'j' && S3 == '2')
|| (S1 == 'M' && S2 == 'J' && S3 == '2'))
cp.cod_format = MJ2_CFMT;
else {
fprintf(stderr,
"Unknown output format image *.%c%c%c [only *.mj2]!! \n",
S1, S2, S3);
return 1;
}
break;
/* ----------------------------------------------------- */
case 'r': /* rates rates/distorsion */
s = optarg;
while (sscanf(s, "%d", &tcp_init->rates[tcp_init->numlayers])
== 1) {
tcp_init->numlayers++;
while (*s && *s != ',') {
s++;
}
if (!*s)
break;
s++;
}
cp.disto_alloc = 1;
cp.matrice = NULL;
break;
/* ----------------------------------------------------- */
case 'q': /* add fixed_quality */
s = optarg;
while (sscanf
(s, "%f", &tcp_init->distoratio[tcp_init->numlayers]) == 1) {
tcp_init->numlayers++;
while (*s && *s != ',') {
s++;
}
if (!*s)
break;
s++;
}
cp.fixed_quality = 1;
cp.matrice = NULL;
break;
/* dda */
/* ----------------------------------------------------- */
case 'f': /* mod fixed_quality (before : -q) */
s = optarg;
sscanf(s, "%d", &tcp_init->numlayers);
s++;
if (tcp_init->numlayers > 9)
s++;
cp.matrice =
(int *) malloc(tcp_init->numlayers * NumResolution * 3 *
sizeof(int));
s = s + 2;
for (i = 0; i < tcp_init->numlayers; i++) {
tcp_init->rates[i] = 1;
sscanf(s, "%d,", &cp.matrice[i * NumResolution * 3]);
s += 2;
if (cp.matrice[i * NumResolution * 3] > 9)
s++;
cp.matrice[i * NumResolution * 3 + 1] = 0;
cp.matrice[i * NumResolution * 3 + 2] = 0;
for (j = 1; j < NumResolution; j++) {
sscanf(s, "%d,%d,%d",
&cp.matrice[i * NumResolution * 3 + j * 3 + 0],
&cp.matrice[i * NumResolution * 3 + j * 3 + 1],
&cp.matrice[i * NumResolution * 3 + j * 3 + 2]);
s += 6;
if (cp.matrice[i * NumResolution * 3 + j * 3] > 9)
s++;
if (cp.matrice[i * NumResolution * 3 + j * 3 + 1] > 9)
s++;
if (cp.matrice[i * NumResolution * 3 + j * 3 + 2] > 9)
s++;
}
if (i < tcp_init->numlayers - 1)
s++;
}
cp.fixed_alloc = 1;
break;
/* ----------------------------------------------------- */
case 't': /* tiles */
sscanf(optarg, "%d,%d", &cp.tdx, &cp.tdy);
Tile_arg = 1;
break;
/* ----------------------------------------------------- */
case 'n': /* resolution */
sscanf(optarg, "%d", &NumResolution);
break;
/* ----------------------------------------------------- */
case 'c': /* precinct dimension */
s = optarg;
do {
sep = 0;
sscanf(s, "[%d,%d]%c", &prcw_init[res_spec],
&prch_init[res_spec], &sep);
CSty |= 0x01;
res_spec++;
s = strpbrk(s, "]") + 2;
} while (sep == ',');
break;
/* ----------------------------------------------------- */
case 'b': /* code-block dimension */
sscanf(optarg, "%d,%d", &cblockw_init, &cblockh_init);
if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024
|| cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) {
fprintf(stderr,
"!! Size of code_block error (option -b) !!\n\nRestriction :\n * width*height<=4096\n * 4<=width,height<= 1024\n\n");
return 1;
}
break;
/* ----------------------------------------------------- */
case 'x': /* creation of index file */
index = optarg;
cp.index_on = 1;
break;
/* ----------------------------------------------------- */
case 'p': /* progression order */
s = optarg;
for (i = 0; i < 4; i++) {
progression[i] = *s;
s++;
}
Prog_order = give_progression(progression);
if (Prog_order == -1) {
fprintf(stderr,
"Unrecognized progression order [LRCP, RLCP, RPCL, PCRL, CPRL] !!\n");
return 1;
}
break;
/* ----------------------------------------------------- */
case 's': /* subsampling factor */
if (sscanf(optarg, "%d,%d", &subsampling_dx, &subsampling_dy)
!= 2) {
fprintf(stderr,
"'-s' sub-sampling argument error ! [-s dx,dy]\n");
return 1;
}
break;
/* ----------------------------------------------------- */
case 'd': /* coordonnate of the reference grid */
if (sscanf(optarg, "%d,%d", &Dim[0], &Dim[1]) != 2) {
fprintf(stderr,
"-d 'coordonnate of the reference grid' argument error !! [-d x0,y0]\n");
return 1;
}
break;
/* ----------------------------------------------------- */
case 'h': /* Display an help description */
help_display();
return 0;
break;
/* ----------------------------------------------------- */
case 'P': /* POC */
fprintf(stderr, "/----------------------------------\\\n");
fprintf(stderr, "| POC option not fully tested !! |\n");
fprintf(stderr, "\\----------------------------------/\n");
s = optarg;
while (sscanf(s, "T%d=%d,%d,%d,%d,%d,%s", &POC[numpocs].tile,
&POC[numpocs].resno0, &POC[numpocs].compno0,
&POC[numpocs].layno1, &POC[numpocs].resno1,
&POC[numpocs].compno1, POC[numpocs].progorder) == 7) {
POC[numpocs].prg = give_progression(POC[numpocs].progorder);
/* POC[numpocs].tile; */
numpocs++;
while (*s && *s != '/') {
s++;
}
if (!*s)
break;
s++;
}
break;
/* ------------------------------------------------------ */
case 'S': /* SOP marker */
CSty |= 0x02;
break;
/* ------------------------------------------------------ */
case 'E': /* EPH marker */
CSty |= 0x04;
break;
/* ------------------------------------------------------ */
case 'M': /* Mode switch pas tous au point !! */
if (sscanf(optarg, "%d", &value) == 1) {
for (i = 0; i <= 5; i++) {
int cache = value & (1 << i);
if (cache)
mode |= (1 << i);
}
}
break;
/* ------------------------------------------------------ */
case 'R': /* ROI */
if (sscanf(optarg, "OI:c=%d,U=%d", &ROI_compno, &ROI_shift) != 2) {
fprintf(stderr, "ROI error !! [-ROI:c='compno',U='shift']\n");
return 1;
}
break;
/* ------------------------------------------------------ */
case 'T': /* Tile offset */
if (sscanf(optarg, "%d,%d", &TX0, &TY0) != 2) {
fprintf(stderr, "-T 'tile offset' argument error !! [-T X0,Y0]");
return 1;
}
break;
/* ------------------------------------------------------ */
case 'C': /* Add a comment */
cp.comment = optarg;
break;
/* ------------------------------------------------------ */
case 'I': /* reversible or not */
ir = 1;
break;
/* ------------------------------------------------------ */
case 'W': /* Width and Height and Cb and Cr subsampling in case of YUV format files */
if (sscanf
(optarg, "%d,%d,%d,%d", &w, &h, &CbCr_subsampling_dx,
&CbCr_subsampling_dy) != 4) {
fprintf(stderr, "-W argument error");
return 1;
}
break;
/* ------------------------------------------------------ */
case 'F': /* Video frame rate */
if (sscanf(optarg, "%d", &frame_rate) != 1) {
fprintf(stderr, "-F argument error");
return 1;
}
break;
/* ------------------------------------------------------ */
default:
return 1;
}
}
cp.tx0 = TX0;
cp.ty0 = TY0;
/* Error messages */
/* -------------- */
if (!infile || !outfile) {
fprintf(stderr,
"Correct usage: mj2_encoder -i yuv-file -o mj2-file (+ options)\n");
return 1;
}
if ((cp.disto_alloc || cp.fixed_alloc || cp.fixed_quality)
&& (!(cp.disto_alloc ^ cp.fixed_alloc ^ cp.fixed_quality))) {
fprintf(stderr,
"Error: options -r -q and -f can not be used together !!\n");
return 1;
} // mod fixed_quality
/* if no rate entered, lossless by default */
if (tcp_init->numlayers == 0) {
tcp_init->rates[tcp_init->numlayers] = 0; //MOD antonin : losslessbug
tcp_init->numlayers++;
cp.disto_alloc = 1;
}
if (TX0 > Dim[0] || TY0 > Dim[1]) {
fprintf(stderr,
"Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n",
TX0, Dim[0], TY0, Dim[1]);
return 1;
}
for (i = 0; i < numpocs; i++) {
if (POC[i].prg == -1) {
fprintf(stderr,
"Unrecognized progression order in option -P (POC n %d) [LRCP, RLCP, RPCL, PCRL, CPRL] !!\n",
i + 1);
}
}
/* to respect profile - 0 */
/* ---------------------- */
numD_min = 0;
x1 = !Dim[0] ? (w - 1) * subsampling_dx + 1 : Dim[0] + (w -
1) *
subsampling_dx + 1;
y1 = !Dim[1] ? (h - 1) * subsampling_dy + 1 : Dim[1] + (h -
1) *
subsampling_dy + 1;
if (Tile_arg == 1) {
cp.tw = int_ceildiv(x1 - cp.tx0, cp.tdx);
cp.th = int_ceildiv(y1 - cp.ty0, cp.tdy);
} else {
cp.tdx = x1 - cp.tx0;
cp.tdy = y1 - cp.ty0;
}
/* Initialization for PPM marker */
cp.ppm = 0;
cp.ppm_data = NULL;
cp.ppm_previous = 0;
cp.ppm_store = 0;
numcomps = 3; /* Because YUV files only have 3 components */
tcp_init->mct = 0; /* No component transform needed */
prec = 8; /* Because in YUV files, components have 8-bit depth */
/* Init the mutiple tiles */
/* ---------------------- */
cp.tcps = (j2k_tcp_t *) malloc(cp.tw * cp.th * sizeof(j2k_tcp_t));
for (tileno = 0; tileno < cp.tw * cp.th; tileno++) {
tcp = &cp.tcps[tileno];
tcp->numlayers = tcp_init->numlayers;
for (j = 0; j < tcp->numlayers; j++) {
if (cp.fixed_quality) // add fixed_quality
tcp->distoratio[j] = tcp_init->distoratio[j];
else
tcp->rates[j] = tcp_init->rates[j];
}
tcp->csty = CSty;
tcp->prg = Prog_order;
tcp->mct = tcp_init->mct;
tcp->ppt = 0;
tcp->ppt_data = NULL;
tcp->ppt_store = 0;
numpocs_tile = 0;
tcp->POC = 0;
if (numpocs) {
/* intialisation of POC */
tcp->POC = 1;
for (i = 0; i < numpocs; i++) {
if (tileno == POC[i].tile - 1 || POC[i].tile == -1) {
tcp_poc = &tcp->pocs[numpocs_tile];
tcp_poc->resno0 = POC[numpocs_tile].resno0;
tcp_poc->compno0 = POC[numpocs_tile].compno0;
tcp_poc->layno1 = POC[numpocs_tile].layno1;
tcp_poc->resno1 = POC[numpocs_tile].resno1;
tcp_poc->compno1 = POC[numpocs_tile].compno1;
tcp_poc->prg = POC[numpocs_tile].prg;
tcp_poc->tile = POC[numpocs_tile].tile;
numpocs_tile++;
}
}
}
tcp->numpocs = numpocs_tile;
tcp->tccps = (j2k_tccp_t *) malloc(numcomps * sizeof(j2k_tccp_t));
for (i = 0; i < numcomps; i++) {
tccp = &tcp->tccps[i];
tccp->csty = CSty & 0x01; /* 0 => one precinct || 1 => custom precinct */
tccp->numresolutions = NumResolution;
tccp->cblkw = int_floorlog2(cblockw_init);
tccp->cblkh = int_floorlog2(cblockh_init);
tccp->cblksty = mode;
tccp->qmfbid = ir ? 0 : 1;
tccp->qntsty = ir ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT;
tccp->numgbits = 2;
if (i == ROI_compno)
tccp->roishift = ROI_shift;
else
tccp->roishift = 0;
if (CSty & J2K_CCP_CSTY_PRT) {
int p = 0;
for (j = tccp->numresolutions - 1; j >= 0; j--) {
if (p < res_spec) {
if (prcw_init[p] < 1)
tccp->prcw[j] = 1;
else
tccp->prcw[j] = int_floorlog2(prcw_init[p]);
if (prch_init[p] < 1)
tccp->prch[j] = 1;
else
tccp->prch[j] = int_floorlog2(prch_init[p]);
} else {
int size_prcw, size_prch;
size_prcw = prcw_init[res_spec - 1] >> (p - (res_spec - 1));
size_prch = 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 pour level %d : %d,%d\n", j,
tccp->prcw[j], tccp->prch[j]); */
}
} else {
for (j = 0; j < tccp->numresolutions; j++) {
tccp->prcw[j] = 15;
tccp->prch[j] = 15;
}
}
calc_explicit_stepsizes(tccp, prec);
}
}
mj2file = fopen(outfile, "wb");
if (!mj2file) {
fprintf(stderr, "failed to open %s for writing\n", argv[2]);
return 1;
}
movie.tk = (mj2_tk_t *) malloc(sizeof(mj2_tk_t));
movie.num_vtk = 1;
movie.num_stk = 0;
movie.num_htk = 0;
movie.tk[0].track_type = 0; // Video Track
movie.tk[0].track_ID = 1;
movie.tk[0].Dim[0] = Dim[0];
movie.tk[0].Dim[1] = Dim[1];
movie.tk[0].w = w;
movie.tk[0].h = h;
movie.tk[0].CbCr_subsampling_dx = CbCr_subsampling_dx;
movie.tk[0].CbCr_subsampling_dy = CbCr_subsampling_dy;
movie.tk[0].sample_rate = frame_rate;
movie.tk[0].jp2_struct.numcomps = 3; // NC
jp2_init_stdjp2(&movie.tk[0].jp2_struct);
movie.tk[0].jp2_struct.w = w;
movie.tk[0].jp2_struct.h = h;
movie.tk[0].jp2_struct.bpc = 7;
movie.tk[0].jp2_struct.meth = 1;
movie.tk[0].jp2_struct.enumcs = 18; // YUV
yuvfile = fopen(infile,"rb");
if (!yuvfile) {
fprintf(stderr, "failed to open %s for reading\n",infile);
return 1;
}
movie.tk[0].num_samples = yuv_num_frames(&movie.tk[0],yuvfile);
if (!movie.tk[0].num_samples) {
fprintf(stderr,"Unable to count the number of frames in YUV input file\n");
}
// One sample per chunk
movie.tk[0].chunk = (mj2_chunk_t*) malloc(movie.tk[0].num_samples * sizeof(mj2_chunk_t));
movie.tk[0].sample = (mj2_sample_t*) malloc(movie.tk[0].num_samples * sizeof(mj2_sample_t));
if (mj2_init_stdmovie(&movie)) {
fprintf(stderr, "Error with movie initialization");
return 1;
};
// Writing JP, FTYP and MDAT boxes
buf = (char*) malloc (300 * sizeof(char)); // Assuming that the JP and FTYP
// boxes won't be longer than 300 bytes
cio_init(buf , 300);
mj2_write_jp();
mj2_write_ftyp(&movie);
mdat_initpos = cio_tell();
cio_skip(4);
cio_write(MJ2_MDAT, 4);
fwrite(buf,cio_tell(),1,mj2file);
offset = cio_tell();
free(buf);
for (i = 0; i < movie.num_stk + movie.num_htk + movie.num_vtk; i++) {
if (movie.tk[i].track_type != 0) {
fprintf(stderr, "Unable to write sound or hint tracks\n");
} else {
//j2k_cp_t cp_init;
mj2_tk_t *tk;
tk = &movie.tk[i];
//tk->sample =
//(mj2_sample_t *) malloc(tk->num_samples * sizeof(mj2_sample_t));
tk->num_chunks = tk->num_samples;
//tk->chunk =
//(mj2_chunk_t *) malloc(tk->num_chunks * sizeof(mj2_chunk_t));
fprintf(stderr, "Video Track number %d\n", i + 1);
// Copy the first tile coding parameters (tcp) to cp_init
//cp_init.tcps =
//(j2k_tcp_t *) malloc(cp.tw * cp.th * sizeof(j2k_tcp_t));
for (tileno = 0; tileno < cp.tw * cp.th; tileno++) {
for (l = 0; l < cp.tcps[tileno].numlayers; l++) {
cp_init.tcps[tileno].rates[l] = cp.tcps[tileno].rates[l];
//tileno = cp.tcps[tileno].rates[l];
}
}
for (sampleno = 0; sampleno < tk->num_samples; sampleno++) {
buf = (char *) malloc(cp.tdx * cp.tdy * cp.th * cp.tw * 2);
cio_init(buf, cp.tdx * cp.tdy * cp.th * cp.tw * 2);
fprintf(stderr, "Frame number %d/%d: ", sampleno + 1, tk->num_samples);
if (!yuvtoimage(yuvfile, tk, &img, sampleno, subsampling_dx, subsampling_dy)) {
fprintf(stderr, "Error with frame number %d in YUV file\n", sampleno);
return 1;
}
jp2c_initpos = cio_tell();
cio_skip(4);
cio_write(JP2_JP2C, 4); // JP2C
len = j2k_encode(&img, &cp, buf, cp.tdx * cp.tdy * 2, index);
if (len ==0) {
fprintf(stderr,"Unable to encode image");
return 1;
}
cio_seek(jp2c_initpos);
cio_write(len+8,4);
for (m = 0; m < img.numcomps; m++) {
free(img.comps[m].data);
}
free(img.comps);
tk->sample[sampleno].sample_size = len+8;
tk->sample[sampleno].offset = offset;
tk->chunk[sampleno].offset = offset; // There is one sample per chunk
fwrite(buf, 1, len+8, mj2file);
offset += len+8;
free(buf);
// Copy the cp_init parameters to cp.tcps
for (tileno = 0; tileno < cp.tw * cp.th; tileno++) {
for (k = 0; k < cp.tcps[tileno].numlayers; k++) {
cp.tcps[tileno].rates[k] = cp_init.tcps[tileno].rates[k];
}
}
}
}
}
fseek(mj2file, mdat_initpos, SEEK_SET);
buf = (char*) malloc(4*sizeof(char));
cio_init(buf, 4); // Init a cio to write box length variable in a little endian way
cio_write(offset - mdat_initpos, 4);
fwrite(buf, 4, 1, mj2file);
fseek(mj2file,0,SEEK_END);
free(buf);
// Writing MOOV box
i=1;
buf = (char*) malloc (10000 * sizeof(char));
cio_init(buf , i*10000);
if (setjmp(j2k_error)) {
i++;
realloc(buf,i*10000* sizeof(char));
pos = cio_tell();
cio_init(buf , i*10000);
cio_seek(pos);
}
mj2_write_moov(&movie);
fwrite(buf,cio_tell(),1,mj2file);
// Ending program
mj2_memory_free(&movie);
free(cp_init.tcps);
if (tcp_init->numlayers > 9)
free(cp.matrice);
for (tileno = 0; tileno < cp.tw * cp.th; tileno++)
free(cp.tcps[tileno].tccps);
free(cp.tcps);
fclose(mj2file);
free(buf);
remove("Compo0");
remove("Compo1");
remove("Compo2");
//MEMORY LEAK
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif
//MEM
return 0;
}

View File

@ -0,0 +1,269 @@
# Microsoft Developer Studio Project File - Name="frames_to_mj2" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=frames_to_mj2 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "frames_to_mj2.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "frames_to_mj2.mak" CFG="frames_to_mj2 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "frames_to_mj2 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "frames_to_mj2 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "frames_to_mj2 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../libopenjpeg" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DONT_HAVE_GETOPT" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "frames_to_mj2 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "frames_to_mj2___Win32_Debug0"
# PROP BASE Intermediate_Dir "frames_to_mj2___Win32_Debug0"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "frames_to_mj2___Win32_Debug0"
# PROP Intermediate_Dir "frames_to_mj2___Win32_Debug0"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../libopenjpeg" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DONT_HAVE_GETOPT" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "frames_to_mj2 - Win32 Release"
# Name "frames_to_mj2 - Win32 Debug"
# Begin Group "MJ2"
# PROP Default_Filter ""
# Begin Group "MJ2 Header Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\compat\getopt.h
# End Source File
# Begin Source File
SOURCE=.\mj2.h
# End Source File
# Begin Source File
SOURCE=.\mj2_convert.h
# End Source File
# End Group
# Begin Group "MJ2 Source Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\frames_to_mj2.c
# End Source File
# Begin Source File
SOURCE=.\compat\getopt.c
# End Source File
# Begin Source File
SOURCE=.\mj2.c
# End Source File
# Begin Source File
SOURCE=.\mj2_convert.c
# End Source File
# End Group
# End Group
# Begin Group "OpenJPEG"
# PROP Default_Filter ""
# Begin Group "OpenJPEG Header Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\libopenjpeg\bio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\cio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\dwt.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\fix.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jpt.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mct.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mqc.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\openjpeg.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\pi.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\raw.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t1.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t2.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tcd.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tgt.h
# End Source File
# End Group
# Begin Group "OpenJPEG Source Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\libopenjpeg\bio.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\cio.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\dwt.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\fix.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jpt.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mct.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mqc.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\pi.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\raw.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t1.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t2.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tcd.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tgt.c
# End Source File
# End Group
# End Group
# End Target
# End Project

2185
mj2/MJ2_codec/meta_out.c Normal file

File diff suppressed because it is too large Load Diff

13
mj2/MJ2_codec/meta_out.h Normal file
View File

@ -0,0 +1,13 @@
/* meta_out.h */
/* Dump MJ2, JP2 metadata (partial so far) to xml file */
/* Callable from mj2_to_metadata */
/* Contributed to Open JPEG by Glenn Pearson, U.S. National Library of Medicine */
#define BOOL int
#define FALSE 0
#define TRUE 1
void xml_write_init(BOOL n, BOOL t, BOOL r, BOOL d);
int xml_write_struct(FILE *file, FILE *xmlout, mj2_movie_t * movie, unsigned int sampleframe, char* stringDTD);

2798
mj2/MJ2_codec/mj2.c Normal file

File diff suppressed because it is too large Load Diff

201
mj2/MJ2_codec/mj2.h Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 2003-2004, François-Olivier Devaux
* Copyright (c) 2003-2004, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
* 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 <j2k.h>
#include <jp2.h>
#ifndef __MJ2_H
#define __MJ2_H
typedef struct { /* Time To Sample */
int sample_count;
int sample_delta;
} mj2_tts_t;
typedef struct { /* Chunk */
int num_samples;
int sample_descr_idx;
int offset;
} mj2_chunk_t;
typedef struct { /* Sample to chunk */
int first_chunk;
int samples_per_chunk;
int sample_descr_idx;
} mj2_sampletochunk_t;
typedef struct { /* Sample */
unsigned int sample_size;
unsigned int offset;
unsigned int sample_delta;
} mj2_sample_t;
typedef struct { /* URL */
int location[4];
} mj2_url_t;
typedef struct { /* URN */
int name[2];
int location[4];
} mj2_urn_t;
typedef struct { /* Video Track Parameters */
int track_ID;
int track_type;
unsigned int creation_time;
unsigned int modification_time;
int duration;
int timescale;
int layer;
int volume;
int language;
int balance;
int maxPDUsize;
int avgPDUsize;
int maxbitrate;
int avgbitrate;
int slidingavgbitrate;
int graphicsmode;
int opcolor[3];
int num_url;
mj2_url_t *url;
int num_urn;
mj2_urn_t *urn;
int Dim[2];
int w;
int h;
int visual_w;
int visual_h;
int CbCr_subsampling_dx;
int CbCr_subsampling_dy;
// int subsampling_dx;
// int subsampling_dy;
int sample_rate;
int sample_description;
int horizresolution;
int vertresolution;
int compressorname[8];
int depth;
unsigned char fieldcount;
unsigned char fieldorder;
unsigned char or_fieldcount;
unsigned char or_fieldorder;
int num_br;
unsigned int *br;
unsigned char num_jp2x;
unsigned char *jp2xdata;
unsigned char hsub;
unsigned char vsub;
unsigned char hoff;
unsigned char voff;
int trans_matrix[9];
unsigned int num_samples; /* Number of samples */
int transorm;
int handler_type;
int name_size;
unsigned char same_sample_size;
int num_tts;
mj2_tts_t *tts; /* Time to sample */
unsigned int num_chunks;
mj2_chunk_t *chunk;
int num_samplestochunk;
mj2_sampletochunk_t *sampletochunk;
char *name;
jp2_struct_t jp2_struct;
mj2_sample_t *sample; /* Sample parameters */
} mj2_tk_t; /* Track Parameters */
typedef struct { /* Movie */
unsigned int brand;
unsigned int minversion;
int num_cl;
unsigned int *cl;
unsigned int creation_time;
unsigned int modification_time;
int timescale;
unsigned int duration;
int rate;
int num_vtk;
int num_stk;
int num_htk;
int volume;
int trans_matrix[9];
int next_tk_id;
mj2_tk_t *tk; /* Track Parameters */
} mj2_movie_t;
typedef struct {
int length;
int type;
int init_pos;
} mj2_box_t;
void mj2_write_jp();
void mj2_write_ftyp(mj2_movie_t * movie);
/*
* Use this function to initialize a standard movie with standard values
* It has one sample per chunk
*/
int mj2_init_stdmovie(mj2_movie_t * movie);
/* int mj2_encode(mj2_movie_t * movie, j2k_cp_t * cp, char *index);
*
* Encode a MJ2 movie from a yuv file
* movie: an existing mj2_movie structure (to create a standard one, use mj2_init_stdmovie
* cp: coding parameters of j2k images
* index: index file name
*/
int mj2_encode(mj2_movie_t * movie, j2k_cp_t * cp, char *index);
/* int mj2_decode(unsigned char *src, int len, mj2_movie_t * movie,
* j2k_cp_t * cp, char *outfile);
*
* Decode a MJ2 movie to a yuv file
* src: pointer to memory where frames will be stored
* movie: a mj2_movie structure
* cp: coding parameters of j2k images
* outfile: yuv file name
*/
int mj2_decode(unsigned char *src, int len, mj2_movie_t * movie,
j2k_cp_t * cp, char *outfile);
/*
* Free memory used to encode and decode mj2 files
*
*/
void mj2_memory_free(mj2_movie_t * movie);
int mj2_read_struct(FILE *file, mj2_movie_t * movie);
void mj2_write_moov(mj2_movie_t * movie);
#endif

318
mj2/MJ2_codec/mj2_convert.c Normal file
View File

@ -0,0 +1,318 @@
#include <stdio.h>
#include <malloc.h>
#include "mj2.h"
#include <j2k.h>
#include <int.h>
/* ----------------------- */
/* */
/* */
/* Count the number of frames */
/* in a YUV file */
/* */
/* ----------------------- */
int yuv_num_frames(mj2_tk_t * tk, FILE *f)
{
int numimages, frame_size;
long end_of_f;
frame_size = (int) (tk->w * tk->h * (1.0 + (double) 2 / (double) (tk->CbCr_subsampling_dx * tk->CbCr_subsampling_dy))); /* Calculate frame size */
fseek(f, 0, SEEK_END);
end_of_f = ftell(f); /* Calculate file size */
if (end_of_f < frame_size) {
fprintf(stderr,
"YUV does not contains any frame of %d x %d size\n", tk->w,
tk->h);
return 0;
}
numimages = end_of_f / frame_size; /* Calculate number of images */
return numimages;
fclose(f);
}
// -----------------------
//
//
// YUV to IMAGE
//
// -----------------------
int yuvtoimage(FILE *yuvfile, mj2_tk_t * tk, j2k_image_t * img,
int frame_num, int subsampling_dx, int subsampling_dy)
{
int i, j;
int offset;
long end_of_f, position;
FILE *Compo;
offset =
(int) ((double) (frame_num * tk->w * tk->h) *
(1.0 +
1.0 * (double) 2 / (double) (tk->CbCr_subsampling_dx *
tk->CbCr_subsampling_dy)));
fseek(yuvfile, 0, SEEK_END);
end_of_f = ftell(yuvfile);
fseek(yuvfile, sizeof(unsigned char) * offset, SEEK_SET);
position = ftell(yuvfile);
if (position >= end_of_f) {
fprintf(stderr, "Cannot reach frame number %d in yuv file !!\n",
frame_num);
return 0;
}
img->x0 = tk->Dim[0];
img->y0 = tk->Dim[1];
img->x1 = !tk->Dim[0] ? (tk->w - 1) * subsampling_dx + 1 : tk->Dim[0] +
(tk->w - 1) * subsampling_dx + 1;
img->y1 = !tk->Dim[1] ? (tk->h - 1) * subsampling_dy + 1 : tk->Dim[1] +
(tk->h - 1) * subsampling_dy + 1;
img->numcomps = 3;
img->color_space = 3;
img->comps = (j2k_comp_t *) malloc(img->numcomps * sizeof(j2k_comp_t));
for (i = 0; i < img->numcomps; i++) {
img->comps[i].data = (int *) malloc(sizeof(int) * tk->w * tk->h);
img->comps[i].prec = 8;
img->comps[i].bpp = 8;
img->comps[i].sgnd = 0;
if (i == 0) {
img->comps[i].dx = subsampling_dx;
img->comps[i].dy = subsampling_dy;
} else {
img->comps[i].dx = subsampling_dx * tk->CbCr_subsampling_dx;
img->comps[i].dy = subsampling_dy * tk->CbCr_subsampling_dy;
}
}
Compo = fopen("Compo0", "wb");
if (!Compo) {
fprintf(stderr, "Failed to open Compo0 for writing !\n");
}
for (i = 0; i < (tk->w * tk->h / (img->comps[0].dx * img->comps[0].dy))
&& !feof(yuvfile); i++) {
unsigned char y;
j = fread(&y, 1, 1, yuvfile);
fwrite(&y, 1, 1, Compo);
}
fclose(Compo);
Compo = fopen("Compo1", "wb");
if (!Compo) {
fprintf(stderr, "Failed to open Compo1 for writing !\n");
}
for (i = 0; i < (tk->w * tk->h / (img->comps[1].dx * img->comps[1].dy))
&& !feof(yuvfile); i++) {
unsigned char cb;
j = fread(&cb, sizeof(unsigned char), 1, yuvfile);
fwrite(&cb, 1, 1, Compo);
}
fclose(Compo);
Compo = fopen("Compo2", "wb");
if (!Compo) {
fprintf(stderr, "Failed to open Compo2 for writing !\n");
}
for (i = 0; i < (tk->w * tk->h / (img->comps[2].dx * img->comps[2].dy))
&& !feof(yuvfile); i++) {
unsigned char cr;
j = fread(&cr, sizeof(unsigned char), 1, yuvfile);
fwrite(&cr, 1, 1, Compo);
}
fclose(Compo);
return 1;
}
// -----------------------
//
//
// IMAGE to YUV
//
// -----------------------
int imagetoyuv(j2k_image_t * img, j2k_cp_t * cp, char *outfile)
{
FILE *f;
int i;
if (img->numcomps == 3) {
if (img->comps[0].dx != img->comps[1].dx / 2
|| img->comps[1].dx != img->comps[2].dx) {
fprintf(stderr,
"Error with the input image components size: cannot create yuv file)\n");
return 1;
}
} else if (!(img->numcomps == 1)) {
fprintf(stderr,
"Error with the number of image components(must be one or three)\n");
return 1;
}
f = fopen(outfile, "a+b");
if (!f) {
fprintf(stderr, "failed to open %s for writing\n", outfile);
return 1;
}
for (i = 0; i < (img->comps[0].w * img->comps[0].h); i++) {
unsigned char y;
y = img->comps[0].data[i];
fwrite(&y, 1, 1, f);
}
if (img->numcomps == 3) {
for (i = 0; i < (img->comps[1].w * img->comps[1].h); i++) {
unsigned char cb;
cb = img->comps[1].data[i];
fwrite(&cb, 1, 1, f);
}
for (i = 0; i < (img->comps[2].w * img->comps[2].h); i++) {
unsigned char cr;
cr = img->comps[2].data[i];
fwrite(&cr, 1, 1, f);
}
} else if (img->numcomps == 1) {
for (i = 0; i < (img->comps[0].w * img->comps[0].h * 0.25); i++) {
unsigned char cb = 125;
fwrite(&cb, 1, 1, f);
}
for (i = 0; i < (img->comps[0].w * img->comps[0].h * 0.25); i++) {
unsigned char cr = 125;
fwrite(&cr, 1, 1, f);
}
}
fclose(f);
return 0;
}
// -----------------------
//
//
// IMAGE to BMP
//
// -----------------------
int imagetobmp(j2k_image_t * img, j2k_cp_t * cp, char *outfile) {
int w,wr,h,hr,i,pad;
FILE *f;
if (img->numcomps == 3 && img->comps[0].dx == img->comps[1].dx
&& img->comps[1].dx == img->comps[2].dx
&& img->comps[0].dy == img->comps[1].dy
&& img->comps[1].dy == img->comps[2].dy
&& img->comps[0].prec == img->comps[1].prec
&& img->comps[1].prec == img->comps[2].prec) {
/* -->> -->> -->> -->>
24 bits color
<<-- <<-- <<-- <<-- */
f = fopen(outfile, "wb");
if (!f) {
fprintf(stderr, "failed to open %s for writing\n", outfile);
return 1;
}
w = img->comps[0].w;
wr = int_ceildivpow2(img->comps[0].w, img->comps[0].factor);
h = img->comps[0].h;
hr = int_ceildivpow2(img->comps[0].h, img->comps[0].factor);
fprintf(f, "BM");
/* FILE HEADER */
/* ------------- */
fprintf(f, "%c%c%c%c",
(unsigned char) (hr * wr * 3 + 3 * hr * (wr % 2) +
54) & 0xff,
(unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
>> 8) & 0xff,
(unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
>> 16) & 0xff,
(unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
>> 24) & 0xff);
fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(f, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff,
((54) >> 16) & 0xff, ((54) >> 24) & 0xff);
/* INFO HEADER */
/* ------------- */
fprintf(f, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff,
((40) >> 16) & 0xff, ((40) >> 24) & 0xff);
fprintf(f, "%c%c%c%c", (unsigned char) ((wr) & 0xff),
(unsigned char) ((wr) >> 8) & 0xff,
(unsigned char) ((wr) >> 16) & 0xff,
(unsigned char) ((wr) >> 24) & 0xff);
fprintf(f, "%c%c%c%c", (unsigned char) ((hr) & 0xff),
(unsigned char) ((hr) >> 8) & 0xff,
(unsigned char) ((hr) >> 16) & 0xff,
(unsigned char) ((hr) >> 24) & 0xff);
fprintf(f, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
fprintf(f, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff);
fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(f, "%c%c%c%c",
(unsigned char) (3 * hr * wr +
3 * hr * (wr % 2)) & 0xff,
(unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2)) >>
8) & 0xff,
(unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2)) >>
16) & 0xff,
(unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2)) >>
24) & 0xff);
fprintf(f, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
fprintf(f, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
for (i = 0; i < wr * hr; i++) {
unsigned char R, G, B;
/* a modifier */
// R = img->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
R = img->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
// G = img->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
G = img->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
// B = img->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
B = img->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
fprintf(f, "%c%c%c", B, G, R);
if ((i + 1) % wr == 0) {
for (pad = (3 * wr) % 4 ? 4 - (3 * wr) % 4 : 0; pad > 0; pad--) /* ADD */
fprintf(f, "%c", 0);
}
}
fclose(f);
free(img->comps[1].data);
free(img->comps[2].data);
}
return 0;
}

View File

@ -0,0 +1,16 @@
#include "mj2.h"
#ifndef __MJ2_CONVERT_H
#define __MJ2_CONVERT_H
int imagetoyuv(j2k_image_t * img, j2k_cp_t * cp, char *outfile);
int imagetobmp(j2k_image_t * img, j2k_cp_t * cp, char *outfile);
int yuvtoimage(FILE *yuvfile, mj2_tk_t * tk, j2k_image_t * img,
int frame_num, int subsampling_dx, int subsampling_dy);
int yuv_num_frames(mj2_tk_t * tk, FILE *f);
#endif

View File

@ -0,0 +1,130 @@
#include <stdio.h>
#include <malloc.h>
#include <setjmp.h>
#include "mj2.h"
#include "mj2_convert.h"
#include <openjpeg.h>
//MEMORY LEAK
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h> // Must be included first
#include <crtdbg.h>
#endif
//MEM
jmp_buf j2k_error;
int main(int argc, char *argv[]) {
unsigned int tnum, snum;
mj2_movie_t movie;
mj2_tk_t *track;
mj2_sample_t *sample;
unsigned char* frame_codestream;
FILE *file, *outfile;
char outfilename[50];
j2k_image_t img;
j2k_cp_t cp;
int i;
cp.layer=0;
cp.reduce=0;
if (argc != 3) {
printf("Bad syntax: Usage: MJ2_decoder inputfile.mj2 outputfile.yuv\n");
printf("Example: MJ2_decoder foreman.mj2 foreman.yuv\n");
return 1;
}
file = fopen(argv[1], "rb");
if (!file) {
fprintf(stderr, "failed to open %s for reading\n", argv[1]);
return 1;
}
// Checking output file
outfile = fopen(argv[2], "w");
if (!file) {
fprintf(stderr, "failed to open %s for writing\n", argv[2]);
return 1;
}
fclose(outfile);
if (mj2_read_struct(file, &movie)) // Creating the movie structure
return 1;
// Decode first video track
tnum = 0;
while (movie.tk[tnum].track_type != 0)
tnum ++;
track = &movie.tk[tnum];
// Output info on first video tracl
fprintf(stdout,"The first video track contains %d frames.\nWidth: %d, Height: %d \n\n",
track->num_samples, track->w, track->h);
for (snum=0; snum < track->num_samples; snum++)
{
fprintf(stdout,"Frame %d: ",snum+1);
sample = &track->sample[snum];
frame_codestream = (unsigned char*) malloc (sample->sample_size-8); // Skipping JP2C marker
fseek(file,sample->offset+8,SEEK_SET);
fread(frame_codestream,sample->sample_size-8,1, file); // Assuming that jp and ftyp markers size do
if (!j2k_decode(frame_codestream, sample->sample_size-8, &img, &cp)) // Decode J2K to image
return 1;
if (((img.numcomps == 3) && (img.comps[0].dx == img.comps[1].dx / 2)
&& (img.comps[0].dx == img.comps[2].dx / 2 ) && (img.comps[0].dx == 1))
|| (img.numcomps == 1)) {
if (imagetoyuv(&img, &cp, argv[2])) // Convert image to YUV
return 1;
}
else if ((img.numcomps == 3) &&
(img.comps[0].dx == 1) && (img.comps[1].dx == 1)&&
(img.comps[2].dx == 1))// If YUV 4:4:4 input --> to bmp
{
fprintf(stdout,"The frames will be output in a bmp format (output_1.bmp, ...)\n");
sprintf(outfilename,"output_%d.bmp",snum);
if (imagetobmp(&img, &cp, outfilename)) // Convert image to YUV
return 1;
}
else {
fprintf(stdout,"Image component dimensions are unknown. Unable to output image\n");
fprintf(stdout,"The frames will be output in a j2k file (output_1.j2k, ...)\n");
sprintf(outfilename,"output_%d.j2k",snum);
outfile = fopen(outfilename, "wb");
if (!outfile) {
fprintf(stderr, "failed to open %s for writing\n",outfilename);
return 1;
}
fwrite(frame_codestream,sample->sample_size-8,1,outfile);
fclose(outfile);
}
for (i=0; i<img.numcomps; i++)
free(img.comps[i].data);
j2k_dec_release();
free(frame_codestream);
}
fclose(file);
fprintf(stdout, "%d frame(s) correctly extracted\n", snum);
mj2_memory_free(&movie);
//MEMORY LEAK
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif
//MEM
return 0;
}

View File

@ -0,0 +1,305 @@
# Microsoft Developer Studio Project File - Name="mj2_to_frames" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=mj2_to_frames - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "mj2_to_frames.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "mj2_to_frames.mak" CFG="mj2_to_frames - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "mj2_to_frames - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mj2_to_frames - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "mj2_to_frames - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../libopenjpeg" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "mj2_to_frames - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "mj2_to_frames___Win32_Debug0"
# PROP BASE Intermediate_Dir "mj2_to_frames___Win32_Debug0"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "mj2_to_frames___Win32_Debug0"
# PROP Intermediate_Dir "mj2_to_frames___Win32_Debug0"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "mj2_to_frames - Win32 Release"
# Name "mj2_to_frames - Win32 Debug"
# Begin Group "MJ2"
# PROP Default_Filter ""
# Begin Group "MJ2 Header Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\compat\getopt.h
# End Source File
# Begin Source File
SOURCE=.\mj2.h
# End Source File
# Begin Source File
SOURCE=.\mj2_convert.h
# End Source File
# End Group
# Begin Group "MJ2 Source Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\compat\getopt.c
!IF "$(CFG)" == "mj2_to_frames - Win32 Release"
!ELSEIF "$(CFG)" == "mj2_to_frames - Win32 Debug"
# ADD CPP /I "../libopenjpeg"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\mj2.c
!IF "$(CFG)" == "mj2_to_frames - Win32 Release"
!ELSEIF "$(CFG)" == "mj2_to_frames - Win32 Debug"
# ADD CPP /I "../libopenjpeg"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\mj2_convert.c
!IF "$(CFG)" == "mj2_to_frames - Win32 Release"
!ELSEIF "$(CFG)" == "mj2_to_frames - Win32 Debug"
# ADD CPP /I "../libopenjpeg"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\mj2_to_frames.c
!IF "$(CFG)" == "mj2_to_frames - Win32 Release"
!ELSEIF "$(CFG)" == "mj2_to_frames - Win32 Debug"
# ADD CPP /I "../libopenjpeg"
!ENDIF
# End Source File
# End Group
# End Group
# Begin Group "OpenJPEG"
# PROP Default_Filter ""
# Begin Group "OpenJPEG Header Files"
# PROP Default_Filter ".h"
# Begin Source File
SOURCE=..\libopenjpeg\bio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\cio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\dwt.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\fix.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jpt.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mct.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mqc.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\openjpeg.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\pi.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\raw.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t1.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t2.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tcd.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tgt.h
# End Source File
# End Group
# Begin Group "OpenJPEG Source Files"
# PROP Default_Filter ".c"
# Begin Source File
SOURCE=..\libopenjpeg\bio.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\cio.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\dwt.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\fix.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jpt.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mct.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mqc.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\pi.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\raw.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t1.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t2.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tcd.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tgt.c
# End Source File
# End Group
# End Group
# End Target
# End Project

View File

@ -0,0 +1,281 @@
/* mj2_to_metadata.c */
/* Dump MJ2, JP2 metadata (partial so far) to xml file */
/* Contributed to Open JPEG by Glenn Pearson, contract software developer, U.S. National Library of Medicine.
The base code in this file was developed by the author as part of a video archiving
project for the U.S. National Library of Medicine, Bethesda, MD.
It is the policy of NLM (and U.S. government) to not assert copyright.
A non-exclusive copy of this code has been contributed to the Open JPEG project.
Except for copyright, inclusion of the code within Open JPEG for distribution and use
can be bound by the Open JPEG open-source license and disclaimer, expressed elsewhere.
*/
#include <stdio.h>
#include <malloc.h>
#include <setjmp.h>
#include "mj2.h"
#include <openjpeg.h>
//MEMORY LEAK
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h> // Must be included first
#include <crtdbg.h>
#endif
//MEM
#include "mj2_to_metadata.h"
#include <string.h>
#ifndef DONT_HAVE_GETOPT
#include <getopt.h>
#else
#include "compat/getopt.h"
#endif
/* ------------- */
void help_display()
{
/* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
fprintf(stdout," Help for the 'mj2_to_metadata' Program\n");
fprintf(stdout," ======================================\n");
fprintf(stdout,"The -h option displays this information on screen.\n\n");
fprintf(stdout,"mj2_to_metadata generates an XML file from a Motion JPEG 2000 file.\n");
fprintf(stdout,"The generated XML shows the structural, but not (yet) curatorial,\n");
fprintf(stdout,"metadata from the movie header and from the JPEG 2000 image and tile\n");
fprintf(stdout,"headers of a sample frame. Excluded: low-level packed-bits image data.\n\n");
fprintf(stdout,"By Default\n");
fprintf(stdout,"----------\n");
fprintf(stdout,"The metadata includes the jp2 image and tile headers of the first frame.\n");
fprintf(stdout,"\n");
fprintf(stdout,"Metadata values are shown in 'raw' form (e.g., hexidecimal) as stored in the\n");
fprintf(stdout,"file, and, if apt, in a 'derived' form that is more quickly grasped.\n");
fprintf(stdout,"\n");
fprintf(stdout,"Notes explaining the XML are embedded as terse comments. These include\n");
fprintf(stdout," meaning of non-obvious tag abbreviations;\n");
fprintf(stdout," range and precision of valid values;\n");
fprintf(stdout," interpretations of values, such as enumerations; and\n");
fprintf(stdout," current implementation limitations.\n");
fprintf(stdout,"\n");
fprintf(stdout,"The sample-size and chunk-offset tables, each with 1 row per frame, are not reported.\n");
fprintf(stdout,"\n");
fprintf(stdout,"The file is self-contained and no verification (e.g., against a DTD) is requested.\n");
fprintf(stdout,"\n");
fprintf(stdout,"Required Parameters (except with -h)\n");
fprintf(stdout,"------------------------------------\n");
fprintf(stdout,"[Caution: file strings that contain spaces should be wrapped with quotes.]\n");
fprintf(stdout,"-i input.mj2 : where 'input' is any source file name or path.\n");
fprintf(stdout," MJ2 files created with 'frames_to_mj2' are supported so far.\n");
fprintf(stdout," These are silent, single-track, 'MJ2 Simple Profile' videos.\n");
fprintf(stdout,"-o output.xml : where 'output' is any destination file name or path.\n");
fprintf(stdout,"\n");
fprintf(stdout,"Optional Parameters\n");
fprintf(stdout,"-------------------\n");
fprintf(stdout,"-h : Display this help information.\n");
fprintf(stdout,"-n : Suppress all mj2_to_metadata notes.\n");
fprintf(stdout,"-t : Include sample-size and chunk-offset tables.\n");
fprintf(stdout,"-f n : where n > 0. Include jp2 header info for frame n [default=1].\n");
fprintf(stdout,"-f 0 : No jp2 header info.\n");
fprintf(stdout,"-r : Suppress all 'raw' data for which a 'derived' form exists.\n");
fprintf(stdout,"-d : Suppress all 'derived' data.\n");
fprintf(stdout," (If both -r and -d given, -r will be ignored.)\n");
fprintf(stdout,"-v string : Verify against the DTD file located by the string.\n");
fprintf(stdout," Prepend quoted 'string' with either SYSTEM or PUBLIC keyword.\n");
fprintf(stdout," Thus, for the distributed DTD placed in the same directory as\n");
fprintf(stdout," the output file: -v \"SYSTEM mj2_to_metadata.dtd\"\n");
fprintf(stdout," \"PUBLIC\" is used with an access protocol (e.g., http:) + URL.\n");
/* More to come */
fprintf(stdout,"\n");
/* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
}
/* ------------- */
int main(int argc, char *argv[]) {
FILE *file, *xmlout;
/* char xmloutname[50]; */
mj2_movie_t movie;
char* infile = 0;
char* outfile = 0;
char* s, S1, S2, S3;
int len;
unsigned int sampleframe = 1; /* First frame */
char* stringDTD = NULL;
BOOL notes = TRUE;
BOOL sampletables = FALSE;
BOOL raw = TRUE;
BOOL derived = TRUE;
#ifndef NO_PACKETS_DECODING
fprintf(stdout,"WARNING: For best performance, define NO_PACKETS_DECODING in preprocessing.\n");
#endif
while (TRUE) {
/* ':' after letter means it takes an argument */
int c = getopt(argc, argv, "i:o:f:v:hntrd");
/* FUTURE: Reserve 'p' for pruning file (which will probably make -t redundant) */
if (c == -1)
break;
switch (c) {
case 'i': /* IN file */
infile = optarg;
s = optarg;
while (*s) { s++; } /* Run to filename end */
s--;
S3 = *s;
s--;
S2 = *s;
s--;
S1 = *s;
if ((S1 == 'm' && S2 == 'j' && S3 == '2')
|| (S1 == 'M' && S2 == 'J' && S3 == '2')) {
break;
}
fprintf(stderr, "Input file name must have .mj2 extension, not .%c%c%c.\n", S1, S2, S3);
return 1;
/* ----------------------------------------------------- */
case 'o': /* OUT file */
outfile = optarg;
while (*outfile) { outfile++; } /* Run to filename end */
outfile--;
S3 = *outfile;
outfile--;
S2 = *outfile;
outfile--;
S1 = *outfile;
outfile = optarg;
if ((S1 == 'x' && S2 == 'm' && S3 == 'l')
|| (S1 == 'X' && S2 == 'M' && S3 == 'L'))
break;
fprintf(stderr,
"Output file name must have .xml extension, not .%c%c%c\n", S1, S2, S3);
return 1;
/* ----------------------------------------------------- */
case 'f': /* Choose sample frame. 0 = none */
sscanf(optarg, "%u", &sampleframe);
break;
/* ----------------------------------------------------- */
case 'v': /* Verification by DTD. */
stringDTD = optarg;
/* We will not insist upon last 3 chars being "dtd", since non-file
access protocol may be used. */
if(strchr(stringDTD,'"') != NULL) {
fprintf(stderr, "-D's string must not contain any embedded double-quote characters.\n");
return 1;
}
if (strncmp(stringDTD,"PUBLIC ",7) == 0 || strncmp(stringDTD,"SYSTEM ",7) == 0)
break;
fprintf(stderr, "-D's string must start with \"PUBLIC \" or \"SYSTEM \"\n");
return 1;
/* ----------------------------------------------------- */
case 'n': /* Suppress comments */
notes = FALSE;
break;
/* ----------------------------------------------------- */
case 't': /* Show sample size and chunk offset tables */
sampletables = TRUE;
break;
/* ----------------------------------------------------- */
case 'h': /* Display an help description */
help_display();
return 0;
/* ----------------------------------------------------- */
case 'r': /* Suppress raw data */
raw = FALSE;
break;
/* ----------------------------------------------------- */
case 'd': /* Suppress derived data */
derived = FALSE;
break;
/* ----------------------------------------------------- */
default:
return 1;
} /* switch */
} /* while */
if(!raw && !derived)
raw = TRUE; /* At least one of 'raw' and 'derived' must be true */
/* Error messages */
/* -------------- */
if (!infile || !outfile) {
fprintf(stderr,"Correct usage: mj2_to_metadata -i mj2-file -o xml-file (plus options)\n");
return 1;
}
/* was:
if (argc != 3) {
printf("Bad syntax: Usage: MJ2_to_metadata inputfile.mj2 outputfile.xml\n");
printf("Example: MJ2_to_metadata foreman.mj2 foreman.xml\n");
return 1;
}
*/
len = strlen(infile);
if(infile[0] == ' ')
{
infile++; /* There may be a leading blank if user put space after -i */
}
file = fopen(infile, "rb"); /* was: argv[1] */
if (!file) {
fprintf(stderr, "Failed to open %s for reading.\n", infile); /* was: argv[1] */
return 1;
}
len = strlen(outfile);
if(outfile[0] == ' ')
{
outfile++; /* There may be a leading blank if user put space after -o */
}
// Checking output file
xmlout = fopen(outfile, "w"); /* was: argv[2] */
if (!xmlout) {
fprintf(stderr, "Failed to open %s for writing.\n", outfile); /* was: argv[2] */
return 1;
}
// Leave it open
if (mj2_read_struct(file, &movie)) // Creating the movie structure
{
fclose(xmlout);
return 1;
}
xml_write_init(notes, sampletables, raw, derived);
xml_write_struct(file, xmlout, &movie, sampleframe, stringDTD);
fclose(xmlout);
mj2_memory_free(&movie);
//MEMORY LEAK
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif
//MEM
return 0;
}

View File

@ -0,0 +1,276 @@
# Microsoft Developer Studio Project File - Name="mj2_to_metadata" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=mj2_to_metadata - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "mj2_to_metadata.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "mj2_to_metadata.mak" CFG="mj2_to_metadata - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "mj2_to_metadata - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mj2_to_metadata - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "mj2_to_metadata - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../libopenjpeg" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DONT_HAVE_GETOPT" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "mj2_to_metadata - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "mj2_to_metadata___Win32_Debug0"
# PROP BASE Intermediate_Dir "mj2_to_metadata___Win32_Debug0"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "mj2_to_metadata___Win32_Debug0"
# PROP Intermediate_Dir "mj2_to_metadata___Win32_Debug0"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../libopenjpeg" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DONT_HAVE_GETOPT" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "mj2_to_metadata - Win32 Release"
# Name "mj2_to_metadata - Win32 Debug"
# Begin Group "MJ2"
# PROP Default_Filter ""
# Begin Group "MJ2 Header Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\compat\getopt.h
# End Source File
# Begin Source File
SOURCE=.\meta_out.h
# End Source File
# Begin Source File
SOURCE=.\mj2.h
# End Source File
# Begin Source File
SOURCE=.\mj2_convert.h
# End Source File
# End Group
# Begin Group "MJ2 Source Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\compat\getopt.c
# End Source File
# Begin Source File
SOURCE=.\meta_out.c
# End Source File
# Begin Source File
SOURCE=.\mj2.c
# End Source File
# Begin Source File
SOURCE=.\mj2_convert.c
# End Source File
# Begin Source File
SOURCE=.\mj2_to_metadata.c
# End Source File
# End Group
# End Group
# Begin Group "OpenJPEG"
# PROP Default_Filter ""
# Begin Group "OpenJPEG Header Files"
# PROP Default_Filter ".h"
# Begin Source File
SOURCE=..\libopenjpeg\bio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\cio.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\dwt.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\fix.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jpt.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mct.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mqc.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\openjpeg.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\pi.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\raw.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t1.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t2.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tcd.h
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tgt.h
# End Source File
# End Group
# Begin Group "OpenJPEG Source Files"
# PROP Default_Filter ".c"
# Begin Source File
SOURCE=..\libopenjpeg\bio.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\cio.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\dwt.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\fix.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\int.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\j2k.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jp2.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\jpt.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mct.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\mqc.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\pi.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\raw.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t1.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\t2.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tcd.c
# End Source File
# Begin Source File
SOURCE=..\libopenjpeg\tgt.c
# End Source File
# End Group
# End Group
# End Target
# End Project

View File

@ -0,0 +1,425 @@
<!--
Preliminary DTD for Open JPEG "mj2_to_metadata" function.
Last revised: April 20, 2005
Author: Glenn Pearson, at U.S. National Library of Medicine.
See mj2_to_metadata.c regarding copyright, license, disclaimer status.
While the vocabulary of this DTD is based on the relevant portions of the
ISO/IEC JPEG 200 standard, the detailed representation is the author's own.
It is neither an ISO/IEC nor NLM official or consensus representation.
Furthermore, it deviates from a pure representation of the ISO/IEC standard
in these aspects:
- it is incomplete in a number of ways (which to some extent may be
addressed over time);
- it has extensions for "derived" data and "statistics";
- it is more flexible. That is, some elements are marked as optional
not because they are optional in an MJ2 file, but because reporting
of them is optional based on current or projected mj2_to_metadata
command-line flags.
-->
<!ELEMENT MJ2_File (JP2?, FileType?, MovieBox?)>
<!ELEMENT JP2 EMPTY>
<!ATTLIST JP2 BoxType CDATA #FIXED "jP[space][space]">
<!ATTLIST JP2 Signature CDATA #FIXED "0x0d0a870a">
<!ELEMENT FileType (Brand, MinorVersion, CompatibilityList)>
<!ATTLIST FileType BoxType CDATA #FIXED "ftyp">
<!ELEMENT Brand (#PCDATA)> <!-- 4 characters max -->
<!ELEMENT MinorVersion (#PCDATA)> <!-- 4 chararcters max -->
<!ELEMENT CompatibilityList (CompatibleBrand)*>
<!ATTLIST CompatibilityList Count CDATA #REQUIRED> <!-- Count >= 0 -->
<!ELEMENT CompatibleBrand (#PCDATA)> <!-- 4 characters max -->
<!ELEMENT MovieBox (MovieHeader, Statistics?, Track*)>
<!ATTLIST MovieBox BoxType CDATA #FIXED "moov">
<!ELEMENT MovieHeader (CreationTime, ModificationTime, Timescale, Rate, Duration, Volume, TransformationMatrix)>
<!ATTLIST MovieHeader BoxType CDATA #FIXED "mvhd">
<!ELEMENT CreationTime (InSeconds?,AsLocalTime?)>
<!ELEMENT InSeconds (#PCDATA)>
<!ELEMENT AsLocalTime (#PCDATA)>
<!ELEMENT ModificationTime (InSeconds?,AsLocalTime?)>
<!ELEMENT Timescale (#PCDATA)> <!-- Timescale defines time units in one second -->
<!ELEMENT Rate (AsHex | (AsHex, AsDecimal) | AsDecimal)> <!-- Decimal is Approximation; Optional on input. -->
<!ELEMENT AsHex (#PCDATA)>
<!ELEMENT AsDecimal (#PCDATA)>
<!ELEMENT Duration (InTimeUnits | (InTimeUnits, InSeconds) | InSeconds)> <!-- InSeconds Optional on input. -->
<!ELEMENT InTimeUnits (#PCDATA)>
<!ELEMENT Volume (AsHex | (AsHex, AsDecimal) | AsDecimal)> <!-- hex default = 0x0100 -->
<!-- Fixed 8.8 value of audio volume. Full, normal value is 1.0 (0x0100) -->
<!ELEMENT TransformationMatrix (TMa,TMb,TMu,TMc,TMd,TMv,TMx,TMy,TMw)> <!-- for video -->
<!-- 3 x 3 Video Transformation Matrix {a,b,u,c,d,v,x,y,w}. Required: u=0, v=0, w=1 -->
<!-- Maps decompressed point (p,q) to rendered point (ap + cq + x, bp + dq + y) -->
<!-- Stored as Fixed Point Hex: all are 16.16, except u,v,w are 2.30 -->
<!-- Unity = 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 -->
<!ELEMENT TMa (#PCDATA)>
<!ELEMENT TMb (#PCDATA)>
<!ELEMENT TMu (#PCDATA)> <!--Always "0x00000000" -->
<!ELEMENT TMc (#PCDATA)>
<!ELEMENT TMd (#PCDATA)>
<!ELEMENT TMv (#PCDATA)> <!--Always "0x00000000" -->
<!ELEMENT TMx (#PCDATA)>
<!ELEMENT TMy (#PCDATA)>
<!ELEMENT TMw (#PCDATA)> <!--Always "0x40000000" -->
<!ELEMENT Statistics (TracksFound)>
<!ELEMENT TracksFound (Video,Audio,Hint)>
<!ELEMENT Video (#PCDATA)>
<!ELEMENT Audio (#PCDATA)>
<!ELEMENT Hint (#PCDATA)>
<!-- For now, output info on at most one video track -->
<!ELEMENT Track (TrackHeader, TrackReferenceContainer?, EditListContainer?, Media, JP2_Frame?)> <!-- JP2_Frame is mj2_to_metadata extension -->
<!ATTLIST Track BoxType CDATA #FIXED "trak">
<!ATTLIST Track Instance CDATA #REQUIRED>
<!ELEMENT TrackHeader (TrackID, TrackLayer?, Volume?, TransformationMatrix?, Width?, Height?)>
<!ATTLIST TrackHeader BoxType CDATA #FIXED "tkhd">
<!-- Not shown here: CreationTime, ModificationTime, Duration. -->
<!-- These 3 fields are reported under MediaHeader below. When reading these 3, -->
<!-- m2j_to_metadata currently doesn't distinguish between TrackHeader and MediaHeader source. -->
<!-- If both found, value read from MediaHeader is used. -->
<!ELEMENT TrackID (#PCDATA)>
<!ELEMENT TrackLayer (#PCDATA)> <!-- front-to-back ordering of video tracks. 0 = normal, -1 is closer, etc. -->
<!-- "Volume" element described above; here it is for particular audio track. Full, normal (default = 0x0100) -->
<!-- "TransformationMatrix" element described above; matrix here is applied before MovieHeader one. -->
<!ELEMENT Width (AsHex | (AsHex, AsDecimal) | AsDecimal)>
<!ELEMENT Height (AsHex | (AsHex, AsDecimal) | AsDecimal)>
<!-- AsHex, AsDecimal already defined above -->
<!-- Width and Height are for the presentation; frames will be scaled to this -->
<!-- /TrackHeader -->
<!ELEMENT TrackReferenceContainer ANY> <!-- TO DO: TrackReferenceContainer 'tref' just used in hint track -->
<!ELEMENT EditListContainer ANY> <!-- TO DO: EditListContainer 'edts', contains EditList 'elst' with media-time, segment-duration, media-rate -->
<!ELEMENT Media (MediaHeader, HandlerReference,MediaInfoContainer)>
<!ATTLIST Media BoxType CDATA #FIXED "mdia">
<!ELEMENT MediaHeader (CreationTime,ModificationTime,Timescale,Duration,Language)>
<!ATTLIST MediaHeader BoxType CDATA #FIXED "mdhd">
<!-- Elements already defined above: CreationTime, ModificationTime, Timescale, Duration -->
<!ELEMENT Language (#PCDATA)> <!-- 3 chars max. There's an enumeration available -->
<!ELEMENT HandlerReference (HandlerType)>
<!ATTLIST HandlerReference BoxType CDATA #FIXED "hdlr">
<!ELEMENT HandlerType (#PCDATA)>
<!ATTLIST HandlerType Code ( vide | soun | hint ) "vide">
<!-- make the media headers multiple? -->
<!ELEMENT MediaInfoContainer ((VideoMediaHeader | SoundMediaHeader | HintMediaHeader), DataInfo, SampleTable)>
<!ATTLIST MediaInfoContainer BoxType CDATA #FIXED "minf">
<!ELEMENT VideoMediaHeader (GraphicsMode, Opcolor)>
<!ATTLIST VideoMediaHeader BoxType CDATA #FIXED "vmhd">
<!ELEMENT GraphicsMode (#PCDATA)>
<!-- Enumerated values of graphics mode: -->
<!-- 0x00 = copy (over existing image); -->
<!-- 0x24 = transparent; 'blue-screen' this image using opcolor; -->
<!-- 0x100 = alpha; alpha-blend this image -->
<!-- 0x101 = whitealpha; alpha-blend this image, which has been blended with white; -->
<!-- 0x102 = blackalpha; alpha-blend this image, which has been blended with black. -->
<!ELEMENT Opcolor (Red,Green,Blue)>
<!ELEMENT Red (#PCDATA)>
<!ELEMENT Green (#PCDATA)>
<!ELEMENT Blue (#PCDATA)>
<!ELEMENT SoundMediaHeader (Balance)>
<!ATTLIST SoundMediaHeader BoxType CDATA #FIXED "smhd">
<!ELEMENT Balance (#PCDATA)>
<!-- Fixed Point 8.8, fixes mono track in stereo space. -->
<!-- 0.0 = center, -1.0 = full left, 1.0 = full right -->
<!ELEMENT HintMediaHeader (MaxPDU_Size, AvgPDU_Size, MaxBitRate, AvgBitRate, SlidingAvgBitRate)>
<!ATTLIST HintMediaHeader BoxType CDATA #FIXED "hmhd">
<!ELEMENT MaxPDU_Size (#PCDATA)>
<!-- Size in bytes of largest PDU in this hint stream. -->
<!ELEMENT AvgPDU_Size (#PCDATA)>
<!-- Average size in bytes of a PDU over the entire presentation. -->
<!ELEMENT MaxBitRate (#PCDATA)>
<!-- Maximum rate in bits per second over any window of 1 second. -->
<!ELEMENT AvgBitRate (#PCDATA)>
<!-- Averate rate in bits per second over the entire presentation. -->
<!ELEMENT SlidingAvgBit (#PCDATA)>
<!-- Maximum rate in bits per second over any window of one minute. -->
<!ELEMENT DataInfo (DataReference)>
<!ATTLIST DataInfo BoxType CDATA #FIXED "dinf">
<!ELEMENT DataReference (DataEntryUrlBox | DataEntryUrnBox )*>
<!ATTLIST DataReference BoxType CDATA #FIXED "dref">
<!ATTLIST DataReference URL_Count CDATA #REQUIRED>
<!ATTLIST DataReference URN_Count CDATA #REQUIRED> <!-- table w. flags, URLs, URNs -->
<!-- // Data structure does not distinguish between single URL, single URN, or DREF table or URLs & URNs.
// We could infer those, but for now just present everything as a DREF table.
-->
<!-- No entries here mean that file is self-contained, as required by Simple Profile. -->
<!ELEMENT DataEntryUrlBox (Location)>
<!ATTLIST DataEntryUrlBox BoxType CDATA #FIXED "url[space]"> <!-- table w. flags, URLs, URNs -->
<!-- Only the first 16 bytes of URL location are recorded in mj2_to_metadata data structure. -->
<!ELEMENT DataEntryUrnBox (Name, Location?)>
<!ATTLIST DataEntryUrnBox BoxType CDATA #FIXED "urn[space]\">
<!-- Only the first 16 bytes each of URN name and optional location are recorded in mj2_to_metadata data structure. -->
<!ELEMENT SampleTable (VisualSampleEntry,TimeToSample,SampleToChunk,SampleSize,ChunkOffset)> <!-- structure doesn't do non-visual sample entry yet -->
<!ATTLIST SampleTable BoxType CDATA #FIXED "stbl"> <!-- to add: entry count -->
<!-- Next are instances of generic SampleDescription BoxType=\"stsd\" -->
<!-- There could be multiple instances of this, but "entry_count" is just a local at read-time.
And it's used wrong, too, as count of just visual type, when it's really all 3 types.
This is referred to as "smj2" within mj2.c -->
<!ELEMENT VisualSampleEntry (WidthAsInteger, HeightAsInteger, HorizontalRes, VerticalRes, CompressorName, Depth, JP2Header?, FieldCoding?, MJP2_Profile?, MJP2_Prefix?, MJP2_SubSampling?, MJP2_OriginalFormat?)>
<!ATTLIST VisualSampleEntry BoxType CDATA #FIXED "mjp2">
<!-- If multiple instances of this, only first is shown here. -->
<!ELEMENT WidthAsInteger (#PCDATA)>
<!ELEMENT HeightAsInteger (#PCDATA)>
<!ELEMENT HorizontalRes (AsHex | (AsHex, AsDecimal) | AsDecimal)>
<!ELEMENT VerticalRes (AsHex | (AsHex, AsDecimal) | AsDecimal)>
<!-- Typical value for both resolution is 72 (0x00480000) -->
<!ELEMENT CompressorName (#PCDATA)>
<!-- Compressor name for debugging. Standard restricts max length to 31 bytes. -->
<!-- Usually blank or \"Motion JPEG2000\" -->
<!ELEMENT Depth (#PCDATA)>
<!-- Depth is: -->
<!-- 0x20: alpha channels present (color or grayscale) -->
<!-- 0x28: grayscale without alpha -->
<!-- 0x18: color without alpha -->
<!-- TODO somewhere: tk->jp2_struct.numcomps -->
<!ELEMENT JP2Header (ImageHeader, ColourSpecification)>
<!ATTLIST JP2Header BoxType CDATA #FIXED "jp2h">
<!ELEMENT ImageHeader (HEIGHT, WIDTH, NC, BPC, C, UnkC, IPR)>
<!ATTLIST ImageHeader BoxType CDATA #FIXED "ihdr">
<!ELEMENT HEIGHT (#PCDATA)> <!-- If 2 fields/frame, total deinterlaced height -->
<!ELEMENT WIDTH (#PCDATA)>
<!ELEMENT NC (#PCDATA)> <!-- number of components -->
<!ELEMENT BPC (AsHex | (AsHex,BitsPerPixel,Signed) | (BitsPerPixel,Signed))>
<!ELEMENT BitsPerPixel (#PCDATA)>
<!ELEMENT Signed (#PCDATA)>
<!ELEMENT C (#PCDATA)> <!-- Compression type. Only "7" defined -->
<!ELEMENT UnkC (#PCDATA)> <!-- Colourspace Unknown. 1 = unknown, 0 = known -->
<!ELEMENT IPR (#PCDATA)> <!-- 1 = frame has Intellectual Prop. box; otherwise 0 -->
<!ELEMENT ColourSpecification (METH, PREC, APPROX, EnumCS)>
<!ATTLIST ColourSpecification BoxType CDATA #FIXED "colr">
<!ELEMENT METH (#PCDATA)> <!-- 1 = EnumCS field; 2 = PROFILE field (not yet generated) -->
<!ELEMENT PREC (#PCDATA)> <!-- precedence must be 0 so far -->
<!ELEMENT APPROX (#PCDATA)> <!-- colourspace approximation must be 0 so far -->
<!ELEMENT EnumCS (#PCDATA)> <!-- Valid enumerated MJ2 colourspaces: 16 (sRGB), 17 (grey sRGB), 18 (YCC) -->
<!-- Following subboxes are optional -->
<!ELEMENT FieldCoding (FieldCount, FieldOrder)>
<!ATTLIST FieldCoding BoxType CDATA #FIXED "fiel">
<!ELEMENT FieldCount (#PCDATA)>
<!-- Must be either 1 or 2 -->
<!ELEMENT FieldOrder (#PCDATA)>
<!-- When FieldCount=2, FieldOrder means: -->
<!-- 0: Field coding unknown -->
<!-- 1: Field with topmost line is stored first in sample; fields are in temporal order -->
<!-- 6: Field with topmost line is stored second in sample; fields are in temporal order -->
<!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->
<!-- Current implementation doesn't retain whether box was actually present. -->
<!ELEMENT MJP2_Profile (CompatibleBrand*)>
<!ATTLIST MJP2_Profile BoxType CDATA #FIXED "jp2p">
<!ATTLIST MJP2_Profile Count CDATA #REQUIRED>
<!ELEMENT MJP2_Prefix (Data*)>
<!ATTLIST MJP2_Prefix BoxType CDATA #FIXED "jp2x">
<!ATTLIST MJP2_Prefix Count CDATA #REQUIRED>
<!-- We'll probably need better formatting than this -->
<!ELEMENT Data (#PCDATA)> <!-- Multiple. Each entry is single byte -->
<!ELEMENT MJP2_SubSampling (HorizontalSub, VerticalSub, HorizontalOffset, VerticalOffset)>
<!ATTLIST MJP2_SubSampling BoxType CDATA #FIXED "jsub">
<!-- These values are all 1 byte -->
<!-- Typical subsample value is 2 for 4:2:0 -->
<!ELEMENT HorizontalSub (#PCDATA)>
<!ELEMENT VerticalSub (#PCDATA)>
<!ELEMENT HorizontalOffset (#PCDATA)>
<!ELEMENT VerticalOffset (#PCDATA)>
<!ELEMENT MJP2_OriginalFormat (OriginalFieldCount, OriginalFieldOrder)>
<!ATTLIST MJP2_OriginalFormat BoxType CDATA #FIXED "orfo"> <!-- Part III Appx. 2 -->
<!ELEMENT OriginalFieldCount (#PCDATA)>
<!-- In original material before encoding. Must be either 1 or 2 -->
<!ELEMENT OriginalFieldOrder (#PCDATA)>
<!-- When FieldCount=2, FieldOrder means: -->
<!-- 0: Field coding unknown -->
<!-- 11: Topmost line came from the earlier field; -->
<!-- 16: Topmost line came form the later field. -->
<!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->
<!-- Current implementation doesn't retain whether box was actually present. -->
<!-- mj2_to_metadata's data structure doesn't record Audio and Hint sample data currently. -->
<!-- Within SampleTable: -->
<!ELEMENT TimeToSample (SampleStatistics, SampleEntries)>
<!ATTLIST TimeToSample BoxType CDATA #FIXED "stts">
<!ELEMENT SampleStatistics (TotalSamples)> <!-- Not part of standard -->
<!ELEMENT TotalSamples (#PCDATA)>
<!-- For video, gives the total frames in the track, by summing all entries in the Sample Table -->
<!ELEMENT SampleEntries (Table*)>
<!ATTLIST SampleEntries EntryCount CDATA #REQUIRED>
<!ELEMENT Table EMPTY> <!-- Multiple. Attributes have values -->
<!ATTLIST Table Entry CDATA #REQUIRED>
<!ATTLIST Table SampleCount CDATA #REQUIRED>
<!ATTLIST Table SampleDelta CDATA #REQUIRED>
<!-- Within SampleTable: -->
<!ELEMENT SampleToChunk (FirstChunk,SamplesPerChunk,SampleDescrIndex)>
<!ATTLIST SampleToChunk BoxType CDATA #FIXED "stsc">
<!ATTLIST SampleToChunk Count CDATA #REQUIRED>
<!ELEMENT FirstChunk (#PCDATA)>
<!ELEMENT SamplesPerChunk (#PCDATA)>
<!ELEMENT SampleDescrIndex (#PCDATA)>
<!ELEMENT SampleSize (Sample_Size,Sample_Count,EntrySize*)>
<!ATTLIST SampleSize BoxType CDATA #FIXED "stsz">
<!ELEMENT Sample_Size (#PCDATA)>
<!ELEMENT Sample_Count (#PCDATA)>
<!ELEMENT EntrySize (#PCDATA)> <!-- appears multiply, but only with mj2_to_metadata option -t -->
<!ATTLIST EntrySize Num CDATA #REQUIRED>
<!ELEMENT ChunkOffset (EntryCount, Chunk_Offset*)>
<!ATTLIST ChunkOffset BoxType CDATA #FIXED "stco">
<!ELEMENT EntryCount (#PCDATA)>
<!ELEMENT Chunk_Offset (#PCDATA)> <!-- appears multiply, but only with mj2_to_metadata option -t -->
<!ATTLIST Chunk_Offset Num CDATA #REQUIRED>
<!-- </SampleTable> </MediaInfoContainer> </Media> -->
<!-- TO DO: optional UserData 'udat', can contain multiple Copyright 'cprt' -->
<!-- Optional, and only for Visual Track: given individual frame -->
<!ELEMENT JP2_Frame (MainHeader, TilePartHeaders)>
<!ATTLIST JP2_Frame Num CDATA #REQUIRED>
<!ELEMENT MainHeader (StartOfCodestream,ImageAndFileSize,CodingStyleDefault,QuantizationDefault,QuantizationComponent*,RegionOfInterest?,ProgressionOrderChange*)>
<!ELEMENT StartOfCodestream EMPTY>
<!ATTLIST StartOfCodestream Marker CDATA #FIXED "SOC">
<!ELEMENT ImageAndFileSize (Xsiz,Ysiz,XOsiz,YOsiz,XTsiz,YTsiz,XTOsiz,YTOsiz,Csiz,Component+)>
<!ATTLIST ImageAndFileSize Marker CDATA #FIXED "SIZ">
<!ELEMENT Xsiz (#PCDATA)>
<!ELEMENT Ysiz (#PCDATA)> <!-- Xsiz, Ysiz is the size of the reference grid. -->
<!ELEMENT XOsiz (#PCDATA)>
<!ELEMENT YOsiz (#PCDATA)> <!-- XOsiz, YOsiz are offsets from grid origin to image origin. -->
<!ELEMENT XTsiz (#PCDATA)>
<!ELEMENT YTsiz (#PCDATA)> <!-- XTsiz, YTsiz is the size of one tile with respect to the grid. -->
<!ELEMENT XTOsiz (#PCDATA)>
<!ELEMENT YTOsiz (#PCDATA)> <!-- XTOsiz, YTOsiz are offsets from grid origin to first tile origin. -->
<!ELEMENT Csiz (#PCDATA)> <!-- Csiz is the number of components in the image. -->
<!-- For image components next -->
<!ELEMENT Component (Ssiz,XRsiz,YRsiz,WidthOfData,HeightOfData)>
<!ATTLIST Component Num CDATA #REQUIRED>
<!ELEMENT Ssiz (AsHex | (AsHex,Signed,PrecisionInBits) | (Signed,PrecisionInBits))>
<!-- Signed already defined -->
<!ELEMENT PrecisionInBits (#PCDATA)> <!-- Bits per pixel (bpp) or pixel depth. -->
<!ELEMENT XRsiz (#PCDATA)>
<!ELEMENT YRsiz (#PCDATA)> <!-- XRsiz, YRsiz denote pixel-sample-spacing on the grid, per Part I Annex B. -->
<!ELEMENT WidthOfData (#PCDATA)>
<!ELEMENT HeightOfData (#PCDATA)> <!-- WidthOfData and HeightOfData are calculated values, e.g.: w = roundup((Xsiz - XOsiz)/ XRsiz) -->
<!-- -->
<!ELEMENT CodingStyleDefault (Scod,SGcod,SPcod)>
<!ATTLIST CodingStyleDefault Marker CDATA #FIXED "COD">
<!ELEMENT Scod (#PCDATA)>
<!-- For Scod, specific bits mean (where bit 0 is lowest or rightmost): -->
<!-- bit 0: Defines entropy coder precincts -->
<!-- 0 = (PPx=15, PPy=15); 1 = precincts defined below. -->
<!-- bit 1: 1 = SOP marker may be used; 0 = not. -->
<!-- bit 2: 1 = EPH marker may be used; 0 = not. -->
<!ELEMENT SGcod (ProgressionOrder,NumberOfLayers,MultipleComponentTransformation)>
<!ELEMENT ProgressionOrder (#PCDATA)>
<!-- Defined Progression Order Values are: -->
<!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->
<!-- where L = "layer", R = "resolution level", C = "component", P = "position". -->
<!ELEMENT NumberOfLayers (#PCDATA)>
<!ELEMENT MultipleComponentTransformation (#PCDATA)>
<!-- For MCT, 0 = none, 1 = transform first 3 components for efficiency, per Part I Annex G -->
<!ELEMENT SPcod (NumberOfDecompositionLevels,CodeblockWidth,CodeblockHeight,CodeblockStyle,Transformation)>
<!ELEMENT NumberOfDecompositionLevels (#PCDATA)>
<!ELEMENT CodeblockWidth (#PCDATA)> <!-- CBW and CBH are non-negative, and summed cannot exceed 8 -->
<!ELEMENT CodeblockHeight (#PCDATA)> <!-- Codeblock dimension is 2^(value + 2) -->
<!ELEMENT CodeblockStyle (#PCDATA)>
<!-- For CodeblockStyle, bits mean (with value 1=feature on, 0=off): -->
<!-- bit 0: Selective arithmetic coding bypass. -->
<!-- bit 1: Reset context probabilities on coding pass boundaries. -->
<!-- bit 2: Termination on each coding pass. -->
<!-- bit 3: Vertically causal context. -->
<!-- bit 4: Predictable termination. -->
<!-- bit 5: Segmentation symbols are used. -->
<!ELEMENT Transformation (#PCDATA)> <!-- For Transformation, 0="9-7 irreversible filter", 1="5-3 reversible filter" -->
<!-- mj2_to_metadata implementation always reports component[0] as using default COD, -->
<!-- and any other component, with main-header style values different from [0], as COC. -->
<!ELEMENT QuantizationDefault (Sqcd,SPqcd)>
<!ATTLIST QuantizationDefault Marker CDATA #FIXED "QCD">
<!ELEMENT Sqcd (AsHex | (AsHex,QuantizationStyle,NumberOfGuardBits) | (QuantizationStyle,NumberOfGuardBits))>
<!ELEMENT QuantizationStyle (#PCDATA)> <!-- Default quantization style for all components. -->
<!-- Quantization style (in Sqcd's low 5 bits) may be: -->
<!-- 0 = No quantization. SPqcd size = 8 bits-->
<!-- 1 = Scalar derived (values signaled for N(L)LL subband only). Use Eq. E.5. SPqcd size = 16. -->
<!-- 2 = Scalar expounded (values signaled for each subband). SPqcd size = 16. -->
<!ELEMENT NumberOfGuardBits (#PCDATA)> <!-- 0-7 guard bits allowed (stored in Sqcd's high 3 bits) -->
<!ELEMENT SPqcd (ReversibleStepSizeValue | QuantizationStepSizeValues )> <!-- TO DO: Irreversible choices -->
<!ELEMENT ReversibleStepSizeValue (DynamicRangeExponent+)>
<!-- Current mj2_to_metadata implementation dumps entire internal table, -->
<!-- until an exponent with zero value is reached. -->
<!-- Exponent epsilon(b) of reversible dynamic range. -->
<!-- Hex value is as stored, in high-order 5 bits. -->
<!ELEMENT DynamicRangeExponent (AsHex | (AsHex, AsDecimal) | AsDecimal)>
<!ATTLIST DynamicRangeExponent Subband CDATA #REQUIRED>
<!ELEMENT QuantizationStepSizeValues (QuantizationValues+, CalculatedExponent*)> <!-- Calculated exponents iff only subband 0 reported -->
<!ELEMENT QuantizationValues (AsHex | (AsHex,Exponent,Mantissa) | (Exponent,Mantissa))>
<!ATTLIST QuantizationValues Subband CDATA #REQUIRED>
<!ELEMENT Exponent (#PCDATA)>
<!ELEMENT Mantissa (#PCDATA)>
<!ELEMENT CalculatedExponent (#PCDATA)>
<!ATTLIST CalculatedExponent Subband CDATA #REQUIRED>
<!-- /QuantizationDefault -->
<!-- mj2_to_metadata implementation always reports component[0] as using default QCD, -->
<!-- and any other component, with main-header quantization values different from [0], as QCC. -->
<!ELEMENT QuantizationComponent (Sqcc,SPqcc)>
<!ATTLIST QuantizationComponent Marker CDATA #FIXED "QCC">
<!ATTLIST QuantizationComponent Component CDATA #REQUIRED>
<!ELEMENT Sqcc (AsHex | (AsHex,QuantizationStyle,NumberOfGuardBits) | (QuantizationStyle,NumberOfGuardBits))>
<!ELEMENT SPqcc (ReversibleStepSizeValue | QuantizationStepSizeValues )> <!-- TO DO: Irreversible choices -->
<!-- /QuantizationComponent -->
<!-- Don't know if MJ2 files can have regions of interest. Assume yes -->
<!ELEMENT RegionOfInterest (Srgn,Crgn,Sprgn)> <!-- Optional in main header, at most 1 per component -->
<!ATTLIST RegionOfInterest Marker CDATA #FIXED "RGN">
<!ELEMENT Srgn (#PCDATA)> <!-- ROI style. Only style=0 defined: Implicit ROI (max. shift) -->
<!ELEMENT Crgn (#PCDATA)> <!-- Zero-based component number. -->
<!ELEMENT SPrgn (#PCDATA)> <!-- Implicit ROI shift, i.e., binary shifting of ROI coefficients above background. -->
<!-- </RegionOfInterest> -->
<!ELEMENT ProgressionOrderChange (Progression+)> <!-- Optional in main header, at most 1 per component (but impl allows more?) -->
<!ATTLIST ProgressionOrderChange Marker CDATA #REQUIRED>
<!ELEMENT Progression (RSpoc,CSpoc,LYEpoc,REpoc,CEpoc,Ppoc)>
<!ATTLIST Progression Num CDATA #REQUIRED>
<!ELEMENT RSpoc (#PCDATA)> <!-- Resolution level index (inclusive) for progression start. Range: 0 to 33 -->
<!ELEMENT CSpoc (#PCDATA)> <!-- Component index (inclusive) for progression start. -->
<!ELEMENT LYEpoc (#PCDATA)> <!-- Layer index (exclusive) for progression end. -->
<!ELEMENT REpoc (#PCDATA)> <!-- Resolution level index (exclusive) for progression end. Range: RSpoc to 33 -->
<!ELEMENT CEpoc (#PCDATA)> <!-- Component index (exclusive) for progression end. Minimum: CSpoc -->
<!ELEMENT Ppoc (#PCDATA)> <!-- Defined Progression Order Values are: -->
<!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->
<!-- where L = "layer", R = "resolution level", C = "component", P = "position". -->
<!-- </Progression>, </ProgressionOrderChange -->
<!-- /MainHeader -->
<!ELEMENT TilePartHeaders (TilePartHeader+)>
<!ATTLIST TilePartHeaders Count CDATA #REQUIRED>
<!ELEMENT TilePartHeader (StartOfTilePart,CodingStyleDefault,QuantizationDefault,QuantizationComponent*,RegionOfInterest?,ProgressionOrderChange*,StartOfData)>
<!ATTLIST TilePartHeader Num CDATA #REQUIRED>
<!ATTLIST TilePartHeader ID CDATA #REQUIRED>
<!ELEMENT StartOfTilePart EMPTY>
<!ATTLIST StartOfTilePart Marker CDATA #FIXED "SOT">
<!-- CodingStyleDefault, QuantizationDefault, QuantizationComponent already defined -->
<!-- mj2_to_metadata implementation always reports component[0] as using default QCD, -->
<!-- and any other component, with tile-part-header quantization values different from [0], as QCC. -->
<!ELEMENT StartOfData EMPTY> <!-- always empty for now -->
<!ATTLIST StartOfData Marker CDATA #FIXED "SOD">
<!-- Tile-part bitstream, not shown, follows tile-part header and SOD marker. -->
<!-- /TilePartHeader, /TilePartHeaders, /JP2_Frame -->
<!-- </Track> -->
<!-- to come:
<MovieExtends mvek> // possibly not in Simple Profile
<UserDataBox udat> contains <CopyrightBox cprt>
-->
<!-- /MovieBox -->
<!-- To come:
<mdat>
<moof> // probably not in Simple Profile
<free>
<skip>
-->
<!-- </MJ2_File> -->

View File

@ -0,0 +1,9 @@
/* mj2_to_metadata.h */
/* Dump MJ2, JP2 metadata (partial so far) to xml file */
/* Contributed to Open JPEG by Glenn Pearson, U.S. National Library of Medicine */
#define BOOL int
#define FALSE 0
#define TRUE 1
#include "meta_out.h"

View File

@ -0,0 +1,324 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="mj2_to_metadata"
ProjectGUID="{338C1241-ACB9-469F-98DF-3B9D79ADD1A0}"
SccProjectName=""
SccLocalPath="">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="../libopenjpeg"
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE,DONT_HAVE_GETOPT,NO_PACKETS_DECODING"
StringPooling="TRUE"
RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Release/mj2_to_metadata.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="odbc32.lib odbccp32.lib"
OutputFile=".\Release/mj2_to_metadata.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
ProgramDatabaseFile=".\Release/mj2_to_metadata.pdb"
SubSystem="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/mj2_to_metadata.tlb"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\mj2_to_metadata___Win32_Debug0"
IntermediateDirectory=".\mj2_to_metadata___Win32_Debug0"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../libopenjpeg"
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,DONT_HAVE_GETOPT,NO_PACKETS_DECODING"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.pch"
AssemblerListingLocation=".\mj2_to_metadata___Win32_Debug0/"
ObjectFile=".\mj2_to_metadata___Win32_Debug0/"
ProgramDataBaseFileName=".\mj2_to_metadata___Win32_Debug0/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="odbc32.lib odbccp32.lib"
OutputFile=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.exe"
LinkIncremental="2"
SuppressStartupBanner="TRUE"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.pdb"
SubSystem="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.tlb"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"
AdditionalIncludeDirectories=""
ResourceOutputFileName=""/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="MJ2"
Filter="">
<Filter
Name="MJ2 Header Files"
Filter="">
<File
RelativePath=".\compat\getopt.h">
</File>
<File
RelativePath="meta_out.h">
</File>
<File
RelativePath=".\mj2.h">
</File>
<File
RelativePath=".\mj2_convert.h">
</File>
<File
RelativePath="mj2_to_metadata.h">
</File>
</Filter>
<Filter
Name="MJ2 Source Files"
Filter="">
<File
RelativePath=".\compat\getopt.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../libopenjpeg;$(NoInherit)"
CompileAs="0"/>
</FileConfiguration>
</File>
<File
RelativePath="meta_out.c">
</File>
<File
RelativePath=".\mj2.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../libopenjpeg;$(NoInherit)"
CompileAs="0"/>
</FileConfiguration>
</File>
<File
RelativePath=".\mj2_convert.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../libopenjpeg;$(NoInherit)"
CompileAs="0"/>
</FileConfiguration>
</File>
<File
RelativePath=".\mj2_to_metadata.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../libopenjpeg;$(NoInherit)"
CompileAs="0"/>
</FileConfiguration>
</File>
</Filter>
</Filter>
<Filter
Name="OpenJPEG"
Filter="">
<Filter
Name="OpenJPEG Header Files"
Filter=".h">
<File
RelativePath="..\libopenjpeg\bio.h">
</File>
<File
RelativePath="..\libopenjpeg\cio.h">
</File>
<File
RelativePath="..\libopenjpeg\dwt.h">
</File>
<File
RelativePath="..\libopenjpeg\fix.h">
</File>
<File
RelativePath="..\libopenjpeg\int.h">
</File>
<File
RelativePath="..\libopenjpeg\j2k.h">
</File>
<File
RelativePath="..\libopenjpeg\jp2.h">
</File>
<File
RelativePath="..\libopenjpeg\jpt.h">
</File>
<File
RelativePath="..\libopenjpeg\mct.h">
</File>
<File
RelativePath="..\libopenjpeg\mqc.h">
</File>
<File
RelativePath="..\libopenjpeg\openjpeg.h">
</File>
<File
RelativePath="..\libopenjpeg\pi.h">
</File>
<File
RelativePath="..\libopenjpeg\raw.h">
</File>
<File
RelativePath="..\libopenjpeg\t1.h">
</File>
<File
RelativePath="..\libopenjpeg\t2.h">
</File>
<File
RelativePath="..\libopenjpeg\tcd.h">
</File>
<File
RelativePath="..\libopenjpeg\tgt.h">
</File>
</Filter>
<Filter
Name="OpenJPEG Source Files"
Filter=".c">
<File
RelativePath="..\libopenjpeg\bio.c">
</File>
<File
RelativePath="..\libopenjpeg\cio.c">
</File>
<File
RelativePath="..\libopenjpeg\dwt.c">
</File>
<File
RelativePath="..\libopenjpeg\fix.c">
</File>
<File
RelativePath="..\libopenjpeg\int.c">
</File>
<File
RelativePath="..\libopenjpeg\j2k.c">
</File>
<File
RelativePath="..\libopenjpeg\jp2.c">
</File>
<File
RelativePath="..\libopenjpeg\jpt.c">
</File>
<File
RelativePath="..\libopenjpeg\mct.c">
</File>
<File
RelativePath="..\libopenjpeg\mqc.c">
</File>
<File
RelativePath="..\libopenjpeg\pi.c">
</File>
<File
RelativePath="..\libopenjpeg\raw.c">
</File>
<File
RelativePath="..\libopenjpeg\t1.c">
</File>
<File
RelativePath="..\libopenjpeg\t2.c">
</File>
<File
RelativePath="..\libopenjpeg\tcd.c">
</File>
<File
RelativePath="..\libopenjpeg\tgt.c">
</File>
</Filter>
</Filter>
<File
RelativePath="resource.h">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

Binary file not shown.

3
mj2/MJ2_codec/readme.txt Normal file
View File

@ -0,0 +1,3 @@
Attention : the motion jpeg 2000 files currently only work with OpenJPEG v0.97 that you can find here :
http://www.openjpeg.org/openjpeg_v097.tar.gz

View File

@ -0,0 +1,287 @@
#include <stdio.h>
#include <malloc.h>
#include <setjmp.h>
#include <string.h>
#include "mj2.h"
#include <cio.h>
#include <j2k.h>
#include <int.h>
#define MJ2_MJ2 0x6d6a7032
#define MJ2_MJ2S 0x6d6a3273
#define JP2_JP2C 0x6a703263
#define MJ2_MDAT 0x6d646174
//MEMORY LEAK
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h> // Must be included first
#include <crtdbg.h>
#endif
//MEM
jmp_buf j2k_error;
void j2k_read_siz_marker(FILE *file, j2k_image_t *j2k_img)
{
int len,i;
char buf, buf2[2];
char *siz_buffer;
fseek(file, 0, SEEK_SET);
do {
fread(&buf,1,1, file);
if (buf==(char)0xff)
fread(&buf,1,1, file);
}
while (!(buf==(char)0x51));
fread(buf2,2,1,file); /* Lsiz */
len = ((buf2[0])<<8) + buf2[1];
siz_buffer = (char*) malloc(len * sizeof(char));
fread(siz_buffer,len, 1, file);
cio_init(siz_buffer,len);
cio_read(2); /* Rsiz (capabilities) */
j2k_img->x1 = cio_read(4); /* Xsiz */
j2k_img->y1 = cio_read(4); /* Ysiz */
j2k_img->x0 = cio_read(4); /* X0siz */
j2k_img->y0 = cio_read(4); /* Y0siz */
cio_skip(16); /* XTsiz, YTsiz, XT0siz, YT0siz */
j2k_img->numcomps = cio_read(2); /* Csiz */
j2k_img->comps =
(j2k_comp_t *) malloc(j2k_img->numcomps * sizeof(j2k_comp_t));
for (i = 0; i < j2k_img->numcomps; i++) {
int tmp;
tmp = cio_read(1); /* Ssiz_i */
j2k_img->comps[i].prec = (tmp & 0x7f) + 1;
j2k_img->comps[i].sgnd = tmp >> 7;
j2k_img->comps[i].dx = cio_read(1); /* XRsiz_i */
j2k_img->comps[i].dy = cio_read(1); /* YRsiz_i */
j2k_img->comps[i].resno_decoded = 0; /* number of resolution decoded */
j2k_img->comps[i].factor = 0; /* reducing factor by component */
}
free(siz_buffer);
fseek(file, 0, SEEK_SET);
}
void setparams(mj2_movie_t *movie, j2k_image_t *img) {
int i, depth_0, depth, sign;
movie->tk[0].sample_rate = 25;
movie->tk[0].w = int_ceildiv(img->x1 - img->x0, img->comps[0].dx);
movie->tk[0].h = int_ceildiv(img->y1 - img->y0, img->comps[0].dy);
mj2_init_stdmovie(movie);
movie->tk[0].depth = img->comps[0].prec;
if (img->numcomps==3) {
if ((img->comps[0].dx == 1) && (img->comps[1].dx == 1) && (img->comps[1].dx == 1))
movie->tk[0].CbCr_subsampling_dx = 1;
else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && (img->comps[1].dx == 2))
movie->tk[0].CbCr_subsampling_dx = 2;
else
fprintf(stderr,"Image component sizes are incoherent\n");
if ((img->comps[0].dy == 1) && (img->comps[1].dy == 1) && (img->comps[1].dy == 1))
movie->tk[0].CbCr_subsampling_dy = 1;
else if ((img->comps[0].dy == 1) && (img->comps[1].dy == 2) && (img->comps[1].dy == 2))
movie->tk[0].CbCr_subsampling_dy = 2;
else
fprintf(stderr,"Image component sizes are incoherent\n");
}
movie->tk[0].sample_rate = 25;
movie->tk[0].jp2_struct.numcomps = img->numcomps; // NC
jp2_init_stdjp2(&movie->tk[0].jp2_struct);
movie->tk[0].jp2_struct.w = int_ceildiv(img->x1 - img->x0, img->comps[0].dx);
movie->tk[0].jp2_struct.h = int_ceildiv(img->y1 - img->y0, img->comps[0].dy);
depth_0 = img->comps[0].prec - 1;
sign = img->comps[0].sgnd;
movie->tk[0].jp2_struct.bpc = depth_0 + (sign << 7);
for (i = 1; i < img->numcomps; i++) {
depth = img->comps[i].prec - 1;
sign = img->comps[i].sgnd;
if (depth_0 != depth)
movie->tk[0].jp2_struct.bpc = 255;
}
for (i = 0; i < img->numcomps; i++)
movie->tk[0].jp2_struct.comps[i].bpcc =
img->comps[i].prec - 1 + (img->comps[i].sgnd << 7);
if ((img->numcomps == 1 || img->numcomps == 3)
&& (movie->tk[0].jp2_struct.bpc != 255))
movie->tk[0].jp2_struct.meth = 1;
else
movie->tk[0].jp2_struct.meth = 2;
if (img->numcomps == 1)
movie->tk[0].jp2_struct.enumcs = 17; // Grayscale
else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 1) && (img->comps[1].dx == 1) &&
(img->comps[0].dy == 1) && (img->comps[1].dy == 1) && (img->comps[1].dy == 1))
movie->tk[0].jp2_struct.enumcs = 16; // RGB
else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && (img->comps[1].dx == 2) &&
(img->comps[0].dy == 1) && (img->comps[1].dy == 2) && (img->comps[1].dy == 2))
movie->tk[0].jp2_struct.enumcs = 18; // YUV
else
movie->tk[0].jp2_struct.enumcs = 0; // Unkown profile */
}
int main(int argc, char *argv[]) {
unsigned int snum;
mj2_movie_t movie;
mj2_sample_t *sample;
unsigned char* frame_codestream;
FILE *mj2file, *j2kfile;
char j2kfilename[50];
char *buf;
int offset, mdat_initpos;
j2k_image_t img;
int i;
if (argc != 3) {
printf("Bad syntax: Usage: MJ2_Wrapper source_location mj2_filename\n");
printf("Example: MJ2_Wrapper input/input output.mj2\n");
return 1;
}
mj2file = fopen(argv[2], "wb");
if (!mj2file) {
fprintf(stderr, "failed to open %s for writing\n", argv[2]);
return 1;
}
// Initialing the movie (parameters used in the JP and FTYP boxes
movie.num_htk = 0; // No hint tracks
movie.num_stk = 0; // No sound tracks
movie.num_vtk = 1; // One video track
movie.tk = (mj2_tk_t*) malloc (sizeof(mj2_tk_t)); //Memory allocation for the video track
movie.tk[0].sample = (mj2_sample_t*) malloc (sizeof(mj2_sample_t));
movie.tk[0].chunk = (mj2_chunk_t *) malloc(sizeof(mj2_chunk_t));
movie.tk[0].track_type = 0; // Video track
movie.tk[0].track_ID = 1; // Track ID = 1
movie.brand = MJ2_MJ2; // One brand: MJ2
movie.num_cl = 2; // Two compatible brands: MJ2 and MJ2S
movie.cl = (unsigned int *) malloc(movie.num_cl * sizeof(unsigned int));
movie.cl[0] = MJ2_MJ2;
movie.cl[1] = MJ2_MJ2S;
movie.minversion = 0; // Minimum version: 0
// Writing JP, FTYP and MDAT boxes
buf = (char*) malloc (300 * sizeof(char)); // Assuming that the JP and FTYP
// boxes won't be longer than 300 bytes
cio_init(buf , 300);
mj2_write_jp();
mj2_write_ftyp(&movie);
mdat_initpos = cio_tell();
cio_skip(4);
cio_write(MJ2_MDAT, 4);
fwrite(buf,cio_tell(),1,mj2file);
free(buf);
// Insert each j2k codestream in a JP2C box
snum=0;
offset = 0;
while(1)
{
sample = &movie.tk[0].sample[snum];
sprintf(j2kfilename,"%s_%d.j2k",argv[1],snum);
j2kfile = fopen(j2kfilename, "rb");
if (!j2kfile) {
if (snum==0) { // Could not open a single codestream
fprintf(stderr, "failed to open %s for reading\n",j2kfilename);
return 1;
}
else { // Tried to open a inexistant codestream
fprintf(stdout,"%d frames created\n",snum);
break;
}
}
// Calculating offset for samples and chunks
offset += cio_tell();
sample->offset = offset;
movie.tk[0].chunk[snum].offset = offset; // There will be one sample per chunk
// Calculating sample size
fseek(j2kfile,0,SEEK_END);
sample->sample_size = ftell(j2kfile) + 8; // Sample size is codestream + JP2C box header
fseek(j2kfile,0,SEEK_SET);
// Reading siz marker of j2k image for the first codestream
if (snum==0)
j2k_read_siz_marker(j2kfile, &img);
// Writing JP2C box header
frame_codestream = (unsigned char*) malloc (sample->sample_size+8);
cio_init(frame_codestream, sample->sample_size);
cio_write(sample->sample_size, 4); // Sample size
cio_write(JP2_JP2C, 4); // JP2C
// Writing codestream from J2K file to MJ2 file
fread(frame_codestream+8,sample->sample_size-8,1,j2kfile);
fwrite(frame_codestream,sample->sample_size,1,mj2file);
cio_skip(sample->sample_size-8);
// Ending loop
fclose(j2kfile);
snum++;
movie.tk[0].sample = realloc(movie.tk[0].sample, (snum+1) * sizeof(mj2_sample_t));
movie.tk[0].chunk = realloc(movie.tk[0].chunk, (snum+1) * sizeof(mj2_chunk_t));
free(frame_codestream);
}
// Writing the MDAT box length in header
offset += cio_tell();
buf = (char*) malloc (4 * sizeof(char));
cio_init(buf,4);
cio_write(offset-mdat_initpos,4); // Write MDAT length in MDAT box header
fseek(mj2file,(long)mdat_initpos,SEEK_SET);
fwrite(buf,4,1,mj2file);
fseek(mj2file,0,SEEK_END);
free(buf);
// Setting movie parameters
movie.tk[0].num_samples=snum;
movie.tk[0].num_chunks=snum;
setparams(&movie, &img);
// Writing MOOV box
i=1;
buf = (char*) malloc (10000 * sizeof(char));
cio_init(buf , i*10000);
if (setjmp(j2k_error)) {
i++;
buf = realloc(buf,i*10000* sizeof(char));
cio_init(buf , i*10000);
}
mj2_write_moov(&movie);
fwrite(buf,cio_tell(),1,mj2file);
// Ending program
fclose(mj2file);
free(img.comps);
free(buf);
mj2_memory_free(&movie);
//MEMORY LEAK
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif
//MEM
return 0;
}