Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JP2_RES proposition for implementation #378

Open
gcode-importer opened this issue Aug 20, 2014 · 11 comments
Open

JP2_RES proposition for implementation #378

gcode-importer opened this issue Aug 20, 2014 · 11 comments

Comments

@gcode-importer
Copy link

Originally reported on Google Code with ID 378

I attached a file containing the modification I have done for getting/setting the resolution.

I've got another stupid question:
Can anybody explain me about the reason it is like that:
/**
 * Supported image color spaces
*/
typedef enum COLOR_SPACE {
    OPJ_CLRSPC_UNKNOWN = -1,    /**< not supported by the library */
    OPJ_CLRSPC_UNSPECIFIED = 0, /**< not specified in the codestream */
    OPJ_CLRSPC_SRGB = 1,        /**< sRGB */
    OPJ_CLRSPC_GRAY = 2,        /**< grayscale */
    OPJ_CLRSPC_SYCC = 3,        /**< YUV */
    OPJ_CLRSPC_EYCC = 4,        /**< e-YCC */
    OPJ_CLRSPC_CMYK = 5         /**< CMYK */
} OPJ_COLOR_SPACE;


instead of instead of using the values defined in the norme:

typedef enum COLOR_SPACE {
    OPJ_CLRSPC_UNKNOWN = -1,    /**< not supported by the library */
    OPJ_CLRSPC_UNSPECIFIED = 0, /**< not specified in the codestream */
    OPJ_CLRSPC_CMYK = 12,
    OPJ_CLRSPC_YCCK = 13,
    OPJ_CLRSPC_LAB = 14,  
    OPJ_CLRSPC_SRGB = 16,       /**< sRGB */
    OPJ_CLRSPC_GRAY = 17,       /**< grayscale */
    OPJ_CLRSPC_SYCC = 18            /**< YUV */
    OPJ_CLRSPC_EYCC = 24,        /**< e-YCC */
} OPJ_COLOR_SPACE;

Thanks .

Mika

Reported by leguilc on 2014-08-20 15:25:33


- _Attachment: [patch_res.diff](https://storage.googleapis.com/google-code-attachments/openjpeg/issue-378/comment-0/patch_res.diff)_
@gcode-importer
Copy link
Author

The norm ISO/IEC 15444-1 does define values for ENUMCS.

winfried

Reported by szukw000 on 2014-08-25 16:07:19

@gcode-importer
Copy link
Author

Reported by mayeut on 2014-10-09 18:11:01

  • Labels added: Type-Enhancement
  • Labels removed: Type-Defect

@sebras
Copy link
Contributor

sebras commented Jun 26, 2016

I'm not sure if writing +1, 👍 or just cheering you guys on is appropriate, but I'd like to see this patch (or some version of it) be added to master. Having the possiblity to determine the resolution of an image would be really nice. :) If I can help you in any way, let me know.

@jerem
Copy link

jerem commented Nov 14, 2017

Here is a copy the original patch:

diff --git a/src/lib/openjp2/jp2.c b/src/lib/openjp2/jp2.c
index 5c88c4d..f3d49c0 100644
--- a/src/lib/openjp2/jp2.c
+++ b/src/lib/openjp2/jp2.c
@@ -118,6 +118,16 @@ static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color);
 */
 static OPJ_BYTE * opj_jp2_write_colr(   opj_jp2_t *jp2,
 									    OPJ_UINT32 * p_nb_bytes_written );
+/**
+ * Writes the Colour Specification box.
+ *
+ * @param jp2					jpeg2000 file codec.
+ * @param p_nb_bytes_written	pointer to store the nb of bytes written by the function.
+ *
+ * @return	the data being copied.
+*/
+static OPJ_BYTE * opj_jp2_write_res(   opj_jp2_t *jp2,
+									    OPJ_UINT32 * p_nb_bytes_written );
 
 /**
  * Writes a FTYP box - File type box
@@ -294,6 +304,21 @@ static OPJ_BOOL opj_jp2_read_colr(  opj_jp2_t *jp2,
                                     OPJ_UINT32 p_colr_header_size,
                                     opj_event_mgr_t * p_manager );
 
+/**
+ * Reads the Color Specification box.
+ *
+ * @param	p_colr_header_data			pointer to actual data (already read from file)
+ * @param	jp2							the jpeg2000 file codec.
+ * @param	p_colr_header_size			the size of the color header
+ * @param	p_manager					the user event manager.
+ *
+ * @return	true if the bpc header is valid, fale else.
+*/
+static OPJ_BOOL opj_jp2_read_res(  opj_jp2_t *jp2,
+                                   OPJ_BYTE * p_colr_header_data,
+                                   OPJ_UINT32 p_colr_header_size,
+                                   opj_event_mgr_t * p_manager );
+
 /*@}*/
 
 /*@}*/
@@ -397,6 +422,7 @@ const opj_jp2_header_handler_t jp2_img_header [] =
 {
 	{JP2_IHDR,opj_jp2_read_ihdr},
 	{JP2_COLR,opj_jp2_read_colr},
+	{JP2_RES,opj_jp2_read_res},
 	{JP2_BPCC,opj_jp2_read_bpcc},
 	{JP2_PCLR,opj_jp2_read_pclr},
 	{JP2_CMAP,opj_jp2_read_cmap},
@@ -749,6 +775,106 @@ OPJ_BYTE * opj_jp2_write_colr(  opj_jp2_t *jp2,
 	return l_colr_data;
 }
 
+void opj_res (OPJ_FLOAT64 res, OPJ_UINT32 * rcn, OPJ_UINT32 *rcd) {
+    const int NUMFRACS = 30;
+    int i;
+
+    OPJ_UINT32 numerator [NUMFRACS];
+    OPJ_UINT32 denominator [NUMFRACS];
+    
+    OPJ_FLOAT64 d=0, d2=0, d3, d4 = -1;
+    OPJ_UINT32   maxNumerator, L2;
+    (*rcn) = (int)(res / 100);
+    (*rcd) = 1;
+    d = d2 = (res / 100);
+    
+    maxNumerator = 0x0ffff;
+
+    numerator[0]=0; denominator[0]=1;
+    numerator[1]=1; denominator[1]=0;
+
+    for(i=2; i<NUMFRACS; ++i)
+    {
+      L2 = (OPJ_UINT32)(d2 + 0.5);
+      numerator[i]= L2 * numerator[i-1] + numerator[i-2];
+      denominator[i]= L2 *denominator[i-1] + denominator[i-2];
+      
+      d3 = ((OPJ_FLOAT64)(numerator[i])) / ((OPJ_FLOAT64)(denominator[i]));
+      
+      if(d3==d4) break; 
+      
+      if(abs (numerator[i]) > maxNumerator) break; 
+
+      (*rcn) = abs (numerator[i]);
+      (*rcd) = abs (denominator[i]);
+
+      if(d3==d) break; 
+
+      d4=d3;
+      
+      d2 = 1/(d2-L2);
+    }
+}
+
+OPJ_BYTE * opj_jp2_write_res(  opj_jp2_t *jp2,
+							   OPJ_UINT32 * p_nb_bytes_written)
+{
+	OPJ_UINT32 l_res_size = 26, l_resc_size = 18;
+	OPJ_BYTE * l_res_data, * l_current_res_ptr;
+  
+    OPJ_UINT32 rcn, rcd, rce = 2;
+	/* preconditions */
+	assert(jp2 != 00);
+	assert(p_nb_bytes_written != 00);
+    
+	l_res_data = (OPJ_BYTE *) opj_malloc(l_res_size);
+	if (l_res_data == 00) {
+		return 00;
+	}
+
+	memset(l_res_data,0,l_res_size);
+	
+	l_current_res_ptr = l_res_data;
+
+	opj_write_bytes(l_current_res_ptr,l_res_size,4);				/* write box size */
+	l_current_res_ptr += 4;
+	
+	opj_write_bytes(l_current_res_ptr,JP2_RES,4);					/* RES */
+	l_current_res_ptr += 4;
+
+	opj_write_bytes(l_current_res_ptr,l_resc_size,4);					/* BPCC */
+	l_current_res_ptr += 4;
+    
+	opj_write_bytes(l_current_res_ptr,JP2_RESC,4);					/* BPCC */
+	l_current_res_ptr += 4;
+
+    opj_res (jp2->resdv, &rcn, &rcd);
+    
+	opj_write_bytes(l_current_res_ptr, rcn, 2);				/* VRcN */
+	l_current_res_ptr += 2;
+
+	opj_write_bytes(l_current_res_ptr, rcn, 2);				/* VRcD */
+	l_current_res_ptr += 2;
+    
+    opj_res (jp2->resdh, &rcn, &rcd);
+
+	opj_write_bytes(l_current_res_ptr, rcn, 2);				/* HRcN */
+	l_current_res_ptr += 2;
+
+	opj_write_bytes(l_current_res_ptr, rcn, 2);				/* HRcD */
+	l_current_res_ptr += 2;
+
+	opj_write_bytes(l_current_res_ptr, rce, 1);				/* VRcE */
+	l_current_res_ptr += 1;
+
+	opj_write_bytes(l_current_res_ptr, rce, 1);				/* HRcE */
+	l_current_res_ptr += 1;
+    
+	*p_nb_bytes_written = l_res_size;
+	
+	return l_res_data;
+}
+
 void opj_jp2_free_pclr(opj_jp2_color_t *color)
 {
     opj_free(color->jp2_pclr->channel_sign);
@@ -1282,6 +1408,57 @@ OPJ_BOOL opj_jp2_read_colr( opj_jp2_t *jp2,
     return OPJ_TRUE;
 }
 
+OPJ_BOOL opj_jp2_read_res( opj_jp2_t *jp2,
+                           OPJ_BYTE * p_res_header_data,
+                           OPJ_UINT32 p_res_header_size,
+                           opj_event_mgr_t * p_manager) 
+{
+  OPJ_UINT32 size, type;	
+  OPJ_UINT32 vrcn, vrcd, hrcn, hrcd, vrce, hrce;
+  
+  /* preconditions */
+  assert(jp2 != 00);
+  assert(p_res_header_data != 00);
+  assert(p_manager != 00);
+        
+  while (p_res_header_size >= 18) {
+    opj_read_bytes(p_res_header_data,&size ,4);
+    p_res_header_data += 4;
+    
+    opj_read_bytes(p_res_header_data,&type ,4);
+    p_res_header_data += 4;
+    
+    opj_read_bytes(p_res_header_data,&vrcn,2);
+    p_res_header_data += 2;
+    
+    opj_read_bytes(p_res_header_data,&vrcd,2);
+    p_res_header_data += 2;
+    
+    opj_read_bytes(p_res_header_data,&hrcn,2);
+    p_res_header_data += 2;
+    
+    opj_read_bytes(p_res_header_data,&hrcd,2);
+    p_res_header_data += 2;
+    
+    opj_read_bytes(p_res_header_data,&vrce,1);
+    ++p_res_header_data;
+    
+    opj_read_bytes(p_res_header_data,&hrce,1);
+    ++p_res_header_data;
+    
+    jp2->resdh = (OPJ_FLOAT64)(hrcn) / (OPJ_FLOAT64)(hrcd) * pow(10, hrce);
+    jp2->resdv = (OPJ_FLOAT64)(vrcn) / (OPJ_FLOAT64)(vrcd) * pow(10, vrce);
+    
+    if ( JP2_RESD == type)
+      return OPJ_TRUE;
+      
+    p_res_header_size -= size;
+  }
+    
+  return OPJ_TRUE;
+}/* jp2_read_res() */
+
+
 OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
                         opj_stream_private_t *p_stream,
                         opj_image_t* p_image,
@@ -1341,7 +1518,7 @@ OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
                             opj_event_mgr_t * p_manager
                             )
 {
-	opj_jp2_img_header_writer_handler_t l_writers [3];
+	opj_jp2_img_header_writer_handler_t l_writers [4];
 	opj_jp2_img_header_writer_handler_t * l_current_writer;
 
 	OPJ_INT32 i, l_nb_pass;
@@ -1359,16 +1536,19 @@ OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
 
 	memset(l_writers,0,sizeof(l_writers));
 
+
 	if (jp2->bpc == 255) {
-		l_nb_pass = 3;
+		l_nb_pass = 4;
 		l_writers[0].handler = opj_jp2_write_ihdr;
 		l_writers[1].handler = opj_jp2_write_bpcc;
 		l_writers[2].handler = opj_jp2_write_colr;
+		l_writers[3].handler = opj_jp2_write_res;
 	}
 	else {
-		l_nb_pass = 2;
+		l_nb_pass = 3;
 		l_writers[0].handler = opj_jp2_write_ihdr;
 		l_writers[1].handler = opj_jp2_write_colr;
+        l_writers[2].handler = opj_jp2_write_res;
 	}
 	
 	/* write box header */
diff --git a/src/lib/openjp2/jp2.h b/src/lib/openjp2/jp2.h
index c11d2f3..6b43008 100644
--- a/src/lib/openjp2/jp2.h
+++ b/src/lib/openjp2/jp2.h
@@ -60,6 +60,9 @@
 #define     JP2_BPCC 0x62706363    /**< Bits per component box */
 #define     JP2_JP2  0x6a703220    /**< File type fields */
 
+#define     JP2_RES  0x72657320    /**< Resolution box (super-box) */
+#define     JP2_RESC 0x72657363    /**< File type fields */
+#define     JP2_RESD 0x72657364    /**< File type fields */
 /* For the future */
 /* #define JP2_RES 0x72657320 */  /**< Resolution box (super-box) */
 /* #define JP2_JP2I 0x6a703269 */  /**< Intellectual property box */
@@ -181,6 +184,8 @@ typedef struct opj_jp2
   OPJ_UINT32 numcl;
   OPJ_UINT32 *cl;
   opj_jp2_comps_t *comps;
+  OPJ_FLOAT64 resdh;
+  OPJ_FLOAT64 resdv;
   /* FIXME: The following two variables are used to save offset
     as we write out a JP2 file to disk. This mecanism is not flexible
     as codec writers will need to extand those fields as new part
diff --git a/src/lib/openjp2/openjpeg.h b/src/lib/openjp2/openjpeg.h
index e4b410e..840e0e8 100644
--- a/src/lib/openjp2/openjpeg.h
+++ b/src/lib/openjp2/openjpeg.h
@@ -701,6 +701,10 @@ typedef struct opj_image {
 	OPJ_BYTE *icc_profile_buf;
 	/** size of ICC profile */
 	OPJ_UINT32 icc_profile_len;
+    /** resolution display vertical */
+    OPJ_FLOAT64 resdv;
+    /** resolution display horizontal */
+    OPJ_FLOAT64 resdh;
 } opj_image_t;
 
 

@jbaiter
Copy link

jbaiter commented Jun 14, 2019

This is also included in the grok fork.
What's the stance on backporting features from grok?

I'd really like so see support for JP2_RES and JP2_COLR in the mainline library. Both features are implemented in grok, and from what I can tell backporting them shouldn't be all too difficult.

If it's okay, I'd love to give this a try.

@rouault
Copy link
Collaborator

rouault commented Jun 14, 2019

If it's okay, I'd love to give this a try.

This isn't OK from a license point of view. Grok uses a more restrictive license, and its code cannot legally be backported to openjpeg.

@jbaiter
Copy link

jbaiter commented Jun 14, 2019

Thanks for getting back so quickly, I wasn't aware of that!

@jbaiter
Copy link

jbaiter commented Jun 14, 2019

Basing a PR on @leguilc's code would be fine, though, right? Given that he submitted his patch for the openjpeg project, can we safely assume that the copyright situation is clear?

@rouault
Copy link
Collaborator

rouault commented Jun 14, 2019

can we safely assume that the copyright situation is clear?

yes

@leguilc
Copy link

leguilc commented Jun 15, 2019

How time flies!!
I completely forgotten about writing this code/patch ....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants
@jerem @detonin @jbaiter @sebras @rouault @leguilc @gcode-importer and others